From 770fcbf8c13871620b689fcadec36f5936c5fe5a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:11:58 +0000 Subject: Move test-float-parse to the 2024 edition --- src/etc/test-float-parse/Cargo.toml | 2 +- src/etc/test-float-parse/src/gen/exhaustive.rs | 42 --------- src/etc/test-float-parse/src/gen/exponents.rs | 95 ------------------- src/etc/test-float-parse/src/gen/fuzz.rs | 87 ----------------- src/etc/test-float-parse/src/gen/integers.rs | 104 --------------------- src/etc/test-float-parse/src/gen/long_fractions.rs | 58 ------------ src/etc/test-float-parse/src/gen/many_digits.rs | 84 ----------------- src/etc/test-float-parse/src/gen/sparse.rs | 99 -------------------- src/etc/test-float-parse/src/gen/spot_checks.rs | 101 -------------------- src/etc/test-float-parse/src/gen/subnorm.rs | 103 -------------------- src/etc/test-float-parse/src/gen_/exhaustive.rs | 42 +++++++++ src/etc/test-float-parse/src/gen_/exponents.rs | 95 +++++++++++++++++++ src/etc/test-float-parse/src/gen_/fuzz.rs | 87 +++++++++++++++++ src/etc/test-float-parse/src/gen_/integers.rs | 104 +++++++++++++++++++++ .../test-float-parse/src/gen_/long_fractions.rs | 58 ++++++++++++ src/etc/test-float-parse/src/gen_/many_digits.rs | 84 +++++++++++++++++ src/etc/test-float-parse/src/gen_/sparse.rs | 99 ++++++++++++++++++++ src/etc/test-float-parse/src/gen_/spot_checks.rs | 101 ++++++++++++++++++++ src/etc/test-float-parse/src/gen_/subnorm.rs | 103 ++++++++++++++++++++ src/etc/test-float-parse/src/lib.rs | 38 ++++---- 20 files changed, 793 insertions(+), 793 deletions(-) delete mode 100644 src/etc/test-float-parse/src/gen/exhaustive.rs delete mode 100644 src/etc/test-float-parse/src/gen/exponents.rs delete mode 100644 src/etc/test-float-parse/src/gen/fuzz.rs delete mode 100644 src/etc/test-float-parse/src/gen/integers.rs delete mode 100644 src/etc/test-float-parse/src/gen/long_fractions.rs delete mode 100644 src/etc/test-float-parse/src/gen/many_digits.rs delete mode 100644 src/etc/test-float-parse/src/gen/sparse.rs delete mode 100644 src/etc/test-float-parse/src/gen/spot_checks.rs delete mode 100644 src/etc/test-float-parse/src/gen/subnorm.rs create mode 100644 src/etc/test-float-parse/src/gen_/exhaustive.rs create mode 100644 src/etc/test-float-parse/src/gen_/exponents.rs create mode 100644 src/etc/test-float-parse/src/gen_/fuzz.rs create mode 100644 src/etc/test-float-parse/src/gen_/integers.rs create mode 100644 src/etc/test-float-parse/src/gen_/long_fractions.rs create mode 100644 src/etc/test-float-parse/src/gen_/many_digits.rs create mode 100644 src/etc/test-float-parse/src/gen_/sparse.rs create mode 100644 src/etc/test-float-parse/src/gen_/spot_checks.rs create mode 100644 src/etc/test-float-parse/src/gen_/subnorm.rs (limited to 'src/etc/test-float-parse') diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml index bacb9e09f3f..8a9c5322ef7 100644 --- a/src/etc/test-float-parse/Cargo.toml +++ b/src/etc/test-float-parse/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "test-float-parse" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen/exhaustive.rs deleted file mode 100644 index 01458fb0b60..00000000000 --- a/src/etc/test-float-parse/src/gen/exhaustive.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::fmt::Write; -use std::ops::RangeInclusive; - -use crate::{Float, Generator, Int}; - -/// Test every possible bit pattern. This is infeasible to run on any float types larger than -/// `f32` (which takes about an hour). -pub struct Exhaustive { - iter: RangeInclusive, -} - -impl Generator for Exhaustive -where - RangeInclusive: Iterator, -{ - const SHORT_NAME: &'static str = "exhaustive"; - - type WriteCtx = F; - - fn total_tests() -> u64 { - 1u64.checked_shl(F::Int::BITS).expect("More than u64::MAX tests") - } - - fn new() -> Self { - Self { iter: F::Int::ZERO..=F::Int::MAX } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx:e}").unwrap(); - } -} - -impl Iterator for Exhaustive -where - RangeInclusive: Iterator, -{ - type Item = F; - - fn next(&mut self) -> Option { - Some(F::from_bits(self.iter.next()?)) - } -} diff --git a/src/etc/test-float-parse/src/gen/exponents.rs b/src/etc/test-float-parse/src/gen/exponents.rs deleted file mode 100644 index 3748e9d380c..00000000000 --- a/src/etc/test-float-parse/src/gen/exponents.rs +++ /dev/null @@ -1,95 +0,0 @@ -use std::fmt::Write; -use std::ops::RangeInclusive; - -use crate::traits::BoxGenIter; -use crate::{Float, Generator}; - -const SMALL_COEFF_MAX: i32 = 10_000; -const SMALL_EXP_MAX: i32 = 300; - -const SMALL_COEFF_RANGE: RangeInclusive = (-SMALL_COEFF_MAX)..=SMALL_COEFF_MAX; -const SMALL_EXP_RANGE: RangeInclusive = (-SMALL_EXP_MAX)..=SMALL_EXP_MAX; - -const LARGE_COEFF_RANGE: RangeInclusive = 0..=100_000; -const LARGE_EXP_RANGE: RangeInclusive = 300..=350; - -/// Check exponential values around zero. -pub struct SmallExponents { - iter: BoxGenIter, -} - -impl Generator for SmallExponents { - const NAME: &'static str = "small exponents"; - const SHORT_NAME: &'static str = "small exp"; - - /// `(coefficient, exponent)` - type WriteCtx = (i32, i32); - - fn total_tests() -> u64 { - ((1 + SMALL_COEFF_RANGE.end() - SMALL_COEFF_RANGE.start()) - * (1 + SMALL_EXP_RANGE.end() - SMALL_EXP_RANGE.start())) - .try_into() - .unwrap() - } - - fn new() -> Self { - let iter = SMALL_EXP_RANGE.flat_map(|exp| SMALL_COEFF_RANGE.map(move |coeff| (coeff, exp))); - - Self { iter: Box::new(iter) } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - let (coeff, exp) = ctx; - write!(s, "{coeff}e{exp}").unwrap(); - } -} - -impl Iterator for SmallExponents { - type Item = (i32, i32); - - fn next(&mut self) -> Option { - self.iter.next() - } -} - -/// Check exponential values further from zero. -pub struct LargeExponents { - iter: BoxGenIter, -} - -impl Generator for LargeExponents { - const NAME: &'static str = "large positive exponents"; - const SHORT_NAME: &'static str = "large exp"; - - /// `(coefficient, exponent, is_positive)` - type WriteCtx = (u32, u32, bool); - - fn total_tests() -> u64 { - ((1 + LARGE_EXP_RANGE.end() - LARGE_EXP_RANGE.start()) - * (1 + LARGE_COEFF_RANGE.end() - LARGE_COEFF_RANGE.start()) - * 2) - .into() - } - - fn new() -> Self { - let iter = LARGE_EXP_RANGE - .flat_map(|exp| LARGE_COEFF_RANGE.map(move |coeff| (coeff, exp))) - .flat_map(|(coeff, exp)| [(coeff, exp, false), (coeff, exp, true)]); - - Self { iter: Box::new(iter) } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - let (coeff, exp, is_positive) = ctx; - let sign = if is_positive { "" } else { "-" }; - write!(s, "{sign}{coeff}e{exp}").unwrap(); - } -} - -impl Iterator for LargeExponents { - type Item = (u32, u32, bool); - - fn next(&mut self) -> Option { - self.iter.next() - } -} diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen/fuzz.rs deleted file mode 100644 index 1d6c5562a14..00000000000 --- a/src/etc/test-float-parse/src/gen/fuzz.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::any::{TypeId, type_name}; -use std::collections::BTreeMap; -use std::fmt::Write; -use std::marker::PhantomData; -use std::ops::Range; -use std::sync::Mutex; - -use rand::Rng; -use rand::distr::{Distribution, StandardUniform}; -use rand_chacha::ChaCha8Rng; -use rand_chacha::rand_core::SeedableRng; - -use crate::{Float, Generator, Int, SEED}; - -/// Mapping of float types to the number of iterations that should be run. -/// -/// We could probably make `Generator::new` take an argument instead of the global state, -/// but we only load this once so it works. -static FUZZ_COUNTS: Mutex> = Mutex::new(BTreeMap::new()); - -/// Generic fuzzer; just tests deterministic random bit patterns N times. -pub struct Fuzz { - iter: Range, - rng: ChaCha8Rng, - /// Allow us to use generics in `Iterator`. - marker: PhantomData, -} - -impl Fuzz { - /// Register how many iterations the fuzzer should run for a type. Uses some logic by - /// default, but if `from_cfg` is `Some`, that will be used instead. - pub fn set_iterations(from_cfg: Option) { - let count = if let Some(cfg_count) = from_cfg { - cfg_count - } else if F::BITS <= crate::MAX_BITS_FOR_EXHAUUSTIVE { - // If we run exhaustively, still fuzz but only do half as many bits. The only goal here is - // to catch failures from e.g. high bit patterns before exhaustive tests would get to them. - (F::Int::MAX >> (F::BITS / 2)).try_into().unwrap() - } else { - // Eveything bigger gets a fuzz test with as many iterations as `f32` exhaustive. - u32::MAX.into() - }; - - let _ = FUZZ_COUNTS.lock().unwrap().insert(TypeId::of::(), count); - } -} - -impl Generator for Fuzz -where - StandardUniform: Distribution<::Int>, -{ - const SHORT_NAME: &'static str = "fuzz"; - - type WriteCtx = F; - - fn total_tests() -> u64 { - *FUZZ_COUNTS - .lock() - .unwrap() - .get(&TypeId::of::()) - .unwrap_or_else(|| panic!("missing fuzz count for {}", type_name::())) - } - - fn new() -> Self { - let rng = ChaCha8Rng::from_seed(SEED); - - Self { iter: 0..Self::total_tests(), rng, marker: PhantomData } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx:e}").unwrap(); - } -} - -impl Iterator for Fuzz -where - StandardUniform: Distribution<::Int>, -{ - type Item = >::WriteCtx; - - fn next(&mut self) -> Option { - let _ = self.iter.next()?; - let i: F::Int = self.rng.random(); - - Some(F::from_bits(i)) - } -} diff --git a/src/etc/test-float-parse/src/gen/integers.rs b/src/etc/test-float-parse/src/gen/integers.rs deleted file mode 100644 index 070d188e88c..00000000000 --- a/src/etc/test-float-parse/src/gen/integers.rs +++ /dev/null @@ -1,104 +0,0 @@ -use std::fmt::Write; -use std::ops::{Range, RangeInclusive}; - -use crate::traits::BoxGenIter; -use crate::{Float, Generator}; - -const SMALL_MAX_POW2: u32 = 19; - -/// All values up to the max power of two -const SMALL_VALUES: RangeInclusive = { - let max = 1i32 << SMALL_MAX_POW2; - (-max)..=max -}; - -/// Large values only get tested around powers of two -const LARGE_POWERS: Range = SMALL_MAX_POW2..128; - -/// We perturbe each large value around these ranges -const LARGE_PERTURBATIONS: RangeInclusive = -256..=256; - -/// Test all integers up to `2 ^ MAX_POW2` -pub struct SmallInt { - iter: RangeInclusive, -} - -impl Generator for SmallInt { - const NAME: &'static str = "small integer values"; - const SHORT_NAME: &'static str = "int small"; - - type WriteCtx = i32; - - fn total_tests() -> u64 { - (SMALL_VALUES.end() + 1 - SMALL_VALUES.start()).try_into().unwrap() - } - - fn new() -> Self { - Self { iter: SMALL_VALUES } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx}").unwrap(); - } -} - -impl Iterator for SmallInt { - type Item = i32; - - fn next(&mut self) -> Option { - self.iter.next() - } -} - -/// Test much bigger integers than [`SmallInt`]. -pub struct LargeInt { - iter: BoxGenIter, -} - -impl LargeInt { - const EDGE_CASES: [i128; 7] = [ - i32::MIN as i128, - i32::MAX as i128, - i64::MIN as i128, - i64::MAX as i128, - u64::MAX as i128, - i128::MIN, - i128::MAX, - ]; -} - -impl Generator for LargeInt { - const NAME: &'static str = "large integer values"; - const SHORT_NAME: &'static str = "int large"; - - type WriteCtx = i128; - - fn total_tests() -> u64 { - u64::try_from( - (i128::from(LARGE_POWERS.end - LARGE_POWERS.start) - + i128::try_from(Self::EDGE_CASES.len()).unwrap()) - * (LARGE_PERTURBATIONS.end() + 1 - LARGE_PERTURBATIONS.start()), - ) - .unwrap() - } - - fn new() -> Self { - let iter = LARGE_POWERS - .map(|pow| 1i128 << pow) - .chain(Self::EDGE_CASES) - .flat_map(|base| LARGE_PERTURBATIONS.map(move |perturb| base.saturating_add(perturb))); - - Self { iter: Box::new(iter) } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx}").unwrap(); - } -} -impl Iterator for LargeInt { - type Item = i128; - - fn next(&mut self) -> Option { - self.iter.next() - } -} diff --git a/src/etc/test-float-parse/src/gen/long_fractions.rs b/src/etc/test-float-parse/src/gen/long_fractions.rs deleted file mode 100644 index b75148b779c..00000000000 --- a/src/etc/test-float-parse/src/gen/long_fractions.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::char; -use std::fmt::Write; - -use crate::{Float, Generator}; - -/// Number of decimal digits to check (all of them). -const MAX_DIGIT: u32 = 9; -/// Test with this many decimals in the string. -const MAX_DECIMALS: usize = 410; -const PREFIX: &str = "0."; - -/// Test e.g. `0.1`, `0.11`, `0.111`, `0.1111`, ..., `0.2`, `0.22`, ... -pub struct RepeatingDecimal { - digit: u32, - buf: String, -} - -impl Generator for RepeatingDecimal { - const NAME: &'static str = "repeating decimal"; - const SHORT_NAME: &'static str = "dec rep"; - - type WriteCtx = String; - - fn total_tests() -> u64 { - u64::from(MAX_DIGIT + 1) * u64::try_from(MAX_DECIMALS + 1).unwrap() + 1 - } - - fn new() -> Self { - Self { digit: 0, buf: PREFIX.to_owned() } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - *s = ctx; - } -} - -impl Iterator for RepeatingDecimal { - type Item = String; - - fn next(&mut self) -> Option { - if self.digit > MAX_DIGIT { - return None; - } - - let digit = self.digit; - let inc_digit = self.buf.len() - PREFIX.len() > MAX_DECIMALS; - - if inc_digit { - // Reset the string - self.buf.clear(); - self.digit += 1; - self.buf.write_str(PREFIX).unwrap(); - } - - self.buf.push(char::from_digit(digit, 10).unwrap()); - Some(self.buf.clone()) - } -} diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen/many_digits.rs deleted file mode 100644 index 741e11437fe..00000000000 --- a/src/etc/test-float-parse/src/gen/many_digits.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::char; -use std::fmt::Write; -use std::marker::PhantomData; -use std::ops::{Range, RangeInclusive}; - -use rand::distr::{Distribution, Uniform}; -use rand::{Rng, SeedableRng}; -use rand_chacha::ChaCha8Rng; - -use crate::{Float, Generator, SEED}; - -/// Total iterations -const ITERATIONS: u64 = 5_000_000; - -/// Possible lengths of the string, excluding decimals and exponents -const POSSIBLE_NUM_DIGITS: RangeInclusive = 100..=400; - -/// Range of possible exponents -const EXP_RANGE: Range = -4500..4500; - -/// Try strings of random digits. -pub struct RandDigits { - rng: ChaCha8Rng, - iter: Range, - uniform: Uniform, - /// Allow us to use generics in `Iterator`. - marker: PhantomData, -} - -impl Generator for RandDigits { - const NAME: &'static str = "random digits"; - - const SHORT_NAME: &'static str = "rand digits"; - - type WriteCtx = String; - - fn total_tests() -> u64 { - ITERATIONS - } - - fn new() -> Self { - let rng = ChaCha8Rng::from_seed(SEED); - let range = Uniform::try_from(0..10).unwrap(); - - Self { rng, iter: 0..ITERATIONS, uniform: range, marker: PhantomData } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - *s = ctx; - } -} - -impl Iterator for RandDigits { - type Item = String; - - fn next(&mut self) -> Option { - let _ = self.iter.next()?; - let num_digits = self.rng.random_range(POSSIBLE_NUM_DIGITS); - let has_decimal = self.rng.random_bool(0.2); - let has_exp = self.rng.random_bool(0.2); - - let dec_pos = if has_decimal { Some(self.rng.random_range(0..num_digits)) } else { None }; - - let mut s = String::with_capacity(num_digits); - - for pos in 0..num_digits { - let digit = char::from_digit(self.uniform.sample(&mut self.rng), 10).unwrap(); - s.push(digit); - - if let Some(dec_pos) = dec_pos { - if pos == dec_pos { - s.push('.'); - } - } - } - - if has_exp { - let exp = self.rng.random_range(EXP_RANGE); - write!(s, "e{exp}").unwrap(); - } - - Some(s) - } -} diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen/sparse.rs deleted file mode 100644 index 72b65d4ce7f..00000000000 --- a/src/etc/test-float-parse/src/gen/sparse.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::fmt::Write; - -use crate::traits::BoxGenIter; -use crate::{Float, Generator}; - -const POWERS_OF_TWO: [u128; 128] = make_powers_of_two(); - -const fn make_powers_of_two() -> [u128; 128] { - let mut ret = [0; 128]; - let mut i = 0; - while i < 128 { - ret[i] = 1 << i; - i += 1; - } - - ret -} - -/// Can't clone this result because of lifetime errors, just use a macro. -macro_rules! pow_iter { - () => { - (0..F::BITS).map(|i| F::Int::try_from(POWERS_OF_TWO[i as usize]).unwrap()) - }; -} - -/// Test all numbers that include three 1s in the binary representation as integers. -pub struct FewOnesInt -where - FewOnesInt: Generator, -{ - iter: BoxGenIter, -} - -impl Generator for FewOnesInt -where - >::Error: std::fmt::Debug, -{ - const SHORT_NAME: &'static str = "few ones int"; - - type WriteCtx = F::Int; - - fn total_tests() -> u64 { - u64::from(F::BITS).pow(3) - } - - fn new() -> Self { - let iter = pow_iter!() - .flat_map(move |a| pow_iter!().map(move |b| (a, b))) - .flat_map(move |(a, b)| pow_iter!().map(move |c| (a, b, c))) - .map(|(a, b, c)| a | b | c); - - Self { iter: Box::new(iter) } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx}").unwrap(); - } -} - -impl Iterator for FewOnesInt { - type Item = F::Int; - - fn next(&mut self) -> Option { - self.iter.next() - } -} - -/// Similar to `FewOnesInt` except test those bit patterns as a float. -pub struct FewOnesFloat(FewOnesInt); - -impl Generator for FewOnesFloat -where - >::Error: std::fmt::Debug, -{ - const NAME: &'static str = "few ones float"; - const SHORT_NAME: &'static str = "few ones float"; - - type WriteCtx = F; - - fn total_tests() -> u64 { - FewOnesInt::::total_tests() - } - - fn new() -> Self { - Self(FewOnesInt::new()) - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx:e}").unwrap(); - } -} - -impl Iterator for FewOnesFloat { - type Item = F; - - fn next(&mut self) -> Option { - self.0.next().map(|i| F::from_bits(i)) - } -} diff --git a/src/etc/test-float-parse/src/gen/spot_checks.rs b/src/etc/test-float-parse/src/gen/spot_checks.rs deleted file mode 100644 index 18691f9d6cf..00000000000 --- a/src/etc/test-float-parse/src/gen/spot_checks.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::fmt::Write; - -use crate::traits::{Float, Generator}; - -const SPECIAL: &[&str] = &[ - "inf", "Inf", "iNf", "INF", "-inf", "-Inf", "-iNf", "-INF", "+inf", "+Inf", "+iNf", "+INF", - "nan", "NaN", "NAN", "nAn", "-nan", "-NaN", "-NAN", "-nAn", "+nan", "+NaN", "+NAN", "+nAn", - "1", "-1", "+1", "1e1", "-1e1", "+1e1", "1e-1", "-1e-1", "+1e-1", "1e+1", "-1e+1", "+1e+1", - "1E1", "-1E1", "+1E1", "1E-1", "-1E-1", "+1E-1", "1E+1", "-1E+1", "+1E+1", "0", "-0", "+0", -]; - -/// Check various non-numeric special strings. -pub struct Special { - iter: std::slice::Iter<'static, &'static str>, -} - -impl Generator for Special { - const NAME: &'static str = "special values"; - - const SHORT_NAME: &'static str = "special"; - - type WriteCtx = &'static str; - - fn total_tests() -> u64 { - SPECIAL.len().try_into().unwrap() - } - - fn new() -> Self { - Self { iter: SPECIAL.iter() } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - s.write_str(ctx).unwrap(); - } -} - -impl Iterator for Special { - type Item = &'static str; - - fn next(&mut self) -> Option { - self.iter.next().copied() - } -} - -/// Strings that we know have failed in the past -const REGRESSIONS: &[&str] = &[ - // From - "1234567890123456789012345678901234567890e-340", - "2.225073858507201136057409796709131975934819546351645648023426109724822222021076945516529523908135087914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012981122451451889849057222307285255133155755015914397476397983411801999323962548289017107081850690630666655994938275772572015763062690663332647565300009245888316433037779791869612049497390377829704905051080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621572289880258182545180325707018860872113128079512233426288368622321503775666622503982534335974568884423900265498198385487948292206894721689831099698365846814022854243330660339850886445804001034933970427567186443383770486037861622771738545623065874679014086723327636718749999999999999999999999999999999999999e-308", - "2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308", - "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222507385850720138309023271733240406421921598046233183055332741688720443481391819585428315901251102056406733973103581100515243416155346010885601238537771882113077799353200233047961014744258363607192156504694250373420837525080665061665815894872049117996859163964850063590877011830487479978088775374994945158045160505091539985658247081864511353793580499211598108576605199243335211435239014879569960959128889160299264151106346631339366347758651302937176204732563178148566435087212282863764204484681140761391147706280168985324411002416144742161856716615054015428508471675290190316132277889672970737312333408698898317506783884692609277397797285865965494109136909540613646756870239867831529068098461721092462539672851562500000000000000001", - "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999", - "2.47032822920623272e-324", - "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316", - "3.237883913302901289588352412501532174863037669423108059901297049552301970670676565786835742587799557860615776559838283435514391084153169252689190564396459577394618038928365305143463955100356696665629202017331344031730044369360205258345803431471660032699580731300954848363975548690010751530018881758184174569652173110473696022749934638425380623369774736560008997404060967498028389191878963968575439222206416981462690113342524002724385941651051293552601421155333430225237291523843322331326138431477823591142408800030775170625915670728657003151953664260769822494937951845801530895238439819708403389937873241463484205608000027270531106827387907791444918534771598750162812548862768493201518991668028251730299953143924168545708663913273994694463908672332763671875E-319", - "6.953355807847677105972805215521891690222119817145950754416205607980030131549636688806115726399441880065386399864028691275539539414652831584795668560082999889551357784961446896042113198284213107935110217162654939802416034676213829409720583759540476786936413816541621287843248433202369209916612249676005573022703244799714622116542188837770376022371172079559125853382801396219552418839469770514904192657627060319372847562301074140442660237844114174497210955449896389180395827191602886654488182452409583981389442783377001505462015745017848754574668342161759496661766020028752888783387074850773192997102997936619876226688096314989645766000479009083731736585750335262099860150896718774401964796827166283225641992040747894382698751809812609536720628966577351093292236328125E-310", - "3.339068557571188581835713701280943911923401916998521771655656997328440314559615318168849149074662609099998113009465566426808170378434065722991659642619467706034884424989741080790766778456332168200464651593995817371782125010668346652995912233993254584461125868481633343674905074271064409763090708017856584019776878812425312008812326260363035474811532236853359905334625575404216060622858633280744301892470300555678734689978476870369853549413277156622170245846166991655321535529623870646888786637528995592800436177901746286272273374471701452991433047257863864601424252024791567368195056077320885329384322332391564645264143400798619665040608077549162173963649264049738362290606875883456826586710961041737908872035803481241600376705491726170293986797332763671875E-319", - "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999e-324", - "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324", - "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001e-324", - "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324", - "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324", - "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324", - "94393431193180696942841837085033647913224148539854e-358", - "104308485241983990666713401708072175773165034278685682646111762292409330928739751702404658197872319129036519947435319418387839758990478549477777586673075945844895981012024387992135617064532141489278815239849108105951619997829153633535314849999674266169258928940692239684771590065027025835804863585454872499320500023126142553932654370362024104462255244034053203998964360882487378334860197725139151265590832887433736189468858614521708567646743455601905935595381852723723645799866672558576993978025033590728687206296379801363024094048327273913079612469982585674824156000783167963081616214710691759864332339239688734656548790656486646106983450809073750535624894296242072010195710276073042036425579852459556183541199012652571123898996574563824424330960027873516082763671875e-1075", - "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281249", - "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251", -]; - -/// Check items that failed in the past. -pub struct RegressionCheck { - iter: std::slice::Iter<'static, &'static str>, -} - -impl Generator for RegressionCheck { - const NAME: &'static str = "regression check"; - - const SHORT_NAME: &'static str = "regression"; - - type WriteCtx = &'static str; - - fn total_tests() -> u64 { - REGRESSIONS.len().try_into().unwrap() - } - - fn new() -> Self { - Self { iter: REGRESSIONS.iter() } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - s.write_str(ctx).unwrap(); - } -} - -impl Iterator for RegressionCheck { - type Item = &'static str; - - fn next(&mut self) -> Option { - self.iter.next().copied() - } -} diff --git a/src/etc/test-float-parse/src/gen/subnorm.rs b/src/etc/test-float-parse/src/gen/subnorm.rs deleted file mode 100644 index 4fe3b90a3dd..00000000000 --- a/src/etc/test-float-parse/src/gen/subnorm.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::cmp::min; -use std::fmt::Write; -use std::ops::RangeInclusive; - -use crate::{Float, Generator, Int}; - -/// Spot check some edge cases for subnormals. -pub struct SubnormEdgeCases { - cases: [F::Int; 6], - index: usize, -} - -impl SubnormEdgeCases { - /// Shorthand - const I1: F::Int = F::Int::ONE; - - fn edge_cases() -> [F::Int; 6] { - // Comments use an 8-bit mantissa as a demo - [ - // 0b00000001 - Self::I1, - // 0b10000000 - Self::I1 << (F::MAN_BITS - 1), - // 0b00001000 - Self::I1 << ((F::MAN_BITS / 2) - 1), - // 0b00001111 - Self::I1 << ((F::MAN_BITS / 2) - 1), - // 0b00001111 - Self::I1 << ((F::MAN_BITS / 2) - 1), - // 0b11111111 - F::MAN_MASK, - ] - } -} - -impl Generator for SubnormEdgeCases { - const NAME: &'static str = "subnormal edge cases"; - const SHORT_NAME: &'static str = "subnorm edge"; - - type WriteCtx = F; - - fn new() -> Self { - Self { cases: Self::edge_cases(), index: 0 } - } - - fn total_tests() -> u64 { - Self::edge_cases().len().try_into().unwrap() - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx:e}").unwrap(); - } -} - -impl Iterator for SubnormEdgeCases { - type Item = F; - - fn next(&mut self) -> Option { - let i = self.cases.get(self.index)?; - self.index += 1; - - Some(F::from_bits(*i)) - } -} - -/// Test all subnormals up to `1 << 22`. -pub struct SubnormComplete { - iter: RangeInclusive, -} - -impl Generator for SubnormComplete -where - RangeInclusive: Iterator, -{ - const NAME: &'static str = "subnormal"; - const SHORT_NAME: &'static str = "subnorm "; - - type WriteCtx = F; - - fn total_tests() -> u64 { - let iter = Self::new().iter; - (F::Int::ONE + *iter.end() - *iter.start()).try_into().unwrap() - } - - fn new() -> Self { - Self { iter: F::Int::ZERO..=min(F::Int::ONE << 22, F::MAN_BITS.try_into().unwrap()) } - } - - fn write_string(s: &mut String, ctx: Self::WriteCtx) { - write!(s, "{ctx:e}").unwrap(); - } -} - -impl Iterator for SubnormComplete -where - RangeInclusive: Iterator, -{ - type Item = F; - - fn next(&mut self) -> Option { - Some(F::from_bits(self.iter.next()?)) - } -} diff --git a/src/etc/test-float-parse/src/gen_/exhaustive.rs b/src/etc/test-float-parse/src/gen_/exhaustive.rs new file mode 100644 index 00000000000..01458fb0b60 --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/exhaustive.rs @@ -0,0 +1,42 @@ +use std::fmt::Write; +use std::ops::RangeInclusive; + +use crate::{Float, Generator, Int}; + +/// Test every possible bit pattern. This is infeasible to run on any float types larger than +/// `f32` (which takes about an hour). +pub struct Exhaustive { + iter: RangeInclusive, +} + +impl Generator for Exhaustive +where + RangeInclusive: Iterator, +{ + const SHORT_NAME: &'static str = "exhaustive"; + + type WriteCtx = F; + + fn total_tests() -> u64 { + 1u64.checked_shl(F::Int::BITS).expect("More than u64::MAX tests") + } + + fn new() -> Self { + Self { iter: F::Int::ZERO..=F::Int::MAX } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx:e}").unwrap(); + } +} + +impl Iterator for Exhaustive +where + RangeInclusive: Iterator, +{ + type Item = F; + + fn next(&mut self) -> Option { + Some(F::from_bits(self.iter.next()?)) + } +} diff --git a/src/etc/test-float-parse/src/gen_/exponents.rs b/src/etc/test-float-parse/src/gen_/exponents.rs new file mode 100644 index 00000000000..3748e9d380c --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/exponents.rs @@ -0,0 +1,95 @@ +use std::fmt::Write; +use std::ops::RangeInclusive; + +use crate::traits::BoxGenIter; +use crate::{Float, Generator}; + +const SMALL_COEFF_MAX: i32 = 10_000; +const SMALL_EXP_MAX: i32 = 300; + +const SMALL_COEFF_RANGE: RangeInclusive = (-SMALL_COEFF_MAX)..=SMALL_COEFF_MAX; +const SMALL_EXP_RANGE: RangeInclusive = (-SMALL_EXP_MAX)..=SMALL_EXP_MAX; + +const LARGE_COEFF_RANGE: RangeInclusive = 0..=100_000; +const LARGE_EXP_RANGE: RangeInclusive = 300..=350; + +/// Check exponential values around zero. +pub struct SmallExponents { + iter: BoxGenIter, +} + +impl Generator for SmallExponents { + const NAME: &'static str = "small exponents"; + const SHORT_NAME: &'static str = "small exp"; + + /// `(coefficient, exponent)` + type WriteCtx = (i32, i32); + + fn total_tests() -> u64 { + ((1 + SMALL_COEFF_RANGE.end() - SMALL_COEFF_RANGE.start()) + * (1 + SMALL_EXP_RANGE.end() - SMALL_EXP_RANGE.start())) + .try_into() + .unwrap() + } + + fn new() -> Self { + let iter = SMALL_EXP_RANGE.flat_map(|exp| SMALL_COEFF_RANGE.map(move |coeff| (coeff, exp))); + + Self { iter: Box::new(iter) } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + let (coeff, exp) = ctx; + write!(s, "{coeff}e{exp}").unwrap(); + } +} + +impl Iterator for SmallExponents { + type Item = (i32, i32); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +/// Check exponential values further from zero. +pub struct LargeExponents { + iter: BoxGenIter, +} + +impl Generator for LargeExponents { + const NAME: &'static str = "large positive exponents"; + const SHORT_NAME: &'static str = "large exp"; + + /// `(coefficient, exponent, is_positive)` + type WriteCtx = (u32, u32, bool); + + fn total_tests() -> u64 { + ((1 + LARGE_EXP_RANGE.end() - LARGE_EXP_RANGE.start()) + * (1 + LARGE_COEFF_RANGE.end() - LARGE_COEFF_RANGE.start()) + * 2) + .into() + } + + fn new() -> Self { + let iter = LARGE_EXP_RANGE + .flat_map(|exp| LARGE_COEFF_RANGE.map(move |coeff| (coeff, exp))) + .flat_map(|(coeff, exp)| [(coeff, exp, false), (coeff, exp, true)]); + + Self { iter: Box::new(iter) } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + let (coeff, exp, is_positive) = ctx; + let sign = if is_positive { "" } else { "-" }; + write!(s, "{sign}{coeff}e{exp}").unwrap(); + } +} + +impl Iterator for LargeExponents { + type Item = (u32, u32, bool); + + fn next(&mut self) -> Option { + self.iter.next() + } +} diff --git a/src/etc/test-float-parse/src/gen_/fuzz.rs b/src/etc/test-float-parse/src/gen_/fuzz.rs new file mode 100644 index 00000000000..1d6c5562a14 --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/fuzz.rs @@ -0,0 +1,87 @@ +use std::any::{TypeId, type_name}; +use std::collections::BTreeMap; +use std::fmt::Write; +use std::marker::PhantomData; +use std::ops::Range; +use std::sync::Mutex; + +use rand::Rng; +use rand::distr::{Distribution, StandardUniform}; +use rand_chacha::ChaCha8Rng; +use rand_chacha::rand_core::SeedableRng; + +use crate::{Float, Generator, Int, SEED}; + +/// Mapping of float types to the number of iterations that should be run. +/// +/// We could probably make `Generator::new` take an argument instead of the global state, +/// but we only load this once so it works. +static FUZZ_COUNTS: Mutex> = Mutex::new(BTreeMap::new()); + +/// Generic fuzzer; just tests deterministic random bit patterns N times. +pub struct Fuzz { + iter: Range, + rng: ChaCha8Rng, + /// Allow us to use generics in `Iterator`. + marker: PhantomData, +} + +impl Fuzz { + /// Register how many iterations the fuzzer should run for a type. Uses some logic by + /// default, but if `from_cfg` is `Some`, that will be used instead. + pub fn set_iterations(from_cfg: Option) { + let count = if let Some(cfg_count) = from_cfg { + cfg_count + } else if F::BITS <= crate::MAX_BITS_FOR_EXHAUUSTIVE { + // If we run exhaustively, still fuzz but only do half as many bits. The only goal here is + // to catch failures from e.g. high bit patterns before exhaustive tests would get to them. + (F::Int::MAX >> (F::BITS / 2)).try_into().unwrap() + } else { + // Eveything bigger gets a fuzz test with as many iterations as `f32` exhaustive. + u32::MAX.into() + }; + + let _ = FUZZ_COUNTS.lock().unwrap().insert(TypeId::of::(), count); + } +} + +impl Generator for Fuzz +where + StandardUniform: Distribution<::Int>, +{ + const SHORT_NAME: &'static str = "fuzz"; + + type WriteCtx = F; + + fn total_tests() -> u64 { + *FUZZ_COUNTS + .lock() + .unwrap() + .get(&TypeId::of::()) + .unwrap_or_else(|| panic!("missing fuzz count for {}", type_name::())) + } + + fn new() -> Self { + let rng = ChaCha8Rng::from_seed(SEED); + + Self { iter: 0..Self::total_tests(), rng, marker: PhantomData } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx:e}").unwrap(); + } +} + +impl Iterator for Fuzz +where + StandardUniform: Distribution<::Int>, +{ + type Item = >::WriteCtx; + + fn next(&mut self) -> Option { + let _ = self.iter.next()?; + let i: F::Int = self.rng.random(); + + Some(F::from_bits(i)) + } +} diff --git a/src/etc/test-float-parse/src/gen_/integers.rs b/src/etc/test-float-parse/src/gen_/integers.rs new file mode 100644 index 00000000000..070d188e88c --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/integers.rs @@ -0,0 +1,104 @@ +use std::fmt::Write; +use std::ops::{Range, RangeInclusive}; + +use crate::traits::BoxGenIter; +use crate::{Float, Generator}; + +const SMALL_MAX_POW2: u32 = 19; + +/// All values up to the max power of two +const SMALL_VALUES: RangeInclusive = { + let max = 1i32 << SMALL_MAX_POW2; + (-max)..=max +}; + +/// Large values only get tested around powers of two +const LARGE_POWERS: Range = SMALL_MAX_POW2..128; + +/// We perturbe each large value around these ranges +const LARGE_PERTURBATIONS: RangeInclusive = -256..=256; + +/// Test all integers up to `2 ^ MAX_POW2` +pub struct SmallInt { + iter: RangeInclusive, +} + +impl Generator for SmallInt { + const NAME: &'static str = "small integer values"; + const SHORT_NAME: &'static str = "int small"; + + type WriteCtx = i32; + + fn total_tests() -> u64 { + (SMALL_VALUES.end() + 1 - SMALL_VALUES.start()).try_into().unwrap() + } + + fn new() -> Self { + Self { iter: SMALL_VALUES } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx}").unwrap(); + } +} + +impl Iterator for SmallInt { + type Item = i32; + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +/// Test much bigger integers than [`SmallInt`]. +pub struct LargeInt { + iter: BoxGenIter, +} + +impl LargeInt { + const EDGE_CASES: [i128; 7] = [ + i32::MIN as i128, + i32::MAX as i128, + i64::MIN as i128, + i64::MAX as i128, + u64::MAX as i128, + i128::MIN, + i128::MAX, + ]; +} + +impl Generator for LargeInt { + const NAME: &'static str = "large integer values"; + const SHORT_NAME: &'static str = "int large"; + + type WriteCtx = i128; + + fn total_tests() -> u64 { + u64::try_from( + (i128::from(LARGE_POWERS.end - LARGE_POWERS.start) + + i128::try_from(Self::EDGE_CASES.len()).unwrap()) + * (LARGE_PERTURBATIONS.end() + 1 - LARGE_PERTURBATIONS.start()), + ) + .unwrap() + } + + fn new() -> Self { + let iter = LARGE_POWERS + .map(|pow| 1i128 << pow) + .chain(Self::EDGE_CASES) + .flat_map(|base| LARGE_PERTURBATIONS.map(move |perturb| base.saturating_add(perturb))); + + Self { iter: Box::new(iter) } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx}").unwrap(); + } +} +impl Iterator for LargeInt { + type Item = i128; + + fn next(&mut self) -> Option { + self.iter.next() + } +} diff --git a/src/etc/test-float-parse/src/gen_/long_fractions.rs b/src/etc/test-float-parse/src/gen_/long_fractions.rs new file mode 100644 index 00000000000..b75148b779c --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/long_fractions.rs @@ -0,0 +1,58 @@ +use std::char; +use std::fmt::Write; + +use crate::{Float, Generator}; + +/// Number of decimal digits to check (all of them). +const MAX_DIGIT: u32 = 9; +/// Test with this many decimals in the string. +const MAX_DECIMALS: usize = 410; +const PREFIX: &str = "0."; + +/// Test e.g. `0.1`, `0.11`, `0.111`, `0.1111`, ..., `0.2`, `0.22`, ... +pub struct RepeatingDecimal { + digit: u32, + buf: String, +} + +impl Generator for RepeatingDecimal { + const NAME: &'static str = "repeating decimal"; + const SHORT_NAME: &'static str = "dec rep"; + + type WriteCtx = String; + + fn total_tests() -> u64 { + u64::from(MAX_DIGIT + 1) * u64::try_from(MAX_DECIMALS + 1).unwrap() + 1 + } + + fn new() -> Self { + Self { digit: 0, buf: PREFIX.to_owned() } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + *s = ctx; + } +} + +impl Iterator for RepeatingDecimal { + type Item = String; + + fn next(&mut self) -> Option { + if self.digit > MAX_DIGIT { + return None; + } + + let digit = self.digit; + let inc_digit = self.buf.len() - PREFIX.len() > MAX_DECIMALS; + + if inc_digit { + // Reset the string + self.buf.clear(); + self.digit += 1; + self.buf.write_str(PREFIX).unwrap(); + } + + self.buf.push(char::from_digit(digit, 10).unwrap()); + Some(self.buf.clone()) + } +} diff --git a/src/etc/test-float-parse/src/gen_/many_digits.rs b/src/etc/test-float-parse/src/gen_/many_digits.rs new file mode 100644 index 00000000000..741e11437fe --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/many_digits.rs @@ -0,0 +1,84 @@ +use std::char; +use std::fmt::Write; +use std::marker::PhantomData; +use std::ops::{Range, RangeInclusive}; + +use rand::distr::{Distribution, Uniform}; +use rand::{Rng, SeedableRng}; +use rand_chacha::ChaCha8Rng; + +use crate::{Float, Generator, SEED}; + +/// Total iterations +const ITERATIONS: u64 = 5_000_000; + +/// Possible lengths of the string, excluding decimals and exponents +const POSSIBLE_NUM_DIGITS: RangeInclusive = 100..=400; + +/// Range of possible exponents +const EXP_RANGE: Range = -4500..4500; + +/// Try strings of random digits. +pub struct RandDigits { + rng: ChaCha8Rng, + iter: Range, + uniform: Uniform, + /// Allow us to use generics in `Iterator`. + marker: PhantomData, +} + +impl Generator for RandDigits { + const NAME: &'static str = "random digits"; + + const SHORT_NAME: &'static str = "rand digits"; + + type WriteCtx = String; + + fn total_tests() -> u64 { + ITERATIONS + } + + fn new() -> Self { + let rng = ChaCha8Rng::from_seed(SEED); + let range = Uniform::try_from(0..10).unwrap(); + + Self { rng, iter: 0..ITERATIONS, uniform: range, marker: PhantomData } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + *s = ctx; + } +} + +impl Iterator for RandDigits { + type Item = String; + + fn next(&mut self) -> Option { + let _ = self.iter.next()?; + let num_digits = self.rng.random_range(POSSIBLE_NUM_DIGITS); + let has_decimal = self.rng.random_bool(0.2); + let has_exp = self.rng.random_bool(0.2); + + let dec_pos = if has_decimal { Some(self.rng.random_range(0..num_digits)) } else { None }; + + let mut s = String::with_capacity(num_digits); + + for pos in 0..num_digits { + let digit = char::from_digit(self.uniform.sample(&mut self.rng), 10).unwrap(); + s.push(digit); + + if let Some(dec_pos) = dec_pos { + if pos == dec_pos { + s.push('.'); + } + } + } + + if has_exp { + let exp = self.rng.random_range(EXP_RANGE); + write!(s, "e{exp}").unwrap(); + } + + Some(s) + } +} diff --git a/src/etc/test-float-parse/src/gen_/sparse.rs b/src/etc/test-float-parse/src/gen_/sparse.rs new file mode 100644 index 00000000000..72b65d4ce7f --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/sparse.rs @@ -0,0 +1,99 @@ +use std::fmt::Write; + +use crate::traits::BoxGenIter; +use crate::{Float, Generator}; + +const POWERS_OF_TWO: [u128; 128] = make_powers_of_two(); + +const fn make_powers_of_two() -> [u128; 128] { + let mut ret = [0; 128]; + let mut i = 0; + while i < 128 { + ret[i] = 1 << i; + i += 1; + } + + ret +} + +/// Can't clone this result because of lifetime errors, just use a macro. +macro_rules! pow_iter { + () => { + (0..F::BITS).map(|i| F::Int::try_from(POWERS_OF_TWO[i as usize]).unwrap()) + }; +} + +/// Test all numbers that include three 1s in the binary representation as integers. +pub struct FewOnesInt +where + FewOnesInt: Generator, +{ + iter: BoxGenIter, +} + +impl Generator for FewOnesInt +where + >::Error: std::fmt::Debug, +{ + const SHORT_NAME: &'static str = "few ones int"; + + type WriteCtx = F::Int; + + fn total_tests() -> u64 { + u64::from(F::BITS).pow(3) + } + + fn new() -> Self { + let iter = pow_iter!() + .flat_map(move |a| pow_iter!().map(move |b| (a, b))) + .flat_map(move |(a, b)| pow_iter!().map(move |c| (a, b, c))) + .map(|(a, b, c)| a | b | c); + + Self { iter: Box::new(iter) } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx}").unwrap(); + } +} + +impl Iterator for FewOnesInt { + type Item = F::Int; + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +/// Similar to `FewOnesInt` except test those bit patterns as a float. +pub struct FewOnesFloat(FewOnesInt); + +impl Generator for FewOnesFloat +where + >::Error: std::fmt::Debug, +{ + const NAME: &'static str = "few ones float"; + const SHORT_NAME: &'static str = "few ones float"; + + type WriteCtx = F; + + fn total_tests() -> u64 { + FewOnesInt::::total_tests() + } + + fn new() -> Self { + Self(FewOnesInt::new()) + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx:e}").unwrap(); + } +} + +impl Iterator for FewOnesFloat { + type Item = F; + + fn next(&mut self) -> Option { + self.0.next().map(|i| F::from_bits(i)) + } +} diff --git a/src/etc/test-float-parse/src/gen_/spot_checks.rs b/src/etc/test-float-parse/src/gen_/spot_checks.rs new file mode 100644 index 00000000000..18691f9d6cf --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/spot_checks.rs @@ -0,0 +1,101 @@ +use std::fmt::Write; + +use crate::traits::{Float, Generator}; + +const SPECIAL: &[&str] = &[ + "inf", "Inf", "iNf", "INF", "-inf", "-Inf", "-iNf", "-INF", "+inf", "+Inf", "+iNf", "+INF", + "nan", "NaN", "NAN", "nAn", "-nan", "-NaN", "-NAN", "-nAn", "+nan", "+NaN", "+NAN", "+nAn", + "1", "-1", "+1", "1e1", "-1e1", "+1e1", "1e-1", "-1e-1", "+1e-1", "1e+1", "-1e+1", "+1e+1", + "1E1", "-1E1", "+1E1", "1E-1", "-1E-1", "+1E-1", "1E+1", "-1E+1", "+1E+1", "0", "-0", "+0", +]; + +/// Check various non-numeric special strings. +pub struct Special { + iter: std::slice::Iter<'static, &'static str>, +} + +impl Generator for Special { + const NAME: &'static str = "special values"; + + const SHORT_NAME: &'static str = "special"; + + type WriteCtx = &'static str; + + fn total_tests() -> u64 { + SPECIAL.len().try_into().unwrap() + } + + fn new() -> Self { + Self { iter: SPECIAL.iter() } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + s.write_str(ctx).unwrap(); + } +} + +impl Iterator for Special { + type Item = &'static str; + + fn next(&mut self) -> Option { + self.iter.next().copied() + } +} + +/// Strings that we know have failed in the past +const REGRESSIONS: &[&str] = &[ + // From + "1234567890123456789012345678901234567890e-340", + "2.225073858507201136057409796709131975934819546351645648023426109724822222021076945516529523908135087914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012981122451451889849057222307285255133155755015914397476397983411801999323962548289017107081850690630666655994938275772572015763062690663332647565300009245888316433037779791869612049497390377829704905051080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621572289880258182545180325707018860872113128079512233426288368622321503775666622503982534335974568884423900265498198385487948292206894721689831099698365846814022854243330660339850886445804001034933970427567186443383770486037861622771738545623065874679014086723327636718749999999999999999999999999999999999999e-308", + "2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308", + "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000222507385850720138309023271733240406421921598046233183055332741688720443481391819585428315901251102056406733973103581100515243416155346010885601238537771882113077799353200233047961014744258363607192156504694250373420837525080665061665815894872049117996859163964850063590877011830487479978088775374994945158045160505091539985658247081864511353793580499211598108576605199243335211435239014879569960959128889160299264151106346631339366347758651302937176204732563178148566435087212282863764204484681140761391147706280168985324411002416144742161856716615054015428508471675290190316132277889672970737312333408698898317506783884692609277397797285865965494109136909540613646756870239867831529068098461721092462539672851562500000000000000001", + "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999", + "2.47032822920623272e-324", + "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316", + "3.237883913302901289588352412501532174863037669423108059901297049552301970670676565786835742587799557860615776559838283435514391084153169252689190564396459577394618038928365305143463955100356696665629202017331344031730044369360205258345803431471660032699580731300954848363975548690010751530018881758184174569652173110473696022749934638425380623369774736560008997404060967498028389191878963968575439222206416981462690113342524002724385941651051293552601421155333430225237291523843322331326138431477823591142408800030775170625915670728657003151953664260769822494937951845801530895238439819708403389937873241463484205608000027270531106827387907791444918534771598750162812548862768493201518991668028251730299953143924168545708663913273994694463908672332763671875E-319", + "6.953355807847677105972805215521891690222119817145950754416205607980030131549636688806115726399441880065386399864028691275539539414652831584795668560082999889551357784961446896042113198284213107935110217162654939802416034676213829409720583759540476786936413816541621287843248433202369209916612249676005573022703244799714622116542188837770376022371172079559125853382801396219552418839469770514904192657627060319372847562301074140442660237844114174497210955449896389180395827191602886654488182452409583981389442783377001505462015745017848754574668342161759496661766020028752888783387074850773192997102997936619876226688096314989645766000479009083731736585750335262099860150896718774401964796827166283225641992040747894382698751809812609536720628966577351093292236328125E-310", + "3.339068557571188581835713701280943911923401916998521771655656997328440314559615318168849149074662609099998113009465566426808170378434065722991659642619467706034884424989741080790766778456332168200464651593995817371782125010668346652995912233993254584461125868481633343674905074271064409763090708017856584019776878812425312008812326260363035474811532236853359905334625575404216060622858633280744301892470300555678734689978476870369853549413277156622170245846166991655321535529623870646888786637528995592800436177901746286272273374471701452991433047257863864601424252024791567368195056077320885329384322332391564645264143400798619665040608077549162173963649264049738362290606875883456826586710961041737908872035803481241600376705491726170293986797332763671875E-319", + "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999e-324", + "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324", + "2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001e-324", + "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324", + "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324", + "7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324", + "94393431193180696942841837085033647913224148539854e-358", + "104308485241983990666713401708072175773165034278685682646111762292409330928739751702404658197872319129036519947435319418387839758990478549477777586673075945844895981012024387992135617064532141489278815239849108105951619997829153633535314849999674266169258928940692239684771590065027025835804863585454872499320500023126142553932654370362024104462255244034053203998964360882487378334860197725139151265590832887433736189468858614521708567646743455601905935595381852723723645799866672558576993978025033590728687206296379801363024094048327273913079612469982585674824156000783167963081616214710691759864332339239688734656548790656486646106983450809073750535624894296242072010195710276073042036425579852459556183541199012652571123898996574563824424330960027873516082763671875e-1075", + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281249", + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251", +]; + +/// Check items that failed in the past. +pub struct RegressionCheck { + iter: std::slice::Iter<'static, &'static str>, +} + +impl Generator for RegressionCheck { + const NAME: &'static str = "regression check"; + + const SHORT_NAME: &'static str = "regression"; + + type WriteCtx = &'static str; + + fn total_tests() -> u64 { + REGRESSIONS.len().try_into().unwrap() + } + + fn new() -> Self { + Self { iter: REGRESSIONS.iter() } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + s.write_str(ctx).unwrap(); + } +} + +impl Iterator for RegressionCheck { + type Item = &'static str; + + fn next(&mut self) -> Option { + self.iter.next().copied() + } +} diff --git a/src/etc/test-float-parse/src/gen_/subnorm.rs b/src/etc/test-float-parse/src/gen_/subnorm.rs new file mode 100644 index 00000000000..4fe3b90a3dd --- /dev/null +++ b/src/etc/test-float-parse/src/gen_/subnorm.rs @@ -0,0 +1,103 @@ +use std::cmp::min; +use std::fmt::Write; +use std::ops::RangeInclusive; + +use crate::{Float, Generator, Int}; + +/// Spot check some edge cases for subnormals. +pub struct SubnormEdgeCases { + cases: [F::Int; 6], + index: usize, +} + +impl SubnormEdgeCases { + /// Shorthand + const I1: F::Int = F::Int::ONE; + + fn edge_cases() -> [F::Int; 6] { + // Comments use an 8-bit mantissa as a demo + [ + // 0b00000001 + Self::I1, + // 0b10000000 + Self::I1 << (F::MAN_BITS - 1), + // 0b00001000 + Self::I1 << ((F::MAN_BITS / 2) - 1), + // 0b00001111 + Self::I1 << ((F::MAN_BITS / 2) - 1), + // 0b00001111 + Self::I1 << ((F::MAN_BITS / 2) - 1), + // 0b11111111 + F::MAN_MASK, + ] + } +} + +impl Generator for SubnormEdgeCases { + const NAME: &'static str = "subnormal edge cases"; + const SHORT_NAME: &'static str = "subnorm edge"; + + type WriteCtx = F; + + fn new() -> Self { + Self { cases: Self::edge_cases(), index: 0 } + } + + fn total_tests() -> u64 { + Self::edge_cases().len().try_into().unwrap() + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx:e}").unwrap(); + } +} + +impl Iterator for SubnormEdgeCases { + type Item = F; + + fn next(&mut self) -> Option { + let i = self.cases.get(self.index)?; + self.index += 1; + + Some(F::from_bits(*i)) + } +} + +/// Test all subnormals up to `1 << 22`. +pub struct SubnormComplete { + iter: RangeInclusive, +} + +impl Generator for SubnormComplete +where + RangeInclusive: Iterator, +{ + const NAME: &'static str = "subnormal"; + const SHORT_NAME: &'static str = "subnorm "; + + type WriteCtx = F; + + fn total_tests() -> u64 { + let iter = Self::new().iter; + (F::Int::ONE + *iter.end() - *iter.start()).try_into().unwrap() + } + + fn new() -> Self { + Self { iter: F::Int::ZERO..=min(F::Int::ONE << 22, F::MAN_BITS.try_into().unwrap()) } + } + + fn write_string(s: &mut String, ctx: Self::WriteCtx) { + write!(s, "{ctx:e}").unwrap(); + } +} + +impl Iterator for SubnormComplete +where + RangeInclusive: Iterator, +{ + type Item = F; + + fn next(&mut self) -> Option { + Some(F::from_bits(self.iter.next()?)) + } +} diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs index e2f84b085c6..3c3ef5802b6 100644 --- a/src/etc/test-float-parse/src/lib.rs +++ b/src/etc/test-float-parse/src/lib.rs @@ -17,7 +17,7 @@ use traits::{Float, Generator, Int}; use validate::CheckError; /// Test generators. -mod gen { +mod gen_ { pub mod exhaustive; pub mod exponents; pub mod fuzz; @@ -136,24 +136,24 @@ where { if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE { // Only run exhaustive tests if there is a chance of completion. - TestInfo::register::>(tests); + TestInfo::register::>(tests); } - gen::fuzz::Fuzz::::set_iterations(cfg.fuzz_count); - - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::(tests); - TestInfo::register::(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::(tests); - TestInfo::register::(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); + gen_::fuzz::Fuzz::::set_iterations(cfg.fuzz_count); + + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::(tests); + TestInfo::register::(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::(tests); + TestInfo::register::(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); } /// Configuration for a single test. @@ -343,7 +343,7 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration { /// /// This calls the generator's iterator multiple times (in parallel) and validates each output. fn test_runner>(test: &TestInfo, cfg: &Config) { - let gen = G::new(); + let gen_ = G::new(); let executed = AtomicU64::new(0); let failures = AtomicU64::new(0); @@ -387,7 +387,7 @@ fn test_runner>(test: &TestInfo, cfg: &Config) { // Run the test iterations in parallel. Each thread gets a string buffer to write // its check values to. - let res = gen.par_bridge().try_for_each_init(String::new, check_one); + let res = gen_.par_bridge().try_for_each_init(String::new, check_one); let elapsed = started.elapsed(); let executed = executed.into_inner(); -- cgit 1.4.1-3-g733a5