use std::eprintln;
use crate::core::counter::{CounterCodeV1, CounterCodeV2};
use crate::stream::encode::{
encode_counter_auto_v1, encode_counter_auto_v2, encode_counter_v1, encode_counter_v2,
};
use crate::stream::parse::{parse_counter, parse_counter_v2};
use crate::stream::qb64_to_qb2;
use super::{from_hex, load};
fn max_count_for_ss(ss: usize) -> u64 {
let exp = u32::try_from(ss).expect("counter soft size fits u32");
64u64.pow(exp) - 1
}
#[test]
#[allow(
clippy::panic,
clippy::print_stderr,
reason = "test-only differential harness: intentional panic on codec failure and eprintln skip logging per task spec"
)]
fn counter_v1_differential_vs_keripy() {
let vectors = load("counter_v1");
assert!(!vectors.is_empty(), "counter_v1 corpus is empty");
let mut skipped = 0usize;
for v in &vectors {
let Ok(code) = CounterCodeV1::from_hard(&v.code) else {
eprintln!("SKIP counter_v1: unimplemented code {:?}", v.code);
skipped += 1;
continue;
};
let count = v
.count
.unwrap_or_else(|| panic!("counter_v1 vector {:?} missing count", v.code));
let fits = u64::from(count) <= max_count_for_ss(code.soft_size());
let encoded = if fits {
encode_counter_v1(code, count)
.unwrap_or_else(|e| panic!("encode_counter_v1 {:?}: {e:?}", v.code))
} else {
encode_counter_auto_v1(code, count).unwrap_or_else(|e| {
panic!(
"encode_counter_auto_v1 {:?} count {count}: {e:?} \
(cesr cannot promote a code keripy promotes)",
v.code
)
})
};
assert_eq!(
encoded,
v.qb64.as_bytes(),
"qb64 encode mismatch for {:?} count {count}",
v.code
);
let expected_code = if fits {
code
} else {
code.to_big()
.unwrap_or_else(|| panic!("code {:?} overflows but has no big variant", v.code))
};
let (dcode, dcount, rest) = parse_counter(v.qb64.as_bytes())
.unwrap_or_else(|e| panic!("parse_counter {:?}: {e:?}", v.qb64));
assert_eq!(
dcode, expected_code,
"decoded code mismatch for {:?}",
v.qb64
);
assert_eq!(dcount, count, "decoded count mismatch for {:?}", v.qb64);
assert!(rest.is_empty(), "non-empty remainder for {:?}", v.qb64);
let qb2 = qb64_to_qb2(v.qb64.as_bytes())
.unwrap_or_else(|e| panic!("qb64_to_qb2 {:?}: {e:?}", v.qb64));
assert_eq!(
qb2,
from_hex(&v.qb2),
"qb2 transcode mismatch for {:?}",
v.qb64
);
}
eprintln!(
"counter_v1: {} vectors, {skipped} skipped (unimplemented codes)",
vectors.len()
);
}
#[test]
#[allow(
clippy::panic,
clippy::print_stderr,
reason = "test-only differential harness: intentional panic on codec failure and eprintln skip logging per task spec"
)]
fn counter_v2_differential_vs_keripy() {
let vectors = load("counter_v2");
assert!(!vectors.is_empty(), "counter_v2 corpus is empty");
let mut skipped = 0usize;
for v in &vectors {
let Ok(code) = CounterCodeV2::from_hard(&v.code) else {
eprintln!("SKIP counter_v2: unimplemented code {:?}", v.code);
skipped += 1;
continue;
};
let count = v
.count
.unwrap_or_else(|| panic!("counter_v2 vector {:?} missing count", v.code));
let fits = u64::from(count) <= max_count_for_ss(code.soft_size());
let encoded = if fits {
encode_counter_v2(code, count)
.unwrap_or_else(|e| panic!("encode_counter_v2 {:?}: {e:?}", v.code))
} else {
encode_counter_auto_v2(code, count).unwrap_or_else(|e| {
panic!(
"encode_counter_auto_v2 {:?} count {count}: {e:?} \
(cesr cannot promote a code keripy promotes)",
v.code
)
})
};
assert_eq!(
encoded,
v.qb64.as_bytes(),
"qb64 encode mismatch for {:?} count {count}",
v.code
);
let expected_code = if fits {
code
} else {
code.to_big()
.unwrap_or_else(|| panic!("code {:?} overflows but has no big variant", v.code))
};
let (dcode, dcount, rest) = parse_counter_v2(v.qb64.as_bytes())
.unwrap_or_else(|e| panic!("parse_counter_v2 {:?}: {e:?}", v.qb64));
assert_eq!(
dcode, expected_code,
"decoded code mismatch for {:?}",
v.qb64
);
assert_eq!(dcount, count, "decoded count mismatch for {:?}", v.qb64);
assert!(rest.is_empty(), "non-empty remainder for {:?}", v.qb64);
let qb2 = qb64_to_qb2(v.qb64.as_bytes())
.unwrap_or_else(|e| panic!("qb64_to_qb2 {:?}: {e:?}", v.qb64));
assert_eq!(
qb2,
from_hex(&v.qb2),
"qb2 transcode mismatch for {:?}",
v.qb64
);
}
eprintln!(
"counter_v2: {} vectors, {skipped} skipped (unimplemented codes)",
vectors.len()
);
}