diff --git a/src/float/add.rs b/src/float/add.rs index 7707850..63baf00 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -186,16 +186,13 @@ add!(__adddf3: f64); #[cfg(test)] mod tests { use core::{f32, f64}; + use core::fmt; use float::Float; use qc::{U32, U64}; - // NOTE The tests below have special handing for NaN values. - // Because NaN != NaN, the floating-point representations must be used - // Because there are many diffferent values of NaN, and the implementation - // doesn't care about calculating the 'correct' one, if both values are NaN - // the values are considered equivalent. - + // TODO: Move this to F32/F64 in qc.rs + #[derive(Copy, Clone)] struct FRepr(F); impl PartialEq for FRepr { @@ -212,6 +209,12 @@ mod tests { } } + impl fmt::Debug for FRepr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } + } + // TODO: Add F32/F64 to qc so that they print the right values (at the very least) check! { fn __addsf3(f: extern fn(f32, f32) -> f32, diff --git a/src/qc.rs b/src/qc.rs index 1450a4e..f7696b5 100644 --- a/src/qc.rs +++ b/src/qc.rs @@ -195,7 +195,7 @@ macro_rules! check { } )* - mod _compiler_rt { + mod _test { use qc::*; use std::mem; use quickcheck::TestResult; @@ -207,16 +207,37 @@ macro_rules! check { let my_answer = super::$name(super::super::$name, $($arg),*); let compiler_rt_fn = ::compiler_rt::get(stringify!($name)); - unsafe { - let compiler_rt_answer = - super::$name(mem::transmute(compiler_rt_fn), - $($arg),*); - match (my_answer, compiler_rt_answer) { - (None, _) | (_, None) => TestResult::discard(), - (Some(a), Some(b)) => { - TestResult::from_bool(a == b) - } - } + let compiler_rt_answer = unsafe { + super::$name(mem::transmute(compiler_rt_fn), + $($arg),*) + }; + let gcc_s_answer = + match ::gcc_s::get(stringify!($name)) { + Some(f) => unsafe { + Some(super::$name(mem::transmute(f), + $($arg),*)) + }, + None => None, + }; + + let print_values = || { + print!("{} - Args: ", stringify!($name)); + $(print!("{:?} ", $arg);)* + print!("\n"); + println!(" rustc-builtins: {:?}", my_answer); + println!(" compiler_rt: {:?}", compiler_rt_answer); + println!(" gcc_s: {:?}", gcc_s_answer); + }; + + if my_answer != compiler_rt_answer { + print_values(); + TestResult::from_bool(false) + } else if gcc_s_answer.is_some() && + my_answer != gcc_s_answer.unwrap() { + print_values(); + TestResult::from_bool(false) + } else { + TestResult::from_bool(true) } } @@ -224,42 +245,5 @@ macro_rules! check { } )* } - - mod _gcc_s { - use qc::*; - use std::mem; - use quickcheck::TestResult; - - $( - #[test] - fn $name() { - fn my_check($($arg:$t),*) -> TestResult { - let my_answer = super::$name(super::super::$name, - $($arg),*); - let gcc_s_fn = ::gcc_s::get(stringify!($name)).unwrap(); - unsafe { - let gcc_s_answer = - super::$name(mem::transmute(gcc_s_fn), - $($arg),*); - match (my_answer, gcc_s_answer) { - (None, _) | (_, None) => TestResult::discard(), - (Some(a), Some(b)) => { - TestResult::from_bool(a == b) - } - } - } - } - - // If it's not in libgcc, or we couldn't find libgcc, then - // just ignore this. We should have tests through - // compiler-rt in any case - if ::gcc_s::get(stringify!($name)).is_none() { - return - } - - ::quickcheck::quickcheck(my_check as fn($($t),*) -> TestResult) - } - )* - } ) }