Add an integration test that verifies a list of cases
We need someplace to collect known failures, previous regressions, edge cases that are difficult to construct from generics, and similar. Introduce this here.
This commit is contained in:
parent
f070e65e4f
commit
4bf116f146
6 changed files with 750 additions and 5 deletions
|
|
@ -1,5 +1,6 @@
|
|||
//! Different generators that can create random or systematic bit patterns.
|
||||
|
||||
pub mod case_list;
|
||||
pub mod edge_cases;
|
||||
pub mod random;
|
||||
pub mod spaced;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,686 @@
|
|||
//! Test cases to verify specific values.
|
||||
//!
|
||||
//! Each routine can have a set of inputs and, optinoally, outputs. If an output is provided, it
|
||||
//! will be used to check against. If only inputs are provided, the case will be checked against
|
||||
//! a basis.
|
||||
//!
|
||||
//! This is useful for adding regression tests or expected failures.
|
||||
|
||||
use crate::{CheckBasis, CheckCtx, GeneratorKind, MathOp, op};
|
||||
|
||||
pub struct TestCase<Op: MathOp> {
|
||||
pub input: Op::RustArgs,
|
||||
pub output: Option<Op::RustRet>,
|
||||
}
|
||||
|
||||
impl<Op: MathOp> TestCase<Op> {
|
||||
#[expect(dead_code)]
|
||||
fn append_inputs(v: &mut Vec<Self>, l: &[Op::RustArgs]) {
|
||||
v.extend(l.iter().copied().map(|input| Self { input, output: None }));
|
||||
}
|
||||
|
||||
fn append_pairs(v: &mut Vec<Self>, l: &[(Op::RustArgs, Option<Op::RustRet>)])
|
||||
where
|
||||
Op::RustRet: Copy,
|
||||
{
|
||||
v.extend(l.iter().copied().map(|(input, output)| Self { input, output }));
|
||||
}
|
||||
}
|
||||
|
||||
fn acos_cases() -> Vec<TestCase<op::acos::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn acosf_cases() -> Vec<TestCase<op::acosf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn acosh_cases() -> Vec<TestCase<op::acosh::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn acoshf_cases() -> Vec<TestCase<op::acoshf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn asin_cases() -> Vec<TestCase<op::asin::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn asinf_cases() -> Vec<TestCase<op::asinf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn asinh_cases() -> Vec<TestCase<op::asinh::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn asinhf_cases() -> Vec<TestCase<op::asinhf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn atan_cases() -> Vec<TestCase<op::atan::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn atan2_cases() -> Vec<TestCase<op::atan2::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn atan2f_cases() -> Vec<TestCase<op::atan2f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn atanf_cases() -> Vec<TestCase<op::atanf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn atanh_cases() -> Vec<TestCase<op::atanh::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn atanhf_cases() -> Vec<TestCase<op::atanhf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn cbrt_cases() -> Vec<TestCase<op::cbrt::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn cbrtf_cases() -> Vec<TestCase<op::cbrtf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ceil_cases() -> Vec<TestCase<op::ceil::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ceilf_cases() -> Vec<TestCase<op::ceilf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn ceilf128_cases() -> Vec<TestCase<op::ceilf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn ceilf16_cases() -> Vec<TestCase<op::ceilf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn copysign_cases() -> Vec<TestCase<op::copysign::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn copysignf_cases() -> Vec<TestCase<op::copysignf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn copysignf128_cases() -> Vec<TestCase<op::copysignf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn copysignf16_cases() -> Vec<TestCase<op::copysignf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn cos_cases() -> Vec<TestCase<op::cos::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn cosf_cases() -> Vec<TestCase<op::cosf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn cosh_cases() -> Vec<TestCase<op::cosh::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn coshf_cases() -> Vec<TestCase<op::coshf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn erf_cases() -> Vec<TestCase<op::erf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn erfc_cases() -> Vec<TestCase<op::erfc::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn erfcf_cases() -> Vec<TestCase<op::erfcf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn erff_cases() -> Vec<TestCase<op::erff::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn exp_cases() -> Vec<TestCase<op::exp::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn exp10_cases() -> Vec<TestCase<op::exp10::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn exp10f_cases() -> Vec<TestCase<op::exp10f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn exp2_cases() -> Vec<TestCase<op::exp2::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn exp2f_cases() -> Vec<TestCase<op::exp2f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn expf_cases() -> Vec<TestCase<op::expf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn expm1_cases() -> Vec<TestCase<op::expm1::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn expm1f_cases() -> Vec<TestCase<op::expm1f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fabs_cases() -> Vec<TestCase<op::fabs::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fabsf_cases() -> Vec<TestCase<op::fabsf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn fabsf128_cases() -> Vec<TestCase<op::fabsf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn fabsf16_cases() -> Vec<TestCase<op::fabsf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fdim_cases() -> Vec<TestCase<op::fdim::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fdimf_cases() -> Vec<TestCase<op::fdimf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn fdimf128_cases() -> Vec<TestCase<op::fdimf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn fdimf16_cases() -> Vec<TestCase<op::fdimf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn floor_cases() -> Vec<TestCase<op::floor::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn floorf_cases() -> Vec<TestCase<op::floorf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn floorf128_cases() -> Vec<TestCase<op::floorf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn floorf16_cases() -> Vec<TestCase<op::floorf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fma_cases() -> Vec<TestCase<op::fma::Routine>> {
|
||||
let mut v = vec![];
|
||||
TestCase::append_pairs(
|
||||
&mut v,
|
||||
&[
|
||||
// Previously failure with incorrect sign
|
||||
((5e-324, -5e-324, 0.0), Some(-0.0)),
|
||||
],
|
||||
);
|
||||
v
|
||||
}
|
||||
|
||||
fn fmaf_cases() -> Vec<TestCase<op::fmaf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fmax_cases() -> Vec<TestCase<op::fmax::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fmaxf_cases() -> Vec<TestCase<op::fmaxf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn fmaxf128_cases() -> Vec<TestCase<op::fmaxf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn fmaxf16_cases() -> Vec<TestCase<op::fmaxf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fmin_cases() -> Vec<TestCase<op::fmin::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fminf_cases() -> Vec<TestCase<op::fminf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn fminf128_cases() -> Vec<TestCase<op::fminf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn fminf16_cases() -> Vec<TestCase<op::fminf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fmod_cases() -> Vec<TestCase<op::fmod::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn fmodf_cases() -> Vec<TestCase<op::fmodf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn fmodf128_cases() -> Vec<TestCase<op::fmodf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn fmodf16_cases() -> Vec<TestCase<op::fmodf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn frexp_cases() -> Vec<TestCase<op::frexp::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn frexpf_cases() -> Vec<TestCase<op::frexpf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn hypot_cases() -> Vec<TestCase<op::hypot::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn hypotf_cases() -> Vec<TestCase<op::hypotf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ilogb_cases() -> Vec<TestCase<op::ilogb::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ilogbf_cases() -> Vec<TestCase<op::ilogbf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn j0_cases() -> Vec<TestCase<op::j0::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn j0f_cases() -> Vec<TestCase<op::j0f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn j1_cases() -> Vec<TestCase<op::j1::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn j1f_cases() -> Vec<TestCase<op::j1f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn jn_cases() -> Vec<TestCase<op::jn::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn jnf_cases() -> Vec<TestCase<op::jnf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ldexp_cases() -> Vec<TestCase<op::ldexp::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ldexpf_cases() -> Vec<TestCase<op::ldexpf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn ldexpf128_cases() -> Vec<TestCase<op::ldexpf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn ldexpf16_cases() -> Vec<TestCase<op::ldexpf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn lgamma_cases() -> Vec<TestCase<op::lgamma::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn lgamma_r_cases() -> Vec<TestCase<op::lgamma_r::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn lgammaf_cases() -> Vec<TestCase<op::lgammaf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn lgammaf_r_cases() -> Vec<TestCase<op::lgammaf_r::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log_cases() -> Vec<TestCase<op::log::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log10_cases() -> Vec<TestCase<op::log10::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log10f_cases() -> Vec<TestCase<op::log10f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log1p_cases() -> Vec<TestCase<op::log1p::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log1pf_cases() -> Vec<TestCase<op::log1pf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log2_cases() -> Vec<TestCase<op::log2::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn log2f_cases() -> Vec<TestCase<op::log2f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn logf_cases() -> Vec<TestCase<op::logf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn modf_cases() -> Vec<TestCase<op::modf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn modff_cases() -> Vec<TestCase<op::modff::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn nextafter_cases() -> Vec<TestCase<op::nextafter::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn nextafterf_cases() -> Vec<TestCase<op::nextafterf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn pow_cases() -> Vec<TestCase<op::pow::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn powf_cases() -> Vec<TestCase<op::powf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn remainder_cases() -> Vec<TestCase<op::remainder::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn remainderf_cases() -> Vec<TestCase<op::remainderf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn remquo_cases() -> Vec<TestCase<op::remquo::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn remquof_cases() -> Vec<TestCase<op::remquof::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn rint_cases() -> Vec<TestCase<op::rint::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn rintf_cases() -> Vec<TestCase<op::rintf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn rintf128_cases() -> Vec<TestCase<op::rintf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn rintf16_cases() -> Vec<TestCase<op::rintf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn round_cases() -> Vec<TestCase<op::round::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn roundf_cases() -> Vec<TestCase<op::roundf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn roundf128_cases() -> Vec<TestCase<op::roundf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn roundf16_cases() -> Vec<TestCase<op::roundf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn scalbn_cases() -> Vec<TestCase<op::scalbn::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn scalbnf_cases() -> Vec<TestCase<op::scalbnf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn scalbnf128_cases() -> Vec<TestCase<op::scalbnf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn scalbnf16_cases() -> Vec<TestCase<op::scalbnf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sin_cases() -> Vec<TestCase<op::sin::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sincos_cases() -> Vec<TestCase<op::sincos::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sincosf_cases() -> Vec<TestCase<op::sincosf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sinf_cases() -> Vec<TestCase<op::sinf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sinh_cases() -> Vec<TestCase<op::sinh::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sinhf_cases() -> Vec<TestCase<op::sinhf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sqrt_cases() -> Vec<TestCase<op::sqrt::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn sqrtf_cases() -> Vec<TestCase<op::sqrtf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn sqrtf128_cases() -> Vec<TestCase<op::sqrtf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn sqrtf16_cases() -> Vec<TestCase<op::sqrtf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn tan_cases() -> Vec<TestCase<op::tan::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn tanf_cases() -> Vec<TestCase<op::tanf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn tanh_cases() -> Vec<TestCase<op::tanh::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn tanhf_cases() -> Vec<TestCase<op::tanhf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn tgamma_cases() -> Vec<TestCase<op::tgamma::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn tgammaf_cases() -> Vec<TestCase<op::tgammaf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn trunc_cases() -> Vec<TestCase<op::trunc::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn truncf_cases() -> Vec<TestCase<op::truncf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f128_enabled)]
|
||||
fn truncf128_cases() -> Vec<TestCase<op::truncf128::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(f16_enabled)]
|
||||
fn truncf16_cases() -> Vec<TestCase<op::truncf16::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn y0_cases() -> Vec<TestCase<op::y0::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn y0f_cases() -> Vec<TestCase<op::y0f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn y1_cases() -> Vec<TestCase<op::y1::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn y1f_cases() -> Vec<TestCase<op::y1f::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn yn_cases() -> Vec<TestCase<op::yn::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn ynf_cases() -> Vec<TestCase<op::ynf::Routine>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub trait CaseListInput: MathOp + Sized {
|
||||
fn get_cases() -> Vec<TestCase<Self>>;
|
||||
}
|
||||
|
||||
macro_rules! impl_case_list {
|
||||
(
|
||||
fn_name: $fn_name:ident,
|
||||
attrs: [$($attr:meta),*],
|
||||
) => {
|
||||
paste::paste! {
|
||||
$(#[$attr])*
|
||||
impl CaseListInput for crate::op::$fn_name::Routine {
|
||||
fn get_cases() -> Vec<TestCase<Self>> {
|
||||
[< $fn_name _cases >]()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
libm_macros::for_each_function! {
|
||||
callback: impl_case_list,
|
||||
}
|
||||
|
||||
/// This is the test generator for standalone tests, i.e. those with no basis. For this, it
|
||||
/// only extracts tests with a known output.
|
||||
pub fn get_test_cases_standalone<Op>(
|
||||
ctx: &CheckCtx,
|
||||
) -> impl Iterator<Item = (Op::RustArgs, Op::RustRet)> + use<'_, Op>
|
||||
where
|
||||
Op: MathOp + CaseListInput,
|
||||
{
|
||||
assert_eq!(ctx.basis, CheckBasis::None);
|
||||
assert_eq!(ctx.gen_kind, GeneratorKind::List);
|
||||
Op::get_cases().into_iter().filter_map(|x| x.output.map(|o| (x.input, o)))
|
||||
}
|
||||
|
||||
/// Opposite of the above; extract only test cases that don't have a known output, to be run
|
||||
/// against a basis.
|
||||
pub fn get_test_cases_basis<Op>(
|
||||
ctx: &CheckCtx,
|
||||
) -> (impl Iterator<Item = Op::RustArgs> + use<'_, Op>, u64)
|
||||
where
|
||||
Op: MathOp + CaseListInput,
|
||||
{
|
||||
assert_ne!(ctx.basis, CheckBasis::None);
|
||||
assert_eq!(ctx.gen_kind, GeneratorKind::List);
|
||||
|
||||
let cases = Op::get_cases();
|
||||
let count: u64 = cases.iter().filter(|case| case.output.is_none()).count().try_into().unwrap();
|
||||
|
||||
(cases.into_iter().filter(|x| x.output.is_none()).map(|x| x.input), count)
|
||||
}
|
||||
|
|
@ -102,6 +102,7 @@ pub enum GeneratorKind {
|
|||
Extensive,
|
||||
QuickSpaced,
|
||||
Random,
|
||||
List,
|
||||
}
|
||||
|
||||
/// A list of all functions that should get extensive tests.
|
||||
|
|
@ -219,8 +220,8 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 {
|
|||
GeneratorKind::QuickSpaced => domain_iter_count,
|
||||
GeneratorKind::Random => random_iter_count,
|
||||
GeneratorKind::Extensive => extensive_max_iterations(),
|
||||
GeneratorKind::EdgeCases => {
|
||||
unimplemented!("edge case tests shoudn't need `iteration_count`")
|
||||
GeneratorKind::EdgeCases | GeneratorKind::List => {
|
||||
unimplemented!("shoudn't need `iteration_count` for {:?}", ctx.gen_kind)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -269,7 +270,7 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 {
|
|||
GeneratorKind::Random => {
|
||||
format!(" using `{SEED_ENV}={}`", str::from_utf8(SEED.as_slice()).unwrap())
|
||||
}
|
||||
GeneratorKind::EdgeCases => unreachable!(),
|
||||
GeneratorKind::EdgeCases | GeneratorKind::List => unimplemented!(),
|
||||
};
|
||||
|
||||
test_log(&format!(
|
||||
|
|
@ -310,6 +311,7 @@ pub fn int_range(ctx: &CheckCtx, argnum: usize) -> RangeInclusive<i32> {
|
|||
GeneratorKind::Extensive => extensive_range,
|
||||
GeneratorKind::QuickSpaced | GeneratorKind::Random => non_extensive_range,
|
||||
GeneratorKind::EdgeCases => extensive_range,
|
||||
GeneratorKind::List => unimplemented!("shoudn't need range for {:?}", ctx.gen_kind),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
// There are some targets we can't build musl for
|
||||
#![cfg(feature = "build-musl")]
|
||||
|
||||
use libm_test::gen::{edge_cases, random, spaced};
|
||||
use libm_test::gen::{case_list, edge_cases, random, spaced};
|
||||
use libm_test::{CheckBasis, CheckCtx, CheckOutput, GeneratorKind, MathOp, TupleCall};
|
||||
|
||||
const BASIS: CheckBasis = CheckBasis::Musl;
|
||||
|
|
@ -34,6 +34,15 @@ macro_rules! musl_tests {
|
|||
attrs: [$($attr:meta),*],
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[test]
|
||||
$(#[$attr])*
|
||||
fn [< musl_case_list_ $fn_name >]() {
|
||||
type Op = libm_test::op::$fn_name::Routine;
|
||||
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::List);
|
||||
let cases = case_list::get_test_cases_basis::<Op>(&ctx).0;
|
||||
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
$(#[$attr])*
|
||||
fn [< musl_random_ $fn_name >]() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#![cfg(feature = "build-mpfr")]
|
||||
|
||||
use libm_test::gen::{edge_cases, random, spaced};
|
||||
use libm_test::gen::{case_list, edge_cases, random, spaced};
|
||||
use libm_test::mpfloat::MpOp;
|
||||
use libm_test::{CheckBasis, CheckCtx, CheckOutput, GeneratorKind, MathOp, TupleCall};
|
||||
|
||||
|
|
@ -24,6 +24,15 @@ macro_rules! mp_tests {
|
|||
attrs: [$($attr:meta),*],
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[test]
|
||||
$(#[$attr])*
|
||||
fn [< mp_case_list_ $fn_name >]() {
|
||||
type Op = libm_test::op::$fn_name::Routine;
|
||||
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::List);
|
||||
let cases = case_list::get_test_cases_basis::<Op>(&ctx).0;
|
||||
mp_runner::<Op>(&ctx, cases);
|
||||
}
|
||||
|
||||
#[test]
|
||||
$(#[$attr])*
|
||||
fn [< mp_random_ $fn_name >]() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
//! Test cases that have both an input and an output, so do not require a basis.
|
||||
|
||||
use libm_test::gen::case_list;
|
||||
use libm_test::{CheckBasis, CheckCtx, CheckOutput, GeneratorKind, MathOp, TupleCall};
|
||||
|
||||
const BASIS: CheckBasis = CheckBasis::None;
|
||||
|
||||
fn standalone_runner<Op: MathOp>(
|
||||
ctx: &CheckCtx,
|
||||
cases: impl Iterator<Item = (Op::RustArgs, Op::RustRet)>,
|
||||
) {
|
||||
for (input, expected) in cases {
|
||||
let crate_res = input.call(Op::ROUTINE);
|
||||
crate_res.validate(expected, input, ctx).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! mp_tests {
|
||||
(
|
||||
fn_name: $fn_name:ident,
|
||||
attrs: [$($attr:meta),*],
|
||||
) => {
|
||||
paste::paste! {
|
||||
#[test]
|
||||
$(#[$attr])*
|
||||
fn [< standalone_ $fn_name >]() {
|
||||
type Op = libm_test::op::$fn_name::Routine;
|
||||
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::List);
|
||||
let cases = case_list::get_test_cases_standalone::<Op>(&ctx);
|
||||
standalone_runner::<Op>(&ctx, cases);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
libm_macros::for_each_function! {
|
||||
callback: mp_tests,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue