133 lines
4.2 KiB
Rust
133 lines
4.2 KiB
Rust
//! `BfldError` Display format pinning. Operators grep log lines for these
|
|
//! strings; format drift between minor versions breaks monitoring queries.
|
|
//! Each variant gets a test that asserts the documented substrings appear.
|
|
|
|
#![cfg(feature = "std")]
|
|
|
|
use wifi_densepose_bfld::BfldError;
|
|
|
|
#[test]
|
|
fn invalid_magic_displays_both_expected_and_actual_in_hex() {
|
|
let err = BfldError::InvalidMagic(0xDEAD_BEEF);
|
|
let s = err.to_string();
|
|
assert!(s.contains("invalid BFLD magic"), "got: {s}");
|
|
assert!(s.contains("0xBF1D0001"), "expected magic missing: {s}");
|
|
assert!(s.contains("0xDEADBEEF"), "actual magic missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn unsupported_version_displays_the_offending_version() {
|
|
let err = BfldError::UnsupportedVersion(99);
|
|
let s = err.to_string();
|
|
assert!(s.contains("unsupported BFLD version"), "got: {s}");
|
|
assert!(s.contains("99"), "version number missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn crc_mismatch_displays_both_values_in_hex() {
|
|
let err = BfldError::Crc {
|
|
expected: 0xCAFEBABE,
|
|
actual: 0xDEADBEEF,
|
|
};
|
|
let s = err.to_string();
|
|
assert!(s.contains("payload CRC mismatch"), "got: {s}");
|
|
assert!(s.contains("0xCAFEBABE"), "expected missing: {s}");
|
|
assert!(s.contains("0xDEADBEEF"), "actual missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn privacy_violation_displays_the_sink_reason() {
|
|
let err = BfldError::PrivacyViolation {
|
|
reason: "NetworkKind",
|
|
};
|
|
let s = err.to_string();
|
|
assert!(s.contains("privacy violation"), "got: {s}");
|
|
assert!(s.contains("NetworkKind"), "reason missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_privacy_class_displays_the_offending_byte() {
|
|
let err = BfldError::InvalidPrivacyClass(7);
|
|
let s = err.to_string();
|
|
assert!(s.contains("invalid PrivacyClass byte"), "got: {s}");
|
|
assert!(s.contains("7"), "byte value missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn truncated_frame_displays_got_and_need_byte_counts() {
|
|
let err = BfldError::TruncatedFrame { got: 50, need: 86 };
|
|
let s = err.to_string();
|
|
assert!(s.contains("truncated frame"), "got: {s}");
|
|
assert!(s.contains("50"), "got count missing: {s}");
|
|
assert!(s.contains("86"), "need count missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn malformed_section_displays_offset_and_reason() {
|
|
let err = BfldError::MalformedSection {
|
|
offset: 1234,
|
|
reason: "section body runs past buffer end",
|
|
};
|
|
let s = err.to_string();
|
|
assert!(s.contains("malformed payload section"), "got: {s}");
|
|
assert!(s.contains("1234"), "offset missing: {s}");
|
|
assert!(s.contains("buffer end"), "reason missing: {s}");
|
|
}
|
|
|
|
#[test]
|
|
fn invalid_demote_displays_both_from_and_to_class_bytes() {
|
|
let err = BfldError::InvalidDemote { from: 2, to: 1 };
|
|
let s = err.to_string();
|
|
assert!(s.contains("invalid demote"), "got: {s}");
|
|
assert!(s.contains("from class 2"), "from missing: {s}");
|
|
assert!(s.contains("to class 1"), "to missing: {s}");
|
|
}
|
|
|
|
// --- meta: error implements std::error::Error (for ? + dyn use) -------
|
|
|
|
#[test]
|
|
fn bfld_error_implements_std_error_trait() {
|
|
fn assert_error_trait<E: std::error::Error>() {}
|
|
assert_error_trait::<BfldError>();
|
|
}
|
|
|
|
#[test]
|
|
fn bfld_error_is_debug_so_panic_unwrap_messages_carry_diagnostics() {
|
|
let err = BfldError::Crc {
|
|
expected: 0xAA,
|
|
actual: 0xBB,
|
|
};
|
|
let debug = format!("{err:?}");
|
|
assert!(debug.contains("Crc"), "Debug must show variant name: {debug}");
|
|
}
|
|
|
|
// --- catch-all: every variant has a non-empty Display -----------------
|
|
|
|
#[test]
|
|
fn every_variant_has_a_non_empty_display_string() {
|
|
let cases: Vec<BfldError> = vec![
|
|
BfldError::InvalidMagic(0),
|
|
BfldError::UnsupportedVersion(0),
|
|
BfldError::Crc {
|
|
expected: 0,
|
|
actual: 0,
|
|
},
|
|
BfldError::PrivacyViolation { reason: "X" },
|
|
BfldError::InvalidPrivacyClass(0),
|
|
BfldError::TruncatedFrame { got: 0, need: 0 },
|
|
BfldError::MalformedSection {
|
|
offset: 0,
|
|
reason: "X",
|
|
},
|
|
BfldError::InvalidDemote { from: 0, to: 0 },
|
|
];
|
|
for err in cases {
|
|
let s = err.to_string();
|
|
assert!(!s.is_empty(), "Display for {err:?} returned empty string");
|
|
assert!(
|
|
s.len() >= 5,
|
|
"Display for {err:?} suspiciously short: {s:?}",
|
|
);
|
|
}
|
|
}
|