@@ -553,11 +553,27 @@ mod tests {
553553 assert_eq ! ( & buf, & expected) ;
554554 }
555555
556- fn arbitrary_json ( keyspace : & ' static str ) -> impl Strategy < Value = serde_json:: Value > {
556+ /// As it says, generate arbitrary JSON. This is based on
557+ /// https://proptest-rs.github.io/proptest/proptest/tutorial/recursive.html
558+ ///
559+ /// We support controlling the regex for keys, and whether or not floating point values are emitted.
560+ fn arbitrary_json (
561+ keyspace : & ' static str ,
562+ allow_fp : bool ,
563+ ) -> impl Strategy < Value = serde_json:: Value > {
557564 use serde_json:: Value ;
558565 let leaf = prop_oneof ! [
559566 Just ( Value :: Null ) ,
560- any:: <u32 >( ) . prop_map( |v| Value :: Number ( Number :: from_u128( v. into( ) ) . unwrap( ) ) ) ,
567+ any:: <f64 >( ) . prop_filter_map( "valid f64 for JSON" , move |v| {
568+ let n = if allow_fp && v. fract( ) != 0.0 {
569+ Number :: from_f64( v) . unwrap( )
570+ } else {
571+ // Constrain to values clearly lower than
572+ // the https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
573+ Number :: from_u128( v as u32 as u128 ) . unwrap( )
574+ } ;
575+ Some ( Value :: Number ( n) )
576+ } ) ,
561577 any:: <bool >( ) . prop_map( Value :: Bool ) ,
562578 keyspace. prop_map( Value :: String ) ,
563579 ] ;
@@ -578,7 +594,7 @@ mod tests {
578594
579595 proptest ! {
580596 #[ test]
581- fn roundtrip_rfc8785( v in arbitrary_json( ".*" ) ) {
597+ fn roundtrip_rfc8785( v in arbitrary_json( ".*" , true ) ) {
582598 let buf = encode!( & v) . unwrap( ) ;
583599 let v2: serde_json:: Value = serde_json:: from_slice( & buf)
584600 . map_err( |e| format!( "Failed to parse {v:?} -> {}: {e}" , String :: from_utf8_lossy( & buf) ) ) . unwrap( ) ;
@@ -684,7 +700,7 @@ mod tests {
684700 proptest ! {
685701 // Verify strict equivalency with printable ASCII only keys
686702 #[ test]
687- fn crosscheck_olpc_cjson_ascii( v in arbitrary_json( ASCII_ALPHANUMERIC ) ) {
703+ fn crosscheck_olpc_cjson_ascii( v in arbitrary_json( ASCII_ALPHANUMERIC , false ) ) {
688704 let canon_json = String :: from_utf8( encode!( & v) . unwrap( ) ) . unwrap( ) ;
689705 let mut olpc_cjson_serialized = Vec :: new( ) ;
690706 let mut ser = serde_json:: Serializer :: with_formatter( & mut olpc_cjson_serialized, olpc_cjson:: CanonicalFormatter :: new( ) ) ;
@@ -696,15 +712,15 @@ mod tests {
696712 proptest ! {
697713 // Verify strict equivalency with printable ASCII only keys
698714 #[ test]
699- fn crosscheck_cjson_ascii( v in arbitrary_json( ASCII_ALPHANUMERIC ) ) {
715+ fn crosscheck_cjson_ascii( v in arbitrary_json( ASCII_ALPHANUMERIC , false ) ) {
700716 let canon_json = String :: from_utf8( encode!( & v) . unwrap( ) ) . unwrap( ) ;
701717 let cjson = String :: from_utf8( cjson:: to_vec( & v) . unwrap( ) ) . unwrap( ) ;
702718 assert_eq!( canon_json, cjson) ;
703719 }
704720
705721 // Verify equivalency (after sorting) with non-ASCII keys
706722 #[ test]
707- fn crosscheck_cjson( v in arbitrary_json( ".*" ) ) {
723+ fn crosscheck_cjson( v in arbitrary_json( ".*" , false ) ) {
708724 let buf = encode!( & v) . unwrap( ) ;
709725 let self_reparsed = serde_json:: from_slice:: <serde_json:: Value >( & buf) . unwrap( ) ;
710726 let buf = cjson:: to_vec( & v) . unwrap( ) ;
0 commit comments