use noyalib::{ParserConfig, StreamingDeserializer, Value};
use serde::Deserialize;
use std::collections::BTreeMap;
#[test]
fn new_constructs_from_borrowed_str() {
let yaml = "key: value\n";
let mut de = StreamingDeserializer::new(yaml);
let m: BTreeMap<String, String> = Deserialize::deserialize(&mut de).unwrap();
assert_eq!(m["key"], "value");
}
#[test]
fn with_config_accepts_custom_parser_settings() {
let yaml = "k: 1\n";
let config = ParserConfig::strict();
let mut de = StreamingDeserializer::with_config(yaml, &config);
let m: BTreeMap<String, i32> = Deserialize::deserialize(&mut de).unwrap();
assert_eq!(m["k"], 1);
}
#[test]
fn struct_deserialisation_skips_ast() {
#[derive(Debug, Deserialize, PartialEq)]
struct Server {
host: String,
port: u16,
features: Vec<String>,
}
let yaml = "host: localhost\nport: 8080\nfeatures:\n - auth\n - api\n";
let mut de = StreamingDeserializer::new(yaml);
let s = Server::deserialize(&mut de).unwrap();
assert_eq!(s.host, "localhost");
assert_eq!(s.port, 8080);
assert_eq!(s.features, vec!["auth", "api"]);
}
#[test]
fn nested_collections_work() {
let yaml = "a:\n b:\n c: 42\n";
let mut de = StreamingDeserializer::new(yaml);
let m: BTreeMap<String, BTreeMap<String, BTreeMap<String, i32>>> =
Deserialize::deserialize(&mut de).unwrap();
assert_eq!(m["a"]["b"]["c"], 42);
}
#[test]
fn anchor_alias_handled_natively() {
#[derive(Debug, Deserialize, PartialEq)]
struct Endpoint {
host: String,
port: u16,
}
#[derive(Debug, Deserialize)]
struct Doc {
primary: Endpoint,
replica: Endpoint,
}
let yaml = r#"
primary: &p
host: db.local
port: 5432
replica: *p
"#;
let mut de = StreamingDeserializer::new(yaml);
let d = Doc::deserialize(&mut de).unwrap();
assert_eq!(d.primary, d.replica);
assert_eq!(d.primary.host, "db.local");
}
#[test]
fn native_merge_key_expansion() {
let yaml = r#"
base: &b
a: 1
b: 2
target:
<<: *b
c: 3
"#;
let mut de = StreamingDeserializer::new(yaml);
let outer: BTreeMap<String, BTreeMap<String, i64>> = Deserialize::deserialize(&mut de).unwrap();
let target = &outer["target"];
assert_eq!(target["a"], 1);
assert_eq!(target["b"], 2);
assert_eq!(target["c"], 3);
}
#[test]
fn native_multi_merge_key_expansion() {
let yaml = r#"
defaults: &d
host: localhost
port: 8080
overrides: &o
port: 9090
timeout: 30
target:
<<: [*o, *d]
debug: true
"#;
let mut de = StreamingDeserializer::new(yaml);
let outer: BTreeMap<String, BTreeMap<String, Value>> =
Deserialize::deserialize(&mut de).unwrap();
let target = &outer["target"];
assert_eq!(target["host"].as_str().unwrap(), "localhost");
assert_eq!(target["port"].as_i64().unwrap(), 9090);
assert_eq!(target["timeout"].as_i64().unwrap(), 30);
assert!(target["debug"].as_bool().unwrap());
}
#[test]
fn unknown_anchor_produces_error() {
let yaml = "foo: *missing\n";
let mut de = StreamingDeserializer::new(yaml);
let err = <BTreeMap<String, String>>::deserialize(&mut de).unwrap_err();
let msg = err.to_string();
assert!(msg.contains("missing") || msg.contains("unknown"));
}
#[test]
fn invalid_syntax_produces_parse_error() {
let yaml = "key: [unclosed\nnext: v\n";
let mut de = StreamingDeserializer::new(yaml);
let err = <BTreeMap<String, String>>::deserialize(&mut de).unwrap_err();
assert!(!err.to_string().is_empty());
}
#[test]
fn config_is_plumbed_through_with_config_constructor() {
let yaml = "val: True\n";
let config = ParserConfig::strict();
let mut de = StreamingDeserializer::with_config(yaml, &config);
let m: BTreeMap<String, String> = Deserialize::deserialize(&mut de).unwrap();
assert_eq!(m["val"], "True", "strict mode must pass `True` as string");
}
#[test]
fn debug_impl_does_not_panic() {
let de = StreamingDeserializer::new("a: 1");
let s = format!("{de:?}");
assert!(s.contains("StreamingDeserializer"));
}
#[test]
fn equivalent_to_from_str_for_simple_inputs() {
#[derive(Debug, Deserialize, PartialEq)]
struct Cfg {
name: String,
count: u32,
items: Vec<String>,
}
let yaml = "name: x\ncount: 5\nitems:\n - a\n - b\n";
let via_fromstr: Cfg = noyalib::from_str(yaml).unwrap();
let mut de = StreamingDeserializer::new(yaml);
let via_streaming = Cfg::deserialize(&mut de).unwrap();
assert_eq!(via_fromstr, via_streaming);
}