use ms_codec::{encode, inspect, Payload, Tag};
use zeroize::Zeroizing;
fn to_hex(bytes: &[u8]) -> String {
let mut s = String::with_capacity(bytes.len() * 2);
for b in bytes {
s.push_str(&format!("{b:02x}"));
}
s
}
fn sentinel_entropy() -> Vec<u8> {
let mut v = Vec::with_capacity(16);
for _ in 0..4 {
v.extend_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]);
}
v
}
#[test]
fn inspect_report_debug_does_not_leak_entropy() {
let entropy = sentinel_entropy();
let s = encode(Tag::ENTR, &Payload::Entr(entropy.clone())).unwrap();
let report = inspect(&s).unwrap();
let dbg = format!("{report:?}");
assert!(
!dbg.to_lowercase().contains("deadbeef"),
"Debug leaked the entropy hex: {dbg}"
);
assert!(
!dbg.contains("222, 173, 190, 239"),
"Debug leaked the entropy as a Vec element dump: {dbg}"
);
assert!(
dbg.to_lowercase().contains("redacted"),
"Debug must render payload_bytes as a redaction placeholder: {dbg}"
);
assert!(dbg.contains("hrp"), "Debug must still surface `hrp`: {dbg}");
assert!(
dbg.contains("kind"),
"Debug must still surface `kind`: {dbg}"
);
assert!(
dbg.contains("prefix_byte"),
"Debug must still surface `prefix_byte`: {dbg}"
);
assert!(
dbg.contains("language"),
"Debug must still surface `language`: {dbg}"
);
}
#[test]
fn inspect_report_payload_bytes_is_zeroizing() {
let entropy = sentinel_entropy();
let s = encode(Tag::ENTR, &Payload::Entr(entropy)).unwrap();
let report = inspect(&s).unwrap();
fn _assert_zeroizing(_: &Zeroizing<Vec<u8>>) {}
_assert_zeroizing(&report.payload_bytes);
}
#[test]
fn inspect_report_payload_bytes_deref_readers_still_compile() {
let entropy = sentinel_entropy();
let s = encode(Tag::ENTR, &Payload::Entr(entropy.clone())).unwrap();
let report = inspect(&s).unwrap();
let _n = report.payload_bytes.len();
let hexed = to_hex(&report.payload_bytes);
assert_eq!(hexed, to_hex(&entropy), "deref read recovers the bytes");
}