use nord_format::cbin::{Cbin, Generation, Header, RawBody};
use nord_format::formats::{ns3, ns4};
use std::io::Cursor;
#[path = "support/format_table.rs"]
mod format_table;
use format_table::formats;
fn synthesize(tag: &str, body_len: usize, version: u32, generation: Generation) -> Vec<u8> {
let mut header = Header::new(tag, (0, 0), version);
header.generation = generation;
let file = Cbin {
header,
body: RawBody(vec![0u8; body_len]),
};
let mut out = Cursor::new(Vec::new());
file.write_to(&mut out).unwrap();
out.into_inner()
}
#[test]
fn every_tag_dispatches_and_round_trips_both_generations() {
for (tag, body_len, version) in formats() {
for generation in [Generation::V1, Generation::V0] {
let bytes = synthesize(tag, body_len, version, generation);
let entity = nord_format::from_stream(&mut Cursor::new(&bytes))
.unwrap_or_else(|e| panic!("{tag:?} ({generation:?}): {e}"));
assert_eq!(
entity.identity().format,
tag,
"{tag:?} dispatched to {:?}",
entity.identity()
);
let back = nord_format::to_bytes(&entity)
.unwrap_or_else(|e| panic!("{tag:?} ({generation:?}) re-encode: {e}"));
assert_eq!(back, bytes, "{tag:?} ({generation:?}) round trip");
}
}
}
#[test]
fn nul_padded_tags_are_matched_in_full() {
let bytes = synthesize("nssX", 27, 100, Generation::V0);
let err = nord_format::from_stream(&mut Cursor::new(&bytes)).unwrap_err();
assert!(
err.to_string().contains("unknown format"),
"expected an unknown-format refusal, got {err}"
);
}
#[test]
fn version_gates_cover_the_decoded_formats_only() {
let bytes = synthesize(
ns3::program::FORMAT,
ns3::program::BODY_LEN,
999,
Generation::V1,
);
assert!(nord_format::from_stream(&mut Cursor::new(&bytes)).is_err());
let bytes = synthesize(
ns4::settings::FORMAT,
ns4::settings::BODY_LEN,
999,
Generation::V1,
);
assert!(nord_format::from_stream(&mut Cursor::new(&bytes)).is_ok());
}