#[macro_use] extern crate jzon; use jzon::number::Number; use jzon::{ parse, JsonValue, Null }; #[test] fn parse_true() { assert_eq!(parse("true").unwrap(), true); } #[test] fn parse_false() { assert_eq!(parse("false").unwrap(), false); } #[test] fn parse_null() { assert!(parse("null").unwrap().is_null()); } #[test] fn parse_number() { assert_eq!(parse("3.141592653589793").unwrap(), 3.141592653589793); } #[test] fn uncode_identifier() { assert!(parse("[C3A9] <=> [é]").is_err()); } #[test] fn parse_period_requires_digit() { assert!(parse("[1.]").is_err()); } #[test] fn parse_small_number() { assert_eq!(parse("0.05").unwrap(), 0.05); } #[test] fn parse_very_long_float() { let parsed = parse("2.22507385850720113605740979670913197593481954635164564e-308").unwrap(); // Handles convertion correctly assert_eq!(parsed.as_f64().unwrap(), 2.225073858507201e-308); // Exhausts u64 assert_eq!(parsed, unsafe { Number::from_parts_unchecked(true, 2225073858507201136, -326) }); } #[test] fn parse_very_long_exponent() { let parsed = parse("1e999999999999999999999999999999999999999999999999999999999999").unwrap(); assert_eq!(parsed, unsafe { Number::from_parts_unchecked(true, 1, 32767) }); } #[test] fn parse_integer() { assert_eq!(parse("42").unwrap(), 42); } #[test] fn parse_negative_zero() { assert_eq!(parse("-0").unwrap(), JsonValue::from(-0f64)); } #[test] fn parse_negative_integer() { assert_eq!(parse("-42").unwrap(), -42); } #[test] fn parse_number_with_leading_zero() { assert!(parse("01").is_err()); } #[test] fn parse_negative_number_with_leading_zero() { assert!(parse("-01").is_err()); } #[test] fn parse_number_with_e() { assert_eq!(parse("5e2").unwrap(), 500); assert_eq!(parse("5E2").unwrap(), 500); } #[test] fn parse_number_with_positive_e() { assert_eq!(parse("5e+2").unwrap(), 500); assert_eq!(parse("5E+2").unwrap(), 500); } #[test] fn parse_number_with_negative_e() { assert_eq!(parse("5e-2").unwrap(), 0.05); assert_eq!(parse("5E-2").unwrap(), 0.05); } #[test] fn parse_number_with_invalid_e() { assert!(parse("0e").is_err()); } #[test] fn parse_large_number() { assert_eq!(parse("18446744073709551616").unwrap(), 18446744073709552000f64); } #[test] fn parse_array() { assert_eq!(parse(r#"[10, "foo", true, null]"#).unwrap(), array![ 10, "foo", true, null ]); assert_eq!(parse("[]").unwrap(), array![]); assert_eq!(parse("[[]]").unwrap(), array![[]]); } #[test] fn parse_object() { // Without trailing comma assert_eq!(parse(r#" { "foo": "bar", "num": 10 } "#).unwrap(), object!{ foo: "bar", num: 10 }); // Trailing comma in macro assert_eq!(parse(r#" { "foo": "bar", "num": 10 } "#).unwrap(), object!{ foo: "bar", num: 10, }); } #[test] fn parse_object_duplicate_fields() { assert_eq!(parse(r#" { "foo": 0, "bar": 1, "foo": 2 } "#).unwrap(), object!{ foo: 2, bar: 1 }); } #[test] fn parse_object_with_array(){ assert_eq!(parse(r#" { "foo": [1, 2, 3] } "#).unwrap(), object!{ foo: [1, 2, 3] }); } #[test] fn parse_nested_object() { assert_eq!(parse(r#" { "l10n": [ { "product": { "inStock": { "DE": "Lieferung innerhalb von 1-3 Werktagen" } } } ] } "#).unwrap(), object!{ l10n: [ { product: { inStock: { DE: "Lieferung innerhalb von 1-3 Werktagen" } } } ] }); } #[test] fn parse_and_index_from_object() { let data = parse("{ \"pi\": 3.14 }").unwrap(); let ref pi = data["pi"]; assert_eq!(pi, 3.14); } #[test] fn parse_and_index_mut_from_object() { let mut data = parse(r#" { "foo": 100 } "#).unwrap(); assert_eq!(data["foo"], 100); data["foo"] = 200.into(); assert_eq!(data["foo"], 200); } #[test] fn parse_and_index_mut_from_null() { let mut data = parse("null").unwrap(); assert!(data["foo"]["bar"].is_null()); // test that data didn't coerce to object assert!(data.is_null()); data["foo"]["bar"] = 100.into(); assert!(data.is_object()); assert_eq!(data["foo"]["bar"], 100); assert_eq!(data.dump(), r#"{"foo":{"bar":100}}"#); } #[test] fn parse_and_index_from_array() { let data = parse(r#"[100, 200, false, null, "foo"]"#).unwrap(); assert_eq!(data[0], Number::from(100)); assert_eq!(data[1], 200); assert_eq!(data[2], false); assert_eq!(data[3], Null); assert_eq!(data[4], "foo"); assert_eq!(data[5], Null); } #[test] fn parse_and_index_mut_from_array() { let mut data = parse(r#"[100, 200, false, null, "foo"]"#).unwrap(); assert!(data[3].is_null()); assert!(data[5].is_null()); data[3] = "modified".into(); data[5] = "implicid push".into(); assert_eq!(data[3], "modified"); assert_eq!(data[5], "implicid push"); } #[test] fn parse_escaped_characters() { let data = parse(r#" "\r\n\t\b\f\\\/\"" "#).unwrap(); assert!(data.is_string()); assert_eq!(data, "\r\n\t\u{8}\u{c}\\/\""); } #[test] fn parse_escaped_unicode() { let data = parse(r#" "\u2764\ufe0f" "#).unwrap(); assert_eq!(data, "❤️"); } #[test] fn parse_escaped_unicode_surrogate() { let data = parse(r#" "\uD834\uDD1E" "#).unwrap(); assert_eq!(data, "𝄞"); } #[test] fn parse_escaped_unicode_surrogate_fail() { let err = parse(r#" "\uD834 \uDD1E" "#); assert!(err.is_err()); } #[test] fn parse_deeply_nested_arrays_and_objects() { let depth = 256; let mut text = String::new(); for _ in 0..depth { text.push_str("[{\"a\":"); } text.push_str("null"); for _ in 0..depth { text.push_str("}]"); } parse(&text).unwrap(); assert!(true); } #[test] fn parse_error_after_depth_limit() { let depth = 5000; let mut text = String::new(); for _ in 0..depth { text.push_str("[{\"a\":"); } text.push_str("null"); for _ in 0..depth { text.push_str("}]"); } assert_eq!(parse(&text), Err(jzon::Error::ExceededDepthLimit)); } #[test] fn does_not_panic_on_single_unicode_char() { let bytes = vec![0xC3, 0xA5]; let string = String::from_utf8(bytes).unwrap(); assert!(parse(&string).is_err()); } #[test] fn does_not_panic_on_single_zero() { let source = "0"; parse(source).unwrap(); } #[test] fn does_not_panic_on_huge_numbers() { let mut string = String::from("8"); for _ in 1..32787 { string.push('0'); } let _ = jzon::parse(&string); }