#![cfg(all(feature = "compression", feature = "checksum", feature = "messagepack"))]
use cachekit_core::{ByteStorage, StorageEnvelope};
use sha2::{Digest, Sha256};
const FIXTURE: &str = include_str!("vectors/wire-format.json");
const FIXTURE_SHA256: &str = "d6184a945d8cb22491b5c937414fe4d01e682d084ccec9dae9526d0ffba650cb";
#[derive(serde::Deserialize)]
struct WireFormatFixture {
limits: Limits,
vectors: Vec<Vector>,
version: String,
}
#[derive(serde::Deserialize)]
struct Limits {
max_compressed_size: usize,
max_compression_ratio: u64,
max_uncompressed_size: usize,
}
#[derive(serde::Deserialize)]
struct Vector {
name: String,
format: String,
input_hex: String,
input_size: usize,
envelope_hex: String,
envelope_size: usize,
envelope_encoding: Option<String>,
derived_from: Option<String>,
}
impl Vector {
fn is_legacy(&self) -> bool {
self.envelope_encoding.is_none()
}
}
fn load_fixture() -> WireFormatFixture {
serde_json::from_str(FIXTURE).expect("wire-format.json fixture must parse")
}
#[test]
fn fixture_integrity_pinned_sha256() {
let digest = hex::encode(Sha256::digest(FIXTURE.as_bytes()));
assert_eq!(
digest, FIXTURE_SHA256,
"vendored wire-format.json drifted from its pinned sha256 — \
re-vendor from the protocol repo and update FIXTURE_SHA256 deliberately"
);
}
#[test]
fn fixture_is_current_version_with_vectors() {
let fixture = load_fixture();
assert_eq!(fixture.version, "1.1.0");
let legacy = fixture.vectors.iter().filter(|v| v.is_legacy()).count();
let bin = fixture.vectors.len() - legacy;
assert!(
legacy >= 6,
"legacy vectors are retained forever as legacy-read proof; expected at least the original 6, got {legacy}"
);
assert!(
bin >= 6,
"protocol 1.1 pins a *_bin twin per legacy vector; expected at least 6, got {bin}"
);
}
#[test]
fn fixture_limits_match_implementation() {
let fixture = load_fixture();
let storage = ByteStorage::new(None);
assert_eq!(
fixture.limits.max_uncompressed_size,
storage.max_uncompressed_size()
);
assert_eq!(
fixture.limits.max_compressed_size,
storage.max_compressed_size()
);
assert_eq!(
fixture.limits.max_compression_ratio,
storage.max_compression_ratio()
);
}
#[test]
fn vectors_decode_to_expected_payload() {
let storage = ByteStorage::new(None);
for vector in load_fixture().vectors {
let input = hex::decode(&vector.input_hex).expect("input_hex must decode");
let envelope = hex::decode(&vector.envelope_hex).expect("envelope_hex must decode");
assert_eq!(
input.len(),
vector.input_size,
"[{}] input_size mismatch",
vector.name
);
assert_eq!(
envelope.len(),
vector.envelope_size,
"[{}] envelope_size mismatch",
vector.name
);
let (payload, format) = storage
.retrieve(&envelope)
.unwrap_or_else(|e| panic!("[{}] retrieve failed: {e:?}", vector.name));
assert_eq!(
payload, input,
"[{}] decoded payload differs from input",
vector.name
);
assert_eq!(format, vector.format, "[{}] format mismatch", vector.name);
assert!(
storage.validate(&envelope),
"[{}] validate() rejected canonical envelope",
vector.name
);
}
}
#[test]
fn vectors_reencode_byte_identical() {
let storage = ByteStorage::new(None);
for vector in load_fixture()
.vectors
.into_iter()
.filter(|v| !v.is_legacy())
{
let input = hex::decode(&vector.input_hex).expect("input_hex must decode");
let expected = hex::decode(&vector.envelope_hex).expect("envelope_hex must decode");
let encoded = storage
.store(&input, Some(vector.format.clone()))
.unwrap_or_else(|e| panic!("[{}] store failed: {e:?}", vector.name));
assert_eq!(
hex::encode(&encoded),
hex::encode(&expected),
"[{}] re-encoded envelope is not byte-identical to the canonical vector",
vector.name
);
}
}
#[test]
fn envelope_codec_roundtrip_byte_identical() {
for vector in load_fixture()
.vectors
.into_iter()
.filter(|v| !v.is_legacy())
{
let canonical = hex::decode(&vector.envelope_hex).expect("envelope_hex must decode");
let envelope: StorageEnvelope = rmp_serde::from_slice(&canonical)
.unwrap_or_else(|e| panic!("[{}] envelope must deserialize: {e}", vector.name));
let reserialized = rmp_serde::to_vec(&envelope)
.unwrap_or_else(|e| panic!("[{}] envelope must reserialize: {e}", vector.name));
assert_eq!(
hex::encode(&reserialized),
hex::encode(&canonical),
"[{}] MessagePack envelope layout is not byte-stable",
vector.name
);
}
}
#[test]
fn bin_twins_are_bin_encoded_and_field_identical_to_legacy() {
let fixture = load_fixture();
let twins: Vec<&Vector> = fixture.vectors.iter().filter(|v| !v.is_legacy()).collect();
assert!(
!twins.is_empty(),
"protocol 1.1 fixture must carry *_bin twins"
);
for twin in twins {
assert_eq!(
twin.envelope_encoding.as_deref(),
Some("bin"),
"[{}] unknown envelope_encoding",
twin.name
);
let parent_name = twin
.derived_from
.as_deref()
.unwrap_or_else(|| panic!("[{}] *_bin twin missing derived_from", twin.name));
let parent = fixture
.vectors
.iter()
.find(|v| v.name == parent_name)
.unwrap_or_else(|| {
panic!(
"[{}] derived_from '{parent_name}' not in fixture",
twin.name
)
});
let twin_bytes = hex::decode(&twin.envelope_hex).expect("envelope_hex must decode");
assert_eq!(
twin_bytes[0], 0x94,
"[{}] outer fixarray(4) marker",
twin.name
);
assert_eq!(
twin_bytes[1],
0xc4,
"[{}] compressed_data is not bin8-encoded: marker 0x{:02x}",
twin.name,
twin_bytes[1]
);
let parent_bytes = hex::decode(&parent.envelope_hex).expect("envelope_hex must decode");
let twin_env: StorageEnvelope = rmp_serde::from_slice(&twin_bytes)
.unwrap_or_else(|e| panic!("[{}] twin must deserialize: {e}", twin.name));
let parent_env: StorageEnvelope = rmp_serde::from_slice(&parent_bytes)
.unwrap_or_else(|e| panic!("[{parent_name}] parent must deserialize: {e}"));
assert_eq!(
twin_env.compressed_data, parent_env.compressed_data,
"[{}]",
twin.name
);
assert_eq!(twin_env.checksum, parent_env.checksum, "[{}]", twin.name);
assert_eq!(
twin_env.original_size, parent_env.original_size,
"[{}]",
twin.name
);
assert_eq!(twin_env.format, parent_env.format, "[{}]", twin.name);
}
}