3
3
use alloy_json_abi:: Function ;
4
4
use alloy_primitives:: Bytes ;
5
5
use alloy_sol_types:: SolError ;
6
- use std:: path:: Path ;
6
+ use std:: { fmt , path:: Path } ;
7
7
8
8
/// Test filter.
9
9
pub trait TestFilter : Send + Sync {
@@ -19,116 +19,208 @@ pub trait TestFilter: Send + Sync {
19
19
20
20
/// Extension trait for `Function`.
21
21
pub trait TestFunctionExt {
22
- /// Returns whether this function should be executed as invariant test.
23
- fn is_invariant_test ( & self ) -> bool ;
24
-
25
- /// Returns whether this function should be executed as fuzz test.
26
- fn is_fuzz_test ( & self ) -> bool ;
22
+ /// Returns the kind of test function.
23
+ fn test_function_kind ( & self ) -> TestFunctionKind {
24
+ TestFunctionKind :: classify ( self . tfe_as_str ( ) , self . tfe_has_inputs ( ) )
25
+ }
27
26
28
- /// Returns whether this function is a test.
29
- fn is_test ( & self ) -> bool ;
27
+ /// Returns `true` if this function is a `setUp` function.
28
+ fn is_setup ( & self ) -> bool {
29
+ self . test_function_kind ( ) . is_setup ( )
30
+ }
30
31
31
- /// Returns whether this function is a test that should fail.
32
- fn is_test_fail ( & self ) -> bool ;
32
+ /// Returns `true` if this function is a unit, fuzz, or invariant test.
33
+ fn is_any_test ( & self ) -> bool {
34
+ self . test_function_kind ( ) . is_any_test ( )
35
+ }
33
36
34
- /// Returns whether this function is a `setUp` function.
35
- fn is_setup ( & self ) -> bool ;
37
+ /// Returns `true` if this function is a test that should fail.
38
+ fn is_any_test_fail ( & self ) -> bool {
39
+ self . test_function_kind ( ) . is_any_test_fail ( )
40
+ }
36
41
37
- /// Returns whether this function is `afterInvariant` function.
38
- fn is_after_invariant ( & self ) -> bool ;
42
+ /// Returns `true` if this function is a unit test.
43
+ fn is_unit_test ( & self ) -> bool {
44
+ matches ! ( self . test_function_kind( ) , TestFunctionKind :: UnitTest { .. } )
45
+ }
39
46
40
- /// Returns whether this function is a fixture function.
41
- fn is_fixture ( & self ) -> bool ;
42
- }
47
+ /// Returns `true` if this function is a fuzz test.
48
+ fn is_fuzz_test ( & self ) -> bool {
49
+ self . test_function_kind ( ) . is_fuzz_test ( )
50
+ }
43
51
44
- impl TestFunctionExt for Function {
52
+ /// Returns `true` if this function is an invariant test.
45
53
fn is_invariant_test ( & self ) -> bool {
46
- self . name . is_invariant_test ( )
54
+ self . test_function_kind ( ) . is_invariant_test ( )
47
55
}
48
56
49
- fn is_fuzz_test ( & self ) -> bool {
50
- // test functions that have inputs are considered fuzz tests as those inputs will be fuzzed
51
- ! self . inputs . is_empty ( )
57
+ /// Returns `true` if this function is an `afterInvariant` function.
58
+ fn is_after_invariant ( & self ) -> bool {
59
+ self . test_function_kind ( ) . is_after_invariant ( )
52
60
}
53
61
54
- fn is_test ( & self ) -> bool {
55
- self . name . is_test ( )
62
+ /// Returns `true` if this function is a `fixture` function.
63
+ fn is_fixture ( & self ) -> bool {
64
+ self . test_function_kind ( ) . is_fixture ( )
56
65
}
57
66
58
- fn is_test_fail ( & self ) -> bool {
59
- self . name . is_test_fail ( )
67
+ #[ doc( hidden) ]
68
+ fn tfe_as_str ( & self ) -> & str ;
69
+ #[ doc( hidden) ]
70
+ fn tfe_has_inputs ( & self ) -> bool ;
71
+ }
72
+
73
+ impl TestFunctionExt for Function {
74
+ fn tfe_as_str ( & self ) -> & str {
75
+ self . name . as_str ( )
60
76
}
61
77
62
- fn is_setup ( & self ) -> bool {
63
- self . name . is_setup ( )
78
+ fn tfe_has_inputs ( & self ) -> bool {
79
+ ! self . inputs . is_empty ( )
64
80
}
81
+ }
65
82
66
- fn is_after_invariant ( & self ) -> bool {
67
- self . name . is_after_invariant ( )
83
+ impl TestFunctionExt for String {
84
+ fn tfe_as_str ( & self ) -> & str {
85
+ self
68
86
}
69
87
70
- fn is_fixture ( & self ) -> bool {
71
- self . name . is_fixture ( )
88
+ fn tfe_has_inputs ( & self ) -> bool {
89
+ false
72
90
}
73
91
}
74
92
75
- impl TestFunctionExt for String {
76
- fn is_invariant_test ( & self ) -> bool {
77
- self . as_str ( ) . is_invariant_test ( )
93
+ impl TestFunctionExt for str {
94
+ fn tfe_as_str ( & self ) -> & str {
95
+ self
78
96
}
79
97
80
- fn is_fuzz_test ( & self ) -> bool {
81
- self . as_str ( ) . is_fuzz_test ( )
98
+ fn tfe_has_inputs ( & self ) -> bool {
99
+ false
82
100
}
101
+ }
102
+
103
+ /// Test function kind.
104
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
105
+ pub enum TestFunctionKind {
106
+ /// `setUp`.
107
+ Setup ,
108
+ /// `test*`. `should_fail` is `true` for `testFail*`.
109
+ UnitTest { should_fail : bool } ,
110
+ /// `test*`, with arguments. `should_fail` is `true` for `testFail*`.
111
+ FuzzTest { should_fail : bool } ,
112
+ /// `invariant*` or `statefulFuzz*`.
113
+ InvariantTest ,
114
+ /// `afterInvariant`.
115
+ AfterInvariant ,
116
+ /// `fixture*`.
117
+ Fixture ,
118
+ /// Unknown kind.
119
+ Unknown ,
120
+ }
83
121
84
- fn is_test ( & self ) -> bool {
85
- self . as_str ( ) . is_test ( )
122
+ impl TestFunctionKind {
123
+ /// Classify a function.
124
+ #[ inline]
125
+ pub fn classify ( name : & str , has_inputs : bool ) -> Self {
126
+ match ( ) {
127
+ _ if name. starts_with ( "test" ) => {
128
+ let should_fail = name. starts_with ( "testFail" ) ;
129
+ if has_inputs {
130
+ Self :: FuzzTest { should_fail }
131
+ } else {
132
+ Self :: UnitTest { should_fail }
133
+ }
134
+ }
135
+ _ if name. starts_with ( "invariant" ) || name. starts_with ( "statefulFuzz" ) => {
136
+ Self :: InvariantTest
137
+ }
138
+ _ if name. eq_ignore_ascii_case ( "setup" ) => Self :: Setup ,
139
+ _ if name. eq_ignore_ascii_case ( "afterinvariant" ) => Self :: AfterInvariant ,
140
+ _ if name. starts_with ( "fixture" ) => Self :: Fixture ,
141
+ _ => Self :: Unknown ,
142
+ }
86
143
}
87
144
88
- fn is_test_fail ( & self ) -> bool {
89
- self . as_str ( ) . is_test_fail ( )
145
+ /// Returns the name of the function kind.
146
+ pub const fn name ( & self ) -> & ' static str {
147
+ match self {
148
+ Self :: Setup => "setUp" ,
149
+ Self :: UnitTest { should_fail : false } => "test" ,
150
+ Self :: UnitTest { should_fail : true } => "testFail" ,
151
+ Self :: FuzzTest { should_fail : false } => "fuzz" ,
152
+ Self :: FuzzTest { should_fail : true } => "fuzz fail" ,
153
+ Self :: InvariantTest => "invariant" ,
154
+ Self :: AfterInvariant => "afterInvariant" ,
155
+ Self :: Fixture => "fixture" ,
156
+ Self :: Unknown => "unknown" ,
157
+ }
90
158
}
91
159
92
- fn is_setup ( & self ) -> bool {
93
- self . as_str ( ) . is_setup ( )
160
+ /// Returns `true` if this function is a `setUp` function.
161
+ #[ inline]
162
+ pub const fn is_setup ( & self ) -> bool {
163
+ matches ! ( self , Self :: Setup )
94
164
}
95
165
96
- fn is_after_invariant ( & self ) -> bool {
97
- self . as_str ( ) . is_after_invariant ( )
166
+ /// Returns `true` if this function is a unit, fuzz, or invariant test.
167
+ #[ inline]
168
+ pub const fn is_any_test ( & self ) -> bool {
169
+ matches ! ( self , Self :: UnitTest { .. } | Self :: FuzzTest { .. } | Self :: InvariantTest )
98
170
}
99
171
100
- fn is_fixture ( & self ) -> bool {
101
- self . as_str ( ) . is_fixture ( )
172
+ /// Returns `true` if this function is a test that should fail.
173
+ #[ inline]
174
+ pub const fn is_any_test_fail ( & self ) -> bool {
175
+ matches ! ( self , Self :: UnitTest { should_fail: true } | Self :: FuzzTest { should_fail: true } )
102
176
}
103
- }
104
177
105
- impl TestFunctionExt for str {
106
- fn is_invariant_test ( & self ) -> bool {
107
- self . starts_with ( "invariant" ) || self . starts_with ( "statefulFuzz" )
178
+ /// Returns `true` if this function is a unit test.
179
+ #[ inline]
180
+ pub fn is_unit_test ( & self ) -> bool {
181
+ matches ! ( self , Self :: UnitTest { .. } )
108
182
}
109
183
110
- fn is_fuzz_test ( & self ) -> bool {
111
- unimplemented ! ( "no naming convention for fuzz tests" )
184
+ /// Returns `true` if this function is a fuzz test.
185
+ #[ inline]
186
+ pub const fn is_fuzz_test ( & self ) -> bool {
187
+ matches ! ( self , Self :: FuzzTest { .. } )
112
188
}
113
189
114
- fn is_test ( & self ) -> bool {
115
- self . starts_with ( "test" )
190
+ /// Returns `true` if this function is an invariant test.
191
+ #[ inline]
192
+ pub const fn is_invariant_test ( & self ) -> bool {
193
+ matches ! ( self , Self :: InvariantTest )
116
194
}
117
195
118
- fn is_test_fail ( & self ) -> bool {
119
- self . starts_with ( "testFail" )
196
+ /// Returns `true` if this function is an `afterInvariant` function.
197
+ #[ inline]
198
+ pub const fn is_after_invariant ( & self ) -> bool {
199
+ matches ! ( self , Self :: AfterInvariant )
120
200
}
121
201
122
- fn is_setup ( & self ) -> bool {
123
- self . eq_ignore_ascii_case ( "setup" )
202
+ /// Returns `true` if this function is a `fixture` function.
203
+ #[ inline]
204
+ pub const fn is_fixture ( & self ) -> bool {
205
+ matches ! ( self , Self :: Fixture )
124
206
}
125
207
126
- fn is_after_invariant ( & self ) -> bool {
127
- self . eq_ignore_ascii_case ( "afterinvariant" )
208
+ /// Returns `true` if this function kind is known.
209
+ #[ inline]
210
+ pub const fn is_known ( & self ) -> bool {
211
+ !matches ! ( self , Self :: Unknown )
128
212
}
129
213
130
- fn is_fixture ( & self ) -> bool {
131
- self . starts_with ( "fixture" )
214
+ /// Returns `true` if this function kind is unknown.
215
+ #[ inline]
216
+ pub const fn is_unknown ( & self ) -> bool {
217
+ matches ! ( self , Self :: Unknown )
218
+ }
219
+ }
220
+
221
+ impl fmt:: Display for TestFunctionKind {
222
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
223
+ self . name ( ) . fmt ( f)
132
224
}
133
225
}
134
226
0 commit comments