use super::*;
#[test]
fn only_objects_are_records() {
assert!(parse_object("{\"a\":1}").is_some());
assert!(parse_object("{}").is_some());
assert!(parse_object("[1]").is_none());
assert!(parse_object("1").is_none());
assert!(parse_object("\"x\"").is_none());
assert!(parse_object("null").is_none());
assert!(parse_object("{\"a\":").is_none());
assert!(parse_object("").is_none());
assert!(parse_object("{\"a\":1,}").is_none());
assert!(parse_object("{/* c */\"a\":1}").is_none());
}
#[test]
fn the_last_duplicate_key_wins() {
let map: Map<String, Value> = parse_object("{\"a\":\"first\",\"a\":\"last\"}").expect("object");
assert_eq!(string_field(&map, "a"), Some("last"));
}
#[test]
fn text_fields_are_strings_only() {
let map: Map<String, Value> =
parse_object("{\"s\":\"x\",\"n\":1,\"b\":true,\"z\":null}").expect("object");
assert_eq!(string_field(&map, "s"), Some("x"));
assert_eq!(string_field(&map, "n"), None);
assert_eq!(string_field(&map, "b"), None);
assert_eq!(string_field(&map, "z"), None);
assert_eq!(string_field(&map, "missing"), None);
}
#[test]
fn safe_integers_follow_javascript() {
let map: Map<String, Value> = parse_object(
"{\"a\":1,\"b\":1.0,\"c\":1e0,\"d\":1.5,\"e\":9007199254740991,\"f\":9007199254740992,\
\"g\":-9007199254740991,\"h\":-9007199254740992,\"i\":\"1\",\"j\":18446744073709551615,\
\"k\":1e20,\"l\":-0,\"m\":4503599627370495.0,\"n\":9007199254740992.0,\"o\":-3.0}",
)
.expect("object");
assert_eq!(safe_integer_field(&map, "a"), Some(1));
assert_eq!(safe_integer_field(&map, "b"), Some(1));
assert_eq!(safe_integer_field(&map, "c"), Some(1));
assert_eq!(safe_integer_field(&map, "d"), None);
assert_eq!(safe_integer_field(&map, "e"), Some(MAX_SAFE_INTEGER));
assert_eq!(safe_integer_field(&map, "f"), None);
assert_eq!(safe_integer_field(&map, "g"), Some(-MAX_SAFE_INTEGER));
assert_eq!(safe_integer_field(&map, "h"), None);
assert_eq!(safe_integer_field(&map, "i"), None);
assert_eq!(safe_integer_field(&map, "j"), None);
assert_eq!(safe_integer_field(&map, "k"), None);
assert_eq!(safe_integer_field(&map, "l"), Some(0));
assert_eq!(safe_integer_field(&map, "m"), Some(4_503_599_627_370_495));
assert_eq!(safe_integer_field(&map, "n"), None);
assert_eq!(safe_integer_field(&map, "o"), Some(-3));
assert_eq!(safe_integer_field(&map, "missing"), None);
}
#[test]
fn number_equality_compares_values() {
let map: Map<String, Value> =
parse_object("{\"a\":2,\"b\":2.0,\"c\":\"2\",\"d\":3}").expect("object");
assert!(number_equals(&map, "a", 2));
assert!(number_equals(&map, "b", 2));
assert!(!number_equals(&map, "c", 2));
assert!(!number_equals(&map, "d", 2));
assert!(!number_equals(&map, "missing", 2));
}
#[test]
fn the_fatal_decoder_matches_text_decoder() {
assert_eq!(decode_fatal(b"{}"), Some("{}"));
assert_eq!(decode_fatal(b"\xef\xbb\xbf{}"), Some("{}"));
assert_eq!(
decode_fatal(b"\xef\xbb\xbf\xef\xbb\xbf{}"),
Some("\u{feff}{}")
);
assert_eq!(decode_fatal(b"{\xff}"), None);
}
#[test]
fn the_writer_matches_json_stringify() {
let mut writer: ObjectWriter = ObjectWriter::new();
writer
.integer("schemaVersion", 2)
.string("text", "a\"b\\c\n\t\u{1}\u{7f}é/")
.boolean("yes", true)
.boolean("no", false)
.integer("negative", -5)
.raw(
"list",
string_array(&[String::from("x"), String::from("y\"")]).as_str(),
)
.raw("empty", string_array(&[]).as_str());
assert_eq!(
writer.finish(),
"{\"schemaVersion\":2,\"text\":\"a\\\"b\\\\c\\n\\t\\u0001\u{7f}é/\",\"yes\":true,\
\"no\":false,\"negative\":-5,\"list\":[\"x\",\"y\\\"\"],\"empty\":[]}"
);
assert_eq!(ObjectWriter::new().finish(), "{}");
}
#[test]
fn quoting_matches_json_stringify() {
assert_eq!(quote(""), "\"\"");
assert_eq!(quote("\u{8}\u{c}\r"), "\"\\b\\f\\r\"");
assert_eq!(quote("\u{1f}"), "\"\\u001f\"");
assert_eq!(quote("\u{2028}"), "\"\u{2028}\"");
}