@@ -84,13 +84,24 @@ fn fuzz_param_inner(
8484 DynSolType :: Function | DynSolType :: Bool => DynSolValue :: type_strategy ( param) . boxed ( ) ,
8585 DynSolType :: Bytes => value ( ) ,
8686 DynSolType :: FixedBytes ( _size @ 1 ..=32 ) => value ( ) ,
87- DynSolType :: String => value ( )
88- . prop_map ( move |value| {
87+ DynSolType :: String => {
88+ let default_strategy = DynSolValue :: type_strategy ( param ) . prop_map ( move |value| {
8989 DynSolValue :: String (
9090 value. as_str ( ) . unwrap ( ) . trim ( ) . trim_end_matches ( '\0' ) . to_string ( ) ,
9191 )
92- } )
93- . boxed ( ) ,
92+ } ) ;
93+ if let Some ( fixtures) = fuzz_fixtures {
94+ let fixtures = fixtures. to_vec ( ) ;
95+ proptest:: prop_oneof![
96+ 50 => any:: <prop:: sample:: Index >( )
97+ . prop_map( move |index| index. get( & fixtures) . clone( ) ) ,
98+ 50 => default_strategy,
99+ ]
100+ . boxed ( )
101+ } else {
102+ default_strategy. boxed ( )
103+ }
104+ }
94105 DynSolType :: Tuple ( ref params) => params
95106 . iter ( )
96107 . map ( |param| fuzz_param_inner ( param, None ) )
@@ -598,6 +609,22 @@ mod tests {
598609 ) ;
599610 }
600611
612+ #[ test]
613+ fn string_fixtures_are_emitted_verbatim ( ) {
614+ let fixture = DynSolValue :: String ( " padded fixture \0 " . to_string ( ) ) ;
615+ let strategy = super :: fuzz_param_with_fixtures (
616+ & DynSolType :: String ,
617+ Some ( std:: slice:: from_ref ( & fixture) ) ,
618+ "value" ,
619+ ) ;
620+ let mut runner = TestRunner :: deterministic ( ) ;
621+
622+ let emitted =
623+ ( 0 ..1000 ) . any ( |_| strategy. new_tree ( & mut runner) . unwrap ( ) . current ( ) == fixture) ;
624+
625+ assert ! ( emitted, "string fixture was never emitted verbatim" ) ;
626+ }
627+
601628 #[ test]
602629 fn can_fuzz_string_and_bytes_with_ast_literals_and_hashes ( ) {
603630 use super :: fuzz_param_from_state;
0 commit comments