#[expect(dead_code, reason = "roundtrip-only helpers are unused here")]
mod pbt_harness;
use std::cell::Cell;
use std::collections::BTreeMap;
use nojson::Json;
use pbt_harness::{MAX_LEN, needs_escape, run, sample_len, sample_string_arbitrary, sample_vec};
fn sample_pretty_settings(ctx: &mut noprop::TestCaseContext) -> (usize, bool) {
let indent = noprop::sample_choice(ctx, &[0usize, 1, 2, 4, 8]);
let spacing = noprop::sample_bool(ctx);
(indent, spacing)
}
#[test]
fn pretty_roundtrip_nested() -> noprop::TestResult {
let spacing_cases = Cell::new(0usize);
let indented_cases = Cell::new(0usize);
run(|ctx| {
let (indent, spacing) = sample_pretty_settings(ctx);
let v = sample_vec(ctx, |ctx| {
let n = sample_len(ctx, MAX_LEN);
let mut m = BTreeMap::new();
for _ in 0..n {
m.insert(
sample_string_arbitrary(ctx),
sample_vec(ctx, noprop::sample_i32),
);
}
m
});
let text = nojson::json(|f| {
f.set_indent_size(indent);
f.set_spacing(spacing);
f.value(&v)
})
.to_string();
let parsed: Json<Vec<BTreeMap<String, Vec<i32>>>> = text.parse()?;
assert_eq!(parsed.0, v);
if spacing {
spacing_cases.set(spacing_cases.get() + 1);
}
if indent > 0 {
indented_cases.set(indented_cases.get() + 1);
}
Ok(())
})?;
assert!(
spacing_cases.get() > 0,
"no case pretty-printed with set_spacing(true)"
);
assert!(
indented_cases.get() > 0,
"no case pretty-printed with a non-zero indent size"
);
Ok(())
}
#[test]
fn pretty_roundtrip_string() -> noprop::TestResult {
let escape_cases = Cell::new(0usize);
run(|ctx| {
let (indent, spacing) = sample_pretty_settings(ctx);
let s = sample_string_arbitrary(ctx);
let text = nojson::json(|f| {
f.set_indent_size(indent);
f.set_spacing(spacing);
f.value(&s)
})
.to_string();
let parsed: Json<String> = text.parse()?;
assert_eq!(parsed.0, s);
if s.chars().any(needs_escape) {
escape_cases.set(escape_cases.get() + 1);
}
Ok(())
})?;
assert!(
escape_cases.get() > 0,
"no case pretty-printed a string that requires JSON escaping"
);
Ok(())
}