Skip to content

Commit de391b8

Browse files
authored
Merge pull request #5 from champtar/tests
Use CanonJsonSerialize in tests
2 parents d58fab4 + 69a48fc commit de391b8

File tree

2 files changed

+44
-29
lines changed

2 files changed

+44
-29
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ cap-std = "3.4.4"
2020
sha2 = "0.10.9"
2121
# For cross-integration testing
2222
olpc-cjson = "0.1"
23+
cjson = "0.1.2"

src/lib.rs

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ where
372372
where
373373
W: Write,
374374
{
375-
let mut ser = serde_json::Serializer::with_formatter(writer, CanonicalFormatter::new());
375+
let mut ser = Serializer::with_formatter(writer, CanonicalFormatter::new());
376376
Ok(self.serialize(&mut ser)?)
377377
}
378378

@@ -395,8 +395,7 @@ mod tests {
395395
use std::{cmp::Ordering, io::Result};
396396

397397
use proptest::prelude::*;
398-
use serde::Serialize;
399-
use serde_json::{Number, Serializer};
398+
use serde_json::Number;
400399
use sha2::{Digest, Sha256};
401400
use similar_asserts::assert_eq;
402401

@@ -427,10 +426,7 @@ mod tests {
427426
macro_rules! encode {
428427
($($tt:tt)+) => {
429428
(|v: serde_json::Value| -> Result<Vec<u8>> {
430-
let mut buf = Vec::new();
431-
let mut ser = Serializer::with_formatter(&mut buf, CanonicalFormatter::new());
432-
v.serialize(&mut ser)?;
433-
Ok(buf)
429+
v.to_canon_json_vec()
434430
})(serde_json::json!($($tt)+))
435431
};
436432
}
@@ -538,10 +534,6 @@ mod tests {
538534
i128: i128::MIN,
539535
};
540536

541-
let mut buf = Vec::new();
542-
let mut ser = Serializer::with_formatter(&mut buf, CanonicalFormatter::new());
543-
value.serialize(&mut ser).unwrap();
544-
545537
let expected = [
546538
123, 34, 105, 49, 50, 56, 34, 58, 45, 49, 55, 48, 49, 52, 49, 49, 56, 51, 52, 54, 48,
547539
52, 54, 57, 50, 51, 49, 55, 51, 49, 54, 56, 55, 51, 48, 51, 55, 49, 53, 56, 56, 52, 49,
@@ -550,7 +542,7 @@ mod tests {
550542
55, 54, 56, 50, 49, 49, 52, 53, 53, 125,
551543
];
552544

553-
assert_eq!(buf, expected);
545+
assert_eq!(value.to_canon_json_vec().unwrap(), expected);
554546
}
555547

556548
#[test]
@@ -561,24 +553,23 @@ mod tests {
561553
assert_eq!(&buf, &expected);
562554
}
563555

564-
fn arbitrary_json() -> impl Strategy<Value = serde_json::Value> {
556+
fn arbitrary_json(keyspace: &'static str) -> impl Strategy<Value = serde_json::Value> {
565557
use serde_json::Value;
566-
const S: &str = ".*";
567558
let leaf = prop_oneof![
568559
Just(Value::Null),
569560
any::<u32>().prop_map(|v| Value::Number(Number::from_u128(v.into()).unwrap())),
570561
any::<bool>().prop_map(Value::Bool),
571-
S.prop_map(Value::String),
562+
keyspace.prop_map(Value::String),
572563
];
573564
leaf.prop_recursive(
574565
8, // 8 levels deep
575566
256, // Shoot for maximum size of 256 nodes
576567
10, // We put up to 10 items per collection
577-
|inner| {
568+
move |inner| {
578569
prop_oneof![
579570
// Take the inner strategy and make the two recursive cases.
580571
prop::collection::vec(inner.clone(), 0..10).prop_map(Value::Array),
581-
prop::collection::hash_map(S, inner, 0..10)
572+
prop::collection::hash_map(keyspace, inner, 0..10)
582573
.prop_map(|v| { v.into_iter().collect() }),
583574
]
584575
},
@@ -587,7 +578,7 @@ mod tests {
587578

588579
proptest! {
589580
#[test]
590-
fn roundtrip_rfc8785(v in arbitrary_json()) {
581+
fn roundtrip_rfc8785(v in arbitrary_json(".*")) {
591582
let buf = encode!(&v).unwrap();
592583
let v2: serde_json::Value = serde_json::from_slice(&buf)
593584
.map_err(|e| format!("Failed to parse {v:?} -> {}: {e}", String::from_utf8_lossy(&buf))).unwrap();
@@ -597,11 +588,7 @@ mod tests {
597588

598589
fn verify(input: &str, expected: &str) {
599590
let input: serde_json::Value = serde_json::from_str(input).unwrap();
600-
let mut buf = Vec::new();
601-
let mut ser = Serializer::with_formatter(&mut buf, CanonicalFormatter::new());
602-
input.serialize(&mut ser).unwrap();
603-
let buf = String::from_utf8(buf).unwrap();
604-
assert_eq!(expected, &buf);
591+
assert_eq!(expected, input.to_canon_json_string().unwrap());
605592
}
606593

607594
#[test]
@@ -688,17 +675,44 @@ mod tests {
688675
Ok(())
689676
}
690677

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+
691684
proptest! {
685+
// Verify strict equivalency with printable ASCII only keys
692686
#[test]
693-
fn crosscheck_olpc_cjson(v in arbitrary_json()) {
694-
use olpc_cjson::CanonicalFormatter;
695-
687+
fn crosscheck_olpc_cjson_ascii(v in arbitrary_json(ASCII_ALPHANUMERIC)) {
688+
let canon_json = String::from_utf8(encode!(&v).unwrap()).unwrap();
696689
let mut olpc_cjson_serialized = Vec::new();
697-
let mut ser = serde_json::Serializer::with_formatter(&mut olpc_cjson_serialized, CanonicalFormatter::new());
698-
prop_assume!(v.serialize(&mut ser).is_ok());
690+
let mut ser = serde_json::Serializer::with_formatter(&mut olpc_cjson_serialized, olpc_cjson::CanonicalFormatter::new());
691+
v.serialize(&mut ser).unwrap();
692+
assert_eq!(canon_json, String::from_utf8(olpc_cjson_serialized).unwrap());
693+
}
694+
}
695+
696+
proptest! {
697+
// Verify strict equivalency with printable ASCII only keys
698+
#[test]
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+
}
699704

705+
// Verify equivalency (after sorting) with non-ASCII keys
706+
#[test]
707+
fn crosscheck_cjson(v in arbitrary_json(".*")) {
700708
let buf = encode!(&v).unwrap();
701-
assert_eq!(buf, olpc_cjson_serialized);
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);
702716
}
703717
}
704718
}

0 commit comments

Comments
 (0)