@@ -395,7 +395,6 @@ mod tests {
395395 use std:: { cmp:: Ordering , io:: Result } ;
396396
397397 use proptest:: prelude:: * ;
398- use serde:: Serialize ;
399398 use serde_json:: Number ;
400399 use sha2:: { Digest , Sha256 } ;
401400 use similar_asserts:: assert_eq;
@@ -554,24 +553,23 @@ mod tests {
554553 assert_eq ! ( & buf, & expected) ;
555554 }
556555
557- fn arbitrary_json ( ) -> impl Strategy < Value = serde_json:: Value > {
556+ fn arbitrary_json ( keyspace : & ' static str ) -> impl Strategy < Value = serde_json:: Value > {
558557 use serde_json:: Value ;
559- const S : & str = ".*" ;
560558 let leaf = prop_oneof ! [
561559 Just ( Value :: Null ) ,
562560 any:: <u32 >( ) . prop_map( |v| Value :: Number ( Number :: from_u128( v. into( ) ) . unwrap( ) ) ) ,
563561 any:: <bool >( ) . prop_map( Value :: Bool ) ,
564- S . prop_map( Value :: String ) ,
562+ keyspace . prop_map( Value :: String ) ,
565563 ] ;
566564 leaf. prop_recursive (
567565 8 , // 8 levels deep
568566 256 , // Shoot for maximum size of 256 nodes
569567 10 , // We put up to 10 items per collection
570- |inner| {
568+ move |inner| {
571569 prop_oneof ! [
572570 // Take the inner strategy and make the two recursive cases.
573571 prop:: collection:: vec( inner. clone( ) , 0 ..10 ) . prop_map( Value :: Array ) ,
574- prop:: collection:: hash_map( S , inner, 0 ..10 )
572+ prop:: collection:: hash_map( keyspace , inner, 0 ..10 )
575573 . prop_map( |v| { v. into_iter( ) . collect( ) } ) ,
576574 ]
577575 } ,
@@ -580,7 +578,7 @@ mod tests {
580578
581579 proptest ! {
582580 #[ test]
583- fn roundtrip_rfc8785( v in arbitrary_json( ) ) {
581+ fn roundtrip_rfc8785( v in arbitrary_json( ".*" ) ) {
584582 let buf = encode!( & v) . unwrap( ) ;
585583 let v2: serde_json:: Value = serde_json:: from_slice( & buf)
586584 . map_err( |e| format!( "Failed to parse {v:?} -> {}: {e}" , String :: from_utf8_lossy( & buf) ) ) . unwrap( ) ;
@@ -677,24 +675,44 @@ mod tests {
677675 Ok ( ( ) )
678676 }
679677
678+ // Regex that excludes basically everything except printable ASCII
679+ // because we know that e.g. olpc-cjson bombs on control characters,
680+ // and also because it does NFC orering that will cause non-equivalency
681+ // for some whitespace etc.
682+ const ASCII_ALPHANUMERIC : & str = r"[a-zA-Z0-9]*" ;
683+
680684 proptest ! {
685+ // Verify strict equivalency with printable ASCII only keys
681686 #[ test]
682- # [ ignore = "broken (control char)" ]
683- fn crosscheck_olpc_cjson ( v in arbitrary_json ( ) ) {
687+ fn crosscheck_olpc_cjson_ascii ( v in arbitrary_json ( ASCII_ALPHANUMERIC ) ) {
688+ let canon_json = String :: from_utf8 ( encode! ( & v ) . unwrap ( ) ) . unwrap ( ) ;
684689 let mut olpc_cjson_serialized = Vec :: new( ) ;
685690 let mut ser = serde_json:: Serializer :: with_formatter( & mut olpc_cjson_serialized, olpc_cjson:: CanonicalFormatter :: new( ) ) ;
686- prop_assume!( v. serialize( & mut ser) . is_ok( ) ) ;
687-
688- let buf = encode!( & v) . unwrap( ) ;
689- assert_eq!( buf, olpc_cjson_serialized) ;
691+ v. serialize( & mut ser) . unwrap( ) ;
692+ assert_eq!( canon_json, String :: from_utf8( olpc_cjson_serialized) . unwrap( ) ) ;
690693 }
691694 }
692695
693696 proptest ! {
697+ // Verify strict equivalency with printable ASCII only keys
694698 #[ test]
695- #[ ignore = "broken (ordering)" ]
696- fn crosscheck_cjson( v in arbitrary_json( ) ) {
697- assert_eq!( v. to_canon_json_vec( ) . unwrap( ) , cjson:: to_vec( & v) . unwrap( ) ) ;
699+ fn crosscheck_cjson_ascii( v in arbitrary_json( ASCII_ALPHANUMERIC ) ) {
700+ let canon_json = String :: from_utf8( encode!( & v) . unwrap( ) ) . unwrap( ) ;
701+ let cjson = String :: from_utf8( cjson:: to_vec( & v) . unwrap( ) ) . unwrap( ) ;
702+ assert_eq!( canon_json, cjson) ;
703+ }
704+
705+ // Verify equivalency (after sorting) with non-ASCII keys
706+ #[ test]
707+ fn crosscheck_cjson( v in arbitrary_json( ".*" ) ) {
708+ let buf = encode!( & v) . unwrap( ) ;
709+ let self_reparsed = serde_json:: from_slice:: <serde_json:: Value >( & buf) . unwrap( ) ;
710+ let buf = cjson:: to_vec( & v) . unwrap( ) ;
711+ let cjson_reparsed = serde_json:: from_slice:: <serde_json:: Value >( & buf) . unwrap( ) ;
712+ // As above with olpc-cjson, this relies on the fact that serde_json
713+ // sorts object keys by default.
714+ assert_eq!( self_reparsed, v) ;
715+ assert_eq!( cjson_reparsed, v) ;
698716 }
699717 }
700718}
0 commit comments