@@ -29,9 +29,11 @@ mod gen {
2929 pub mod subnorm;
3030}
3131
32- /// Fuzz iterations to run if not specified by CLI arg. By default, test as many conditions
33- /// as the `f32` exhaustive test.
34- pub const DEFAULT_FUZZ_COUNT : u64 = u32:: MAX as u64 ;
32+ /// How many failures to exit after if unspecified.
33+ const DEFAULT_MAX_FAILURES : u64 = 20 ;
34+
35+ /// Register exhaustive tests only for <= 32 bits. No more because it would take years.
36+ const MAX_BITS_FOR_EXHAUUSTIVE : u32 = 32 ;
3537
3638/// If there are more tests than this threashold, the test will be defered until after all
3739/// others run (so as to avoid thread pool starvation). They also can be excluded with
@@ -46,21 +48,34 @@ const SEED: [u8; 32] = *b"3.141592653589793238462643383279";
4648pub struct Config {
4749 pub timeout : Duration ,
4850 /// Failures per test
49- pub max_failures : Option < u64 > ,
51+ pub max_failures : u64 ,
52+ pub disable_max_failures : bool ,
53+ /// If `None`, the default will be used
5054 pub fuzz_count : Option < u64 > ,
5155 pub skip_huge : bool ,
5256}
5357
58+ impl Default for Config {
59+ fn default ( ) -> Self {
60+ Self {
61+ timeout : Duration :: from_secs ( 60 * 60 * 3 ) ,
62+ max_failures : DEFAULT_MAX_FAILURES ,
63+ disable_max_failures : false ,
64+ fuzz_count : None ,
65+ skip_huge : false ,
66+ }
67+ }
68+ }
69+
5470/// Collect, filter, and launch all tests.
5571pub fn run ( cfg : Config , include : & [ String ] , exclude : & [ String ] ) -> ExitCode {
56- gen:: fuzz:: FUZZ_COUNT . store ( cfg. fuzz_count . unwrap_or ( u64:: MAX ) , Ordering :: Relaxed ) ;
57-
5872 // With default parallelism, the CPU doesn't saturate. We don't need to be nice to
5973 // other processes, so do 1.5x to make sure we use all available resources.
6074 let threads = std:: thread:: available_parallelism ( ) . map ( Into :: into) . unwrap_or ( 0 ) * 3 / 2 ;
6175 rayon:: ThreadPoolBuilder :: new ( ) . num_threads ( threads) . build_global ( ) . unwrap ( ) ;
6276
63- let mut tests = register_tests ( ) ;
77+ let mut tests = register_tests ( & cfg) ;
78+ println ! ( "registered" ) ;
6479 let initial_tests: Vec < _ > = tests. iter ( ) . map ( |t| t. name . clone ( ) ) . collect ( ) ;
6580
6681 let unmatched: Vec < _ > = include
@@ -89,20 +104,18 @@ pub fn run(cfg: Config, include: &[String], exclude: &[String]) -> ExitCode {
89104 println ! ( "Skipping test '{exc}'" ) ;
90105 }
91106
107+ println ! ( "launching" ) ;
92108 let elapsed = launch_tests ( & mut tests, & cfg) ;
93109 ui:: finish ( & tests, elapsed, & cfg)
94110}
95111
96112/// Enumerate tests to run but don't actaully run them.
97- pub fn register_tests ( ) -> Vec < TestInfo > {
113+ pub fn register_tests ( cfg : & Config ) -> Vec < TestInfo > {
98114 let mut tests = Vec :: new ( ) ;
99115
100116 // Register normal generators for all floats.
101- register_float :: < f32 > ( & mut tests) ;
102- register_float :: < f64 > ( & mut tests) ;
103-
104- // Register exhaustive tests for <= 32 bits. No more because it would take years.
105- TestInfo :: register :: < f32 , gen:: exhaustive:: Exhaustive < f32 > > ( & mut tests) ;
117+ register_float :: < f32 > ( & mut tests, cfg) ;
118+ register_float :: < f64 > ( & mut tests, cfg) ;
106119
107120 tests. sort_unstable_by_key ( |t| ( t. float_name , t. gen_name ) ) ;
108121 for i in 0 ..( tests. len ( ) - 1 ) {
@@ -115,12 +128,19 @@ pub fn register_tests() -> Vec<TestInfo> {
115128}
116129
117130/// Register all generators for a single float.
118- fn register_float < F : Float > ( tests : & mut Vec < TestInfo > )
131+ fn register_float < F : Float > ( tests : & mut Vec < TestInfo > , cfg : & Config )
119132where
120133 RangeInclusive < F :: Int > : Iterator < Item = F :: Int > ,
121134 <F :: Int as TryFrom < u128 > >:: Error : std:: fmt:: Debug ,
122135 Standard : Distribution < <F as traits:: Float >:: Int > ,
123136{
137+ if F :: BITS <= MAX_BITS_FOR_EXHAUUSTIVE {
138+ // Only run exhaustive tests if there is a chance of completion.
139+ TestInfo :: register :: < F , gen:: exhaustive:: Exhaustive < F > > ( tests) ;
140+ }
141+
142+ gen:: fuzz:: Fuzz :: < F > :: set_iterations ( cfg. fuzz_count ) ;
143+
124144 TestInfo :: register :: < F , gen:: exponents:: LargeExponents < F > > ( tests) ;
125145 TestInfo :: register :: < F , gen:: exponents:: SmallExponents < F > > ( tests) ;
126146 TestInfo :: register :: < F , gen:: fuzz:: Fuzz < F > > ( tests) ;
@@ -451,13 +471,13 @@ fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestIn
451471 buf. clear ( ) ;
452472 G :: write_string ( buf, ctx) ;
453473
454- match validate:: validate :: < F > ( buf, G :: PATTERNS_CONTAIN_NAN ) {
474+ match validate:: validate :: < F > ( buf) {
455475 Ok ( ( ) ) => ( ) ,
456476 Err ( e) => {
457477 tx. send ( Msg :: new :: < F , G > ( e) ) . unwrap ( ) ;
458478 let f = failures. fetch_add ( 1 , Ordering :: Relaxed ) ;
459479 // End early if the limit is exceeded.
460- if cfg . max_failures . map_or ( false , |mf| f >= mf ) {
480+ if f >= cfg . max_failures {
461481 return Err ( EarlyExit :: MaxFailures ) ;
462482 }
463483 }
0 commit comments