use dever_runtime::wire::{self, document, json::Json, serde_json}; #[test] fn proven_fragments_keep_exact_counts_when_nested() { for count in [0, 1, document::MAX_VALUES - 2, document::MAX_VALUES - 1] { let values = vec![7i64; count]; let proven = Json::encode_proven(&values, count + 1, 1).unwrap(); let parsed = Json::parse(proven.as_str()).unwrap(); assert_eq!(Json::array(&[proven]), Json::array(&[parsed])); } let value = Json::encode_proven(&(), 1, 0).unwrap(); let mut wrapped = value; for _ in 0..document::MAX_DEPTH { wrapped = Json::array(&[wrapped]).unwrap(); } assert!(Json::array(&[wrapped]).is_err()); } #[test] fn typed_output_counts_values_and_response_envelope() { let maximum = vec![0i64; document::MAX_VALUES - 1]; let encoded = Json::encode(&maximum).unwrap(); assert_eq!(encoded.as_str(), serde_json::to_string(&maximum).unwrap()); assert!(Json::encode(&vec![0i64; document::MAX_VALUES]).is_err()); assert!(wire::response(&vec![0i64; document::MAX_VALUES - 4]).is_ok()); assert!(wire::response(&vec![0i64; document::MAX_VALUES - 3]).is_err()); } #[test] fn response_fragments_keep_the_envelope_and_its_budgets() { for source in ["null", "[1e9999,-0]", r#"{"text":"\u96ea"}"#] { let value = Json::parse(source).unwrap(); assert_eq!( wire::response_with(|output| output.json(&value)).unwrap(), format!("{{\"code\":0,\"message\":\"ok\",\"data\":{source}}}") ); } for count in [document::MAX_VALUES - 4, document::MAX_VALUES - 3] { let values = vec![0; count]; let value = Json::encode(&values).unwrap(); let output = wire::response_with(|output| output.json(&value)); assert_eq!(output.is_ok(), count == document::MAX_VALUES - 4); assert_eq!(output.is_ok(), wire::response(&values).is_ok()); } let prefix = wire::response_with(|output| output.value("")) .unwrap() .len(); let value = Json::string(&"x".repeat(document::MAX_BYTES - prefix)).unwrap(); assert_eq!( wire::response_with(|output| output.json(&value)) .unwrap() .len(), document::MAX_BYTES ); let value = Json::string(&"x".repeat(document::MAX_BYTES - prefix + 1)).unwrap(); assert!(wire::response_with(|output| output.json(&value)).is_err()); } #[test] fn raw_subtrees_consume_the_outer_depth_and_value_budgets() { let nested = "[".repeat(document::MAX_DEPTH) + &"]".repeat(document::MAX_DEPTH); let typed: serde_json::Value = serde_json::from_str(&nested).unwrap(); assert_eq!(Json::encode(&typed).unwrap().as_str(), nested); assert!(Json::encode(&vec![typed]).is_err()); for raw in [ Json::parse(&nested).unwrap(), serde_json::from_str(&nested).unwrap(), ] { assert_eq!( Json::encode_with(|output| output.json(&raw)) .unwrap() .as_str(), nested ); assert!(Json::array(&[raw]).is_err()); } let maximum = Json::encode(&vec![0i64; document::MAX_VALUES - 1]).unwrap(); assert!(Json::encode_with(|output| output.json(&maximum)).is_ok()); assert!(Json::array(&[maximum]).is_err()); let allowed = Json::encode(&vec![0i64; document::MAX_VALUES - 2]).unwrap(); assert!(Json::array(&[allowed]).is_ok()); } #[test] fn raw_output_keeps_spelling_and_rejects_invalid_object_keys() { let source = r#" {"雪": [1e9999, -0, "\u96ea"]} "#; let raw = Json::parse(source).unwrap(); assert_eq!( Json::array(&[raw]).unwrap().as_str(), format!("[{}]", source.trim()) ); let duplicate = serde_json::value::RawValue::from_string(r#"{"a":1,"\u0061":2}"#.into()).unwrap(); assert!(Json::encode(&duplicate).is_err()); let surrogate = serde_json::value::RawValue::from_string(r#""\ud800""#.into()).unwrap(); assert!(Json::encode(&surrogate).is_err()); } #[test] fn raw_arrays_match_serde_for_empty_and_mixed_inputs() { let sources = [" null ", " [1e9999,-0] ", r#" {"雪":"\u96ea"} "#, " [] "]; for count in [0, 1, 4, 16] { let sources: Vec<_> = sources.into_iter().cycle().take(count).collect(); let reference: Vec> = sources .iter() .map(|source| serde_json::from_str(source).unwrap()) .collect(); for values in [ sources .iter() .map(|source| Json::parse(source).unwrap()) .collect::>(), reference .iter() .cloned() .map(Json::from_validated_raw) .collect(), ] { let encoded = Json::array(&values).unwrap(); assert_eq!(encoded.as_str(), serde_json::to_string(&reference).unwrap()); assert_eq!( Json::array(std::slice::from_ref(&encoded)) .unwrap() .as_str(), format!("[{}]", encoded.as_str()) ); } } } #[test] fn validated_raw_transfers_its_original_allocation_into_text() { let source = r#"{"huge":1e9999,"text":"\u96ea"}"#; let raw: Box = serde_json::from_str(source).unwrap(); let allocation = raw.get().as_ptr(); let value = Json::from_validated_raw(raw); assert_eq!(value.as_str().as_ptr(), allocation); let text = value.into_text(); assert_eq!(text.as_ptr(), allocation); assert_eq!(text, source); } #[test] fn raw_arrays_enforce_combined_value_and_separator_budgets() { let mut values = vec![Json::null().unwrap(); document::MAX_VALUES - 1]; assert!(Json::array(&values).is_ok()); values.push(Json::null().unwrap()); assert!(Json::array(&values).is_err()); for extra in [0, 1] { let values = [ Json::integer(0).unwrap(), Json::string(&"x".repeat(document::MAX_BYTES - 6 + extra)).unwrap(), ]; let encoded = Json::array(&values); if extra == 0 { let encoded = encoded.unwrap(); assert_eq!(encoded.as_str().len(), document::MAX_BYTES); assert!(Json::array(&[encoded]).is_err()); } else { assert!(encoded.is_err()); } } } #[test] fn dynamic_output_keeps_byte_limits_and_counts_empty_containers() { let allowed = vec!["x".repeat(document::MAX_BYTES - 4)]; assert_eq!( Json::encode(&allowed).unwrap().as_str().len(), document::MAX_BYTES ); assert!(Json::encode(&vec!["x".repeat(document::MAX_BYTES - 3)]).is_err()); assert!(Json::encode(&vec![Vec::::new(); document::MAX_VALUES - 1]).is_ok()); assert!(Json::encode(&vec![Vec::::new(); document::MAX_VALUES]).is_err()); } #[test] fn validated_fragments_combine_with_serde_fields_and_keep_reusable_budgets() { let fragment = Json::parse(" \n{\"雪\":[1e9999,-0,\"\\u96ea\"]}\t ").unwrap(); let nested = Json::encode_with(|output| { output.object(|output| { output.field_encoded("\"a\\\"雪\":", |output| output.json(&fragment))?; output.field("b", false, |output| output.value(&vec![Some("雪\n"), None])) }) }) .unwrap(); assert_eq!( nested.as_str(), "{\"a\\\"雪\":{\"雪\":[1e9999,-0,\"\\u96ea\"]},\"b\":[\"雪\\n\",null]}" ); assert_eq!( Json::array(std::slice::from_ref(&nested)).unwrap().as_str(), format!("[{}]", nested.as_str()) ); assert_eq!(fragment.as_str(), " \n{\"雪\":[1e9999,-0,\"\\u96ea\"]}\t "); let allowed = Json::parse(&("[".repeat(document::MAX_DEPTH - 1) + &"]".repeat(document::MAX_DEPTH - 1))) .unwrap(); let full = Json::array(&[allowed]).unwrap(); assert!(Json::array(&[full]).is_err()); let full = Json::encode_with(|output| output.value(&vec![0; document::MAX_VALUES - 1])).unwrap(); assert!(Json::array(&[full]).is_err()); let allowed = Json::string(&"x".repeat(document::MAX_BYTES - 4)).unwrap(); let full = Json::array(&[allowed]).unwrap(); assert_eq!(full.as_str().len(), document::MAX_BYTES); assert!(Json::array(&[full]).is_err()); }