use content_addressable::canonical;
use newt_interaction::{
decode_definition, ControlId, Decoded, IdempotencyKey, Nonce, OptionId, SecretRef,
SurfaceFeature,
};
mod fixtures;
use fixtures::definition;
fn patch_same_length(bytes: &[u8], from: &str, to: &str) -> Vec<u8> {
assert_eq!(from.len(), to.len(), "the patch must not change any length");
let at = bytes
.windows(from.len())
.position(|w| w == from.as_bytes())
.unwrap_or_else(|| panic!("`{from}` not found in the encoded record"));
let mut out = bytes.to_vec();
out[at..at + to.len()].copy_from_slice(to.as_bytes());
out
}
#[test]
fn an_invalid_scalar_does_not_deserialize() {
for bad in ["\"not an id\"", "\"\"", "\"has/slash\"", "\"tab\\there\""] {
assert!(
serde_json::from_str::<ControlId>(bad).is_err(),
"ControlId accepted {bad}"
);
assert!(
serde_json::from_str::<OptionId>(bad).is_err(),
"OptionId accepted {bad}"
);
}
for ty in ["Nonce", "IdempotencyKey", "SecretRef", "SurfaceFeature"] {
let empty = "\"\"";
let refused = match ty {
"Nonce" => serde_json::from_str::<Nonce>(empty).is_err(),
"IdempotencyKey" => serde_json::from_str::<IdempotencyKey>(empty).is_err(),
"SecretRef" => serde_json::from_str::<SecretRef>(empty).is_err(),
_ => serde_json::from_str::<SurfaceFeature>(empty).is_err(),
};
assert!(refused, "{ty} accepted an empty string");
}
let id: ControlId = serde_json::from_str("\"decision\"").unwrap();
assert_eq!(id.as_str(), "decision");
let feature: SurfaceFeature = serde_json::from_str("\"holography\"").unwrap();
assert_eq!(
feature.as_str(),
"holography",
"an UNRECOGNIZED feature name is still a valid one — that is the \
forward-compatibility case, not an invalid scalar"
);
}
#[test]
fn a_canonical_record_with_an_invalid_id_is_never_known() {
let clean = canonical::to_canonical_dagcbor(&definition()).unwrap();
assert!(
matches!(decode_definition(&clean).unwrap(), Decoded::Known(_)),
"the clean record must decode, or this proves nothing"
);
let tainted = patch_same_length(&clean, "decision", "deci ion");
assert_eq!(tainted.len(), clean.len(), "the patch changed the length");
match decode_definition(&tainted).unwrap() {
Decoded::Unknown(raw) => assert_eq!(raw.bytes(), tainted.as_slice()),
Decoded::Known(known) => panic!(
"a record naming control `deci ion` decoded as valid and minted {}",
known.definition_id().unwrap()
),
}
let tainted_option = patch_same_length(&clean, "allow-once", "allow once");
assert!(
!matches!(
decode_definition(&tainted_option).unwrap(),
Decoded::Known(_)
),
"an option id carrying a space decoded as valid"
);
}