@@ -29,9 +29,11 @@ mod gen {
29
29
pub mod subnorm;
30
30
}
31
31
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 ;
35
37
36
38
/// If there are more tests than this threashold, the test will be defered until after all
37
39
/// 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";
46
48
pub struct Config {
47
49
pub timeout : Duration ,
48
50
/// 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
50
54
pub fuzz_count : Option < u64 > ,
51
55
pub skip_huge : bool ,
52
56
}
53
57
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
+
54
70
/// Collect, filter, and launch all tests.
55
71
pub 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
-
58
72
// With default parallelism, the CPU doesn't saturate. We don't need to be nice to
59
73
// other processes, so do 1.5x to make sure we use all available resources.
60
74
let threads = std:: thread:: available_parallelism ( ) . map ( Into :: into) . unwrap_or ( 0 ) * 3 / 2 ;
61
75
rayon:: ThreadPoolBuilder :: new ( ) . num_threads ( threads) . build_global ( ) . unwrap ( ) ;
62
76
63
- let mut tests = register_tests ( ) ;
77
+ let mut tests = register_tests ( & cfg) ;
78
+ println ! ( "registered" ) ;
64
79
let initial_tests: Vec < _ > = tests. iter ( ) . map ( |t| t. name . clone ( ) ) . collect ( ) ;
65
80
66
81
let unmatched: Vec < _ > = include
@@ -89,20 +104,18 @@ pub fn run(cfg: Config, include: &[String], exclude: &[String]) -> ExitCode {
89
104
println ! ( "Skipping test '{exc}'" ) ;
90
105
}
91
106
107
+ println ! ( "launching" ) ;
92
108
let elapsed = launch_tests ( & mut tests, & cfg) ;
93
109
ui:: finish ( & tests, elapsed, & cfg)
94
110
}
95
111
96
112
/// 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 > {
98
114
let mut tests = Vec :: new ( ) ;
99
115
100
116
// 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) ;
106
119
107
120
tests. sort_unstable_by_key ( |t| ( t. float_name , t. gen_name ) ) ;
108
121
for i in 0 ..( tests. len ( ) - 1 ) {
@@ -115,12 +128,19 @@ pub fn register_tests() -> Vec<TestInfo> {
115
128
}
116
129
117
130
/// 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 )
119
132
where
120
133
RangeInclusive < F :: Int > : Iterator < Item = F :: Int > ,
121
134
<F :: Int as TryFrom < u128 > >:: Error : std:: fmt:: Debug ,
122
135
Standard : Distribution < <F as traits:: Float >:: Int > ,
123
136
{
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
+
124
144
TestInfo :: register :: < F , gen:: exponents:: LargeExponents < F > > ( tests) ;
125
145
TestInfo :: register :: < F , gen:: exponents:: SmallExponents < F > > ( tests) ;
126
146
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
451
471
buf. clear ( ) ;
452
472
G :: write_string ( buf, ctx) ;
453
473
454
- match validate:: validate :: < F > ( buf, G :: PATTERNS_CONTAIN_NAN ) {
474
+ match validate:: validate :: < F > ( buf) {
455
475
Ok ( ( ) ) => ( ) ,
456
476
Err ( e) => {
457
477
tx. send ( Msg :: new :: < F , G > ( e) ) . unwrap ( ) ;
458
478
let f = failures. fetch_add ( 1 , Ordering :: Relaxed ) ;
459
479
// End early if the limit is exceeded.
460
- if cfg . max_failures . map_or ( false , |mf| f >= mf ) {
480
+ if f >= cfg . max_failures {
461
481
return Err ( EarlyExit :: MaxFailures ) ;
462
482
}
463
483
}
0 commit comments