use verit::{dump_json, encode, Dt, Message, Ref, Resolver, SchemaBuilder, SchemaMode, Value};
fn rec_schema() -> verit::Schema {
SchemaBuilder::new()
.add_struct("Rec", vec![(1, "n", Dt::U32), (2, "name", Dt::Str)])
.set_default("Rec", 1, Value::U32(7))
.build("Rec")
.unwrap()
}
#[test]
fn absent_field_reads_its_default_but_get_stays_raw() {
let schema = rec_schema();
let bytes = encode(
&schema,
&Value::Struct(vec![(2, Value::str("x"))]),
SchemaMode::Inline,
)
.unwrap();
let resolver = Resolver::identity(&schema).unwrap();
let msg = Message::parse(&bytes).unwrap();
let root = msg.root(&resolver).unwrap();
assert_eq!(root.get_u32(1).unwrap(), None);
assert!(root.get(1).unwrap().is_none());
assert!(matches!(root.get_or_default(1).unwrap(), Some(Ref::U32(7))));
assert!(matches!(
root.get_or_default(2).unwrap(),
Some(Ref::Str("x"))
));
assert_eq!(dump_json(&bytes).unwrap(), r#"{"n":7,"name":"x"}"#);
}
#[test]
fn present_value_overrides_the_default() {
let schema = rec_schema();
let bytes = encode(
&schema,
&Value::Struct(vec![(1, Value::U32(99)), (2, Value::str("x"))]),
SchemaMode::Inline,
)
.unwrap();
let resolver = Resolver::identity(&schema).unwrap();
let msg = Message::parse(&bytes).unwrap();
let root = msg.root(&resolver).unwrap();
assert!(matches!(
root.get_or_default(1).unwrap(),
Some(Ref::U32(99))
));
assert_eq!(dump_json(&bytes).unwrap(), r#"{"n":99,"name":"x"}"#);
}
#[test]
fn adding_a_default_changes_the_id_but_absence_of_one_does_not() {
let with = rec_schema();
let without = SchemaBuilder::new()
.add_struct("Rec", vec![(1, "n", Dt::U32), (2, "name", Dt::Str)])
.build("Rec")
.unwrap();
assert_ne!(
with.id(),
without.id(),
"a default is part of the schema id"
);
let plain = SchemaBuilder::new()
.add_struct("Rec", vec![(1, "n", Dt::U32), (2, "name", Dt::Str)])
.build("Rec")
.unwrap();
assert_eq!(without.canonical_bytes(), plain.canonical_bytes());
}
#[test]
fn schema_with_defaults_round_trips_through_canonical() {
let schema = rec_schema();
let decoded = verit::Schema::from_canonical(schema.canonical_bytes()).unwrap();
assert_eq!(decoded.id(), schema.id());
assert_eq!(decoded.canonical_bytes(), schema.canonical_bytes());
}
#[test]
fn every_scalar_default_kind_round_trips() {
let schema = SchemaBuilder::new()
.add_enum("Color", vec![(0, "Red"), (1, "Green")])
.add_struct(
"All",
vec![
(1, "b", Dt::Bool),
(2, "u", Dt::U16),
(3, "i", Dt::I32),
(4, "f", Dt::F64),
(5, "c", Dt::named("Color")),
],
)
.set_default("All", 1, Value::Bool(true))
.set_default("All", 2, Value::U16(300))
.set_default("All", 3, Value::I32(-5))
.set_default("All", 4, Value::F64(1.5))
.set_default("All", 5, Value::Enum(1))
.build("All")
.unwrap();
let bytes = encode(&schema, &Value::Struct(vec![]), SchemaMode::Inline).unwrap();
assert_eq!(
dump_json(&bytes).unwrap(),
r#"{"b":true,"u":300,"i":-5,"f":1.5,"c":"Green"}"#
);
assert_eq!(
verit::Schema::from_canonical(schema.canonical_bytes())
.unwrap()
.id(),
schema.id()
);
}
#[test]
fn a_default_whose_type_mismatches_is_rejected() {
assert!(SchemaBuilder::new()
.add_struct("Rec", vec![(1, "n", Dt::U32)])
.set_default("Rec", 1, Value::str("nope"))
.build("Rec")
.is_err());
assert!(SchemaBuilder::new()
.add_struct("Rec", vec![(1, "xs", Dt::list(Dt::U8))])
.set_default("Rec", 1, Value::U8(1))
.build("Rec")
.is_err());
}
#[test]
fn evolution_reader_default_fills_a_field_the_writer_never_had() {
let v0 = SchemaBuilder::new()
.add_struct("Rec", vec![(2, "name", Dt::Str)])
.build("Rec")
.unwrap();
let bytes = encode(
&v0,
&Value::Struct(vec![(2, Value::str("legacy"))]),
SchemaMode::HashOnly,
)
.unwrap();
let v1 = rec_schema();
let resolver = Resolver::new(&v0, &v1).unwrap();
let msg = Message::parse(&bytes).unwrap();
let root = msg.root(&resolver).unwrap();
assert_eq!(root.get_u32(1).unwrap(), None, "absent in v0 data");
assert!(
matches!(root.get_or_default(1).unwrap(), Some(Ref::U32(7))),
"reader's default fills the field the writer never wrote"
);
}
#[test]
fn idl_parses_default_syntax() {
let schema = verit::idl::parse("struct Rec { 1: n u32 = 7 2: name string } root Rec").unwrap();
assert_eq!(schema.id(), rec_schema().id());
let s2 = verit::idl::parse("struct R { 1: k i32 = -5 2: on bool = true } root R").unwrap();
let hand = SchemaBuilder::new()
.add_struct("R", vec![(1, "k", Dt::I32), (2, "on", Dt::Bool)])
.set_default("R", 1, Value::I32(-5))
.set_default("R", 2, Value::Bool(true))
.build("R")
.unwrap();
assert_eq!(s2.id(), hand.id());
}