use verit::{dump_json, encode, Dt, Error, Message, SchemaBuilder, SchemaMode, Value};
#[test]
fn dump_with_zero_prior_knowledge() {
let schema = SchemaBuilder::new()
.add_struct("Person", vec![(1, "name", Dt::Str), (2, "age", Dt::U8)])
.build("Person")
.unwrap();
let bytes = encode(
&schema,
&Value::Struct(vec![(1, Value::str("Ada")), (2, Value::U8(36))]),
SchemaMode::Inline,
)
.unwrap();
let json = dump_json(&bytes).unwrap();
assert_eq!(json, r#"{"name":"Ada","age":36}"#);
}
#[test]
fn dump_renders_nested_structs_lists_and_enum_names() {
let schema = SchemaBuilder::new()
.add_enum("Color", vec![(0, "Red"), (1, "Green"), (2, "Blue")])
.add_struct("Point", vec![(1, "x", Dt::F64), (2, "y", Dt::F64)])
.add_struct(
"Shape",
vec![
(1, "label", Dt::Str),
(2, "color", Dt::named("Color")),
(3, "center", Dt::named("Point")),
(4, "corners", Dt::list(Dt::named("Point"))),
(5, "checksum", Dt::Bytes),
],
)
.build("Shape")
.unwrap();
let bytes = encode(
&schema,
&Value::Struct(vec![
(1, Value::str("box")),
(2, Value::Enum(2)),
(
3,
Value::Struct(vec![(1, Value::F64(0.5)), (2, Value::F64(-1.0))]),
),
(
4,
Value::List(vec![
Value::Struct(vec![(1, Value::F64(0.0)), (2, Value::F64(0.0))]),
Value::Struct(vec![(1, Value::F64(1.0))]),
]),
),
(5, Value::Bytes(vec![0xAB, 0xCD])),
]),
SchemaMode::Inline,
)
.unwrap();
let json = dump_json(&bytes).unwrap();
assert_eq!(
json,
r#"{"label":"box","color":"Blue","center":{"x":0.5,"y":-1},"corners":[{"x":0,"y":0},{"x":1}],"checksum":"abcd"}"#
);
}
#[test]
fn unknown_enum_value_dumps_as_number() {
let schema = SchemaBuilder::new()
.add_enum("Color", vec![(0, "Red")])
.add_struct("S", vec![(1, "c", Dt::named("Color"))])
.build("S")
.unwrap();
let bytes = encode(
&schema,
&Value::Struct(vec![(1, Value::Enum(77))]),
SchemaMode::Inline,
)
.unwrap();
assert_eq!(dump_json(&bytes).unwrap(), r#"{"c":77}"#);
}
#[test]
fn hash_only_message_refuses_dump() {
let schema = SchemaBuilder::new()
.add_struct("S", vec![(1, "x", Dt::U32)])
.build("S")
.unwrap();
let bytes = encode(
&schema,
&Value::Struct(vec![(1, Value::U32(5))]),
SchemaMode::HashOnly,
)
.unwrap();
assert!(matches!(dump_json(&bytes), Err(Error::NoInlineSchema)));
}
#[test]
fn inline_schema_recovers_and_hash_verifies() {
let schema = SchemaBuilder::new()
.add_struct("S", vec![(1, "x", Dt::U32), (2, "s", Dt::Str)])
.build("S")
.unwrap();
let bytes = encode(
&schema,
&Value::Struct(vec![(1, Value::U32(5))]),
SchemaMode::Inline,
)
.unwrap();
let msg = Message::parse(&bytes).unwrap();
let recovered = msg.writer_schema().unwrap().unwrap();
assert_eq!(recovered.id(), schema.id());
assert_eq!(recovered.canonical_bytes(), schema.canonical_bytes());
}
#[test]
fn tampered_inline_schema_is_detected() {
let schema = SchemaBuilder::new()
.add_struct("S", vec![(1, "x", Dt::U32)])
.build("S")
.unwrap();
let mut bytes = encode(
&schema,
&Value::Struct(vec![(1, Value::U32(5))]),
SchemaMode::Inline,
)
.unwrap();
bytes[36] ^= 0xFF;
let msg = Message::parse(&bytes).unwrap();
assert!(msg.writer_schema().is_err());
}
#[test]
fn size_overhead_is_bounded_and_amortizable() {
let schema = SchemaBuilder::new()
.add_struct("Person", vec![(1, "name", Dt::Str), (2, "age", Dt::U8)])
.build("Person")
.unwrap();
let value = Value::Struct(vec![(1, Value::str("Ada")), (2, Value::U8(36))]);
let inline = encode(&schema, &value, SchemaMode::Inline).unwrap();
let hash_only = encode(&schema, &value, SchemaMode::HashOnly).unwrap();
let overhead = inline.len() - hash_only.len();
assert!(overhead >= schema.canonical_bytes().len());
assert!(overhead < schema.canonical_bytes().len() + 8);
}