#![cfg(feature = "serde_cbor")]
use cddl_cat::cbor::validate_cbor_bytes;
use serde::{Deserialize, Serialize};
#[rustfmt::skip] pub mod cbor {
pub const BOOL_FALSE: &[u8] = b"\xF4";
pub const BOOL_TRUE: &[u8] = b"\xF5";
pub const NULL: &[u8] = b"\xF6";
pub const UNDEFINED: &[u8] = b"\xF7";
pub const INT_0: &[u8] = b"\x00";
pub const INT_1: &[u8] = b"\x01";
pub const INT_23: &[u8] = b"\x17";
pub const INT_24: &[u8] = b"\x18\x18";
pub const NINT_1000: &[u8] = b"\x39\x03\xe7";
pub const FLOAT_0_0: &[u8] = b"\xf9\x00\x00"; pub const FLOAT_1_0: &[u8] = b"\xf9\x3c\x00"; pub const FLOAT_1E5: &[u8] = b"\xfa\x47\xc3\x50\x00"; pub const FLOAT_1E300: &[u8] = b"\xfb\x7e\x37\xe4\x3c\x88\x00\x75\x9c";
pub const ARRAY_EMPTY: &[u8] = b"\x80"; pub const ARRAY_123: &[u8] = b"\x83\x01\x02\x03"; pub const ARRAY_1_23_45:&[u8] = b"\x83\x01\x82\x02\x03\x82\x04\x05";
pub const TEXT_EMPTY: &[u8] = b"\x60";
pub const TEXT_IETF: &[u8] = b"\x64\x49\x45\x54\x46";
pub const TEXT_CJK: &[u8] = b"\x63\xe6\xb0\xb4";
pub const BYTES_EMPTY: &[u8] = b"\x40";
pub const BYTES_1234: &[u8] = b"\x44\x01\x02\x03\x04";
}
#[test]
fn validate_cbor_null() {
let cddl_input = r#"thing = nil"#;
validate_cbor_bytes("thing", cddl_input, cbor::NULL).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_0).unwrap_err();
let err = validate_cbor_bytes("thing", cddl_input, cbor::BOOL_FALSE).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected nil)");
}
#[test]
fn validate_cbor_bool() {
let cddl_input = r#"thing = true"#;
validate_cbor_bytes("thing", cddl_input, cbor::BOOL_TRUE).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::BOOL_FALSE).unwrap_err();
let err = validate_cbor_bytes("thing", cddl_input, cbor::NULL).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected true)");
}
#[test]
fn validate_cbor_float() {
let cddl_input = r#"thing = 0.0"#;
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_0_0).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected 0)");
let cddl_input = r#"thing = float"#;
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1E5).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1E300).unwrap();
let cddl_input = r#"thing = float16"#;
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
let cddl_input = r#"thing = float32"#;
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1E5).unwrap();
let cddl_input = r#"thing = float64"#;
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1E300).unwrap();
}
#[test]
fn validate_cbor_choice() {
let cddl_input = r#"thing = 23 / 24"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_23).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap();
let cddl_input = r#"thing = (foo // bar) foo = (int / float) bar = tstr"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_23).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_IETF).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::BOOL_TRUE).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected choice of 2)");
let cddl_input = r#"thing = (foo / bar) foo = (int / float) bar = tstr"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_23).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_IETF).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::BOOL_TRUE).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected choice of 2)");
let cddl_input = r#"thing = (int / float // tstr / bstr)"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_23).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_IETF).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::BOOL_TRUE).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected choice of 2)");
}
#[test]
fn validate_cbor_integer() {
let cddl_input = r#"thing = 1"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::NULL).unwrap_err();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap_err();
validate_cbor_bytes("thing", cddl_input, cbor::BOOL_TRUE).unwrap_err();
let cddl_input = r#"thing = int"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::NINT_1000).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap_err();
let cddl_input = r#"thing = uint"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::NINT_1000).unwrap_err();
let cddl_input = r#"thing = nint"#;
validate_cbor_bytes("thing", cddl_input, cbor::NINT_1000).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_0).unwrap_err();
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap_err();
}
#[test]
fn validate_cbor_ranges() {
let cddl_input = r#"thing = 1..5"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected 1..5)");
let err = validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected 1..5)");
let cddl_input = r#"thing = 1..24"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap();
let cddl_input = r#"thing = 1...24"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_23).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap_err();
let cddl_input = r#"thing = 1 .. 5.3"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap_err();
assert_eq!(
err.to_string(),
"Structural(mismatched types on range operator)"
);
let cddl_input = r#"max=5 thing = 1..max"#;
validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::INT_24).unwrap_err();
let cddl_input = r#"thing = 0.9..1.2"#;
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_1_0).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::FLOAT_0_0).unwrap_err();
let err = validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected 0.9..1.2)");
let cddl_input = r#"thing = 1..uint"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap_err();
assert_eq!(err.to_string(), "Structural(bad type on range operator)");
let cddl_input = r#"thing = 1..[5]"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::INT_1).unwrap_err();
assert_eq!(err.to_string(), "Structural(bad type on range operator)");
}
#[test]
fn validate_cbor_textstring() {
for cddl_input in [r#"thing = tstr"#, r#"thing = text"#].iter() {
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_IETF).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_CJK).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::BYTES_EMPTY).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected tstr)");
}
}
#[test]
fn validate_cbor_bytestring() {
for cddl_input in [r#"thing = bstr"#, r#"thing = bytes"#].iter() {
validate_cbor_bytes("thing", cddl_input, cbor::BYTES_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::BYTES_1234).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::TEXT_EMPTY).unwrap_err();
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected bstr)");
}
let cddl_input = r#"thing = h'01020304'"#;
validate_cbor_bytes("thing", cddl_input, cbor::BYTES_1234).unwrap();
}
#[test]
fn validate_cbor_array() {
let cddl_input = r#"thing = []"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::NULL).unwrap_err();
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected shorter array)");
let cddl_input = r#"thing = [1, 2, 3]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected array element 1)");
}
#[derive(Debug, Serialize, Deserialize)]
struct PersonStruct {
name: String,
age: u32,
}
#[derive(Debug, Serialize, Deserialize)]
struct PersonTuple(String, u32);
#[derive(Debug, Serialize, Deserialize)]
struct BackwardsTuple(u32, String);
#[derive(Debug, Serialize, Deserialize)]
struct LongTuple(String, u32, u32);
#[derive(Debug, Serialize, Deserialize)]
struct ShortTuple(String);
#[derive(Debug, Serialize, Deserialize)]
struct KitchenSink(String, u32, f64, bool);
#[test]
fn validate_cbor_homogenous_array() {
let cddl_input = r#"thing = [* int]"#; validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [+ int]"#; validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap_err();
assert_eq!(
err.to_string(),
"Mismatch(expected more array element [+ Int])"
);
let cddl_input = r#"thing = [? int]"#; validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap();
let cbor_bytes = serde_cbor::to_vec(&[42]).unwrap();
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected shorter array)");
let cddl_input = r#"thing = [* tstr]"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected shorter array)");
let cddl_input = r#"thing = [* zipcode] zipcode = int"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
}
#[test]
fn validate_cbor_array_groups() {
let cddl_input = r#"thing = [int, (int, int)]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [(int, int, int)]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [* (int)]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [* (int, int, int)]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [* (int, int)]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
let cddl_input = r#"thing = [a: int, b: int, bar] bar = (c: int)"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [a: int, (bar)] bar = (b: int, c: int)"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [a: int, b: bar] bar = (b: int, c: int)"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Unsupported standalone group");
let cddl_input = r#"thing = [int, (foo // bar)] foo = (int, tstr) bar = (int, int)"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [(int, (int, bool // (int, tstr // int, int)))]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
}
#[test]
fn validate_cbor_array_unwrap() {
let cddl_input = r#"header = [a: int, b: int] thing = [~header c: int]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap_err();
let cddl_input = r#"footer = [a: int, b: int] thing = [c: int ~footer]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"middle = [int] thing = [a: int, ~middle, c: int]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"foo = int middle = [foo] thing = [a: int, ~middle, c: int]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"header = [a: int] thing = [~header, c: int]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
let cddl_input = r#"footer = [a: int] thing = [c: int, ~footer]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
let cddl_input = r#"footer = [a: int, b: int] thing = [c: int, d: int, ~footer]"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected array element Int)");
let cddl_input = r#"thing = [c: int ~footer]"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "MissingRule(footer)");
let cddl_input = r#"header = {a: int, b: int} thing = [~header c: int]"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected unwrap array)");
}
#[test]
fn validate_cbor_array_record() {
let cddl_input = r#"thing = [a: int, b: int, c: int]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap_err();
let cddl_input = r#"thing = [a: int, b: int, c: foo] foo = int"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
let cddl_input = r#"thing = [int, int, int]"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_EMPTY).unwrap_err();
let cddl_input = r#"thing = [a: tstr, b: int]"#;
let input = PersonTuple("Alice".to_string(), 42);
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let input = BackwardsTuple(43, "Carol".to_string());
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
let input = LongTuple("David".to_string(), 44, 45);
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
let input = ShortTuple("Eve".to_string());
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
let cddl_input = r#"thing = [a: tstr, b: uint, c: float, d: bool]"#;
let input = KitchenSink("xyz".to_string(), 17, 9.9, false);
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
}
#[test]
fn validate_cbor_map_unwrap() {
let input = PersonStruct {
name: "Bob".to_string(),
age: 43,
};
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
let cddl_input = r#"thing = {name: tstr, ~agroup} agroup = {age: int}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, ~agroup} agroup = [age: int]"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected unwrap map)");
}
#[test]
fn validate_cbor_map_group() {
let input = PersonStruct {
name: "Bob".to_string(),
age: 43,
};
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
let cddl_input = r#"thing = {name: tstr, agroup} agroup = (age: int)"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {agroup} agroup = (age: int, name: tstr)"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {((agroup))} agroup = (age: int, name: tstr)"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {agroup empty} agroup = (age: int, name: tstr) empty = ()"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input =
r#"thing = {agroup maybe} agroup = (age: int, name: tstr) maybe = (? minor: bool)"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, agroup} agroup = (wrong: int)"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), r#"Mismatch(expected map{"wrong"})"#);
let cddl_input = r#"thing = {name: tstr, agroup} agroup = (age: bool)"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected bool)");
let cddl_input =
r#"thing = { foo // bar } foo = (name: tstr, age: bool) bar = (name: tstr, age: int)"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = { (name: tstr, photo: bstr //
(name: tstr, fail: bool // name: tstr, age: int)) }"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
}
#[test]
fn validate_cbor_map() {
let input = PersonStruct {
name: "Bob".to_string(),
age: 43,
};
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
let cddl_input = r#"thing = {name: tstr, age: int}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, ? age: int}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, age: int, ? minor: bool}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, age: int, * minor: bool}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, age: int, + minor: bool}"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(
err.to_string(),
r#"Mismatch(expected map{+ "minor": Bool}])"#
);
let cddl_input = r#"thing = {name: tstr, age: tstr}"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected tstr)");
let cddl_input = r#"thing = {name: tstr}"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected shorter map)");
let cddl_input = r#"thing = {* tstr => any}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, * tstr => any}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {name: tstr, age: int, * tstr => any}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {+ tstr => any}"#;
validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap();
let cddl_input = r#"thing = {* int => any}"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "Mismatch(expected shorter map)");
let cddl_input = r#"thing = {name: tstr, age: int, minor: bool}"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), r#"Mismatch(expected map{"minor"})"#);
let cddl_input = r#"thing = {x: int, y: int, z: int}"#;
validate_cbor_bytes("thing", cddl_input, cbor::ARRAY_123).unwrap_err();
}
#[derive(Debug, Serialize)]
struct StreetNumber {
street: String,
number: u32,
name: String,
zip_code: u32,
}
#[derive(Debug, Serialize)]
struct POBox {
po_box: u32,
name: String,
zip_code: u32,
}
#[derive(Debug, Serialize)]
struct Pickup {
per_pickup: bool,
}
#[test]
fn validate_choice_example() {
let cddl_input = r#"
address = { delivery }
delivery = (
street: tstr, ? number: uint, city //
po_box: uint, city //
per_pickup: true )
city = (
name: tstr, zip_code: uint
)"#;
let input = POBox {
po_box: 101,
name: "San Francisco".to_string(),
zip_code: 94103,
};
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("address", cddl_input, &cbor_bytes).unwrap();
let input = StreetNumber {
street: "Eleventh St.".to_string(),
number: 375,
name: "San Francisco".to_string(),
zip_code: 94103,
};
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("address", cddl_input, &cbor_bytes).unwrap();
let input = Pickup { per_pickup: true };
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
validate_cbor_bytes("address", cddl_input, &cbor_bytes).unwrap();
}
#[test]
fn test_fatal_propagation() {
let cddl_input = r#"thing = (bad_rule / bool)"#;
let err = validate_cbor_bytes("thing", cddl_input, cbor::BOOL_TRUE).unwrap_err();
assert_eq!(err.to_string(), "MissingRule(bad_rule)");
let cddl_input = r#"thing = [a: (bad_rule / tstr), b: int]"#;
let input = PersonTuple("Alice".to_string(), 42);
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "MissingRule(bad_rule)");
let input = PersonStruct {
name: "Bob".to_string(),
age: 43,
};
let cbor_bytes = serde_cbor::to_vec(&input).unwrap();
let cddl_input = r#"thing = {name: (bad_rule / tstr), age: int}"#;
let err = validate_cbor_bytes("thing", cddl_input, &cbor_bytes).unwrap_err();
assert_eq!(err.to_string(), "MissingRule(bad_rule)");
}