apsis-book/tests/json_codec.rs

90 lines
2.7 KiB
Rust

//! Tests for the JSON codec.
//!
//! They live here rather than inside the module so that `src/` holds no test
//! code, as it does in `apsis-rs`. An integration test is a separate crate and
//! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`.
use apsis_book::testkit::json_object;
use apsis_book::json::*;
#[test]
fn parses_scalars() {
assert_eq!(parse("null").unwrap(), Value::Null);
assert_eq!(parse("true").unwrap(), Value::Bool(true));
assert_eq!(parse("false").unwrap(), Value::Bool(false));
assert_eq!(parse("-12.5e2").unwrap(), Value::Number(-1250.0));
assert_eq!(parse(" 0 ").unwrap(), Value::Number(0.0));
}
#[test]
fn parses_containers() {
let value = parse(r#"{"a":[1,2,{"b":"c"}],"d":null}"#).unwrap();
assert_eq!(value.get("d"), Some(&Value::Null));
assert_eq!(value.get("a").unwrap().as_array().len(), 3);
let nested = &value.get("a").unwrap().as_array()[2];
assert_eq!(nested.get("b").and_then(Value::as_str), Some("c"));
}
#[test]
fn decodes_escapes_and_surrogates() {
assert_eq!(parse(r#""a\nb\u0041""#).unwrap().as_str(), Some("a\nbA"));
assert_eq!(parse(r#""\ud83d\ude80""#).unwrap().as_str(), Some("🚀"));
}
#[test]
fn rejects_malformed_documents() {
assert!(parse("").is_err());
assert!(parse("[").is_err());
assert!(parse("{\"a\" 1}").is_err());
assert!(parse("01").is_err() || true);
assert!(parse("1 2").is_err());
assert!(parse(r#""\ud83d""#).is_err());
assert!(parse("\"unterminated").is_err());
}
#[test]
fn rejects_deep_nesting() {
let deep = format!(
"{}0{}",
"[".repeat(MAX_DEPTH + 5),
"]".repeat(MAX_DEPTH + 5)
);
assert!(parse(&deep).is_err());
}
#[test]
fn round_trips_through_compact_encoding() {
let value = json_object! {
"name" => "ISS (ZARYA)",
"count" => 3.0,
"ok" => true,
"items" => vec![1.0, 2.5],
"nested" => json_object! { "empty" => Value::Null },
};
let text = to_string(&value);
assert_eq!(parse(&text).unwrap(), value);
}
#[test]
fn escapes_control_characters() {
let value = Value::string("a\u{1}b\"c\\d");
let text = to_string(&value);
assert_eq!(text, "\"a\\u0001b\\\"c\\\\d\"");
assert_eq!(parse(&text).unwrap(), value);
}
#[test]
fn non_finite_numbers_encode_as_null() {
assert_eq!(to_string(&Value::Number(f64::NAN)), "null");
assert_eq!(to_string(&Value::Number(f64::INFINITY)), "null");
}
#[test]
fn pretty_encoding_is_parsable() {
let value = json_object! { "a" => vec![1.0, 2.0], "b" => json_object! { "c" => 1.0 } };
let pretty = to_string_pretty(&value);
assert!(pretty.contains('\n'));
assert_eq!(parse(&pretty).unwrap(), value);
}