mod common;
use common::{build_log, SimpleHasher};
use malt::{Log, TreeHasher};
#[test]
fn empty_root() {
let log = Log::new(SimpleHasher);
assert_eq!(log.root(), SimpleHasher.empty());
assert_eq!(log.size(), 0);
}
#[test]
fn single_leaf() {
let mut log = Log::new(SimpleHasher);
log.append(b"hello");
assert_eq!(log.root(), SimpleHasher.leaf(b"hello"));
assert_eq!(log.size(), 1);
}
#[test]
fn append_returns_sequential_indices() {
let mut log = Log::new(SimpleHasher);
for i in 0u64..10 {
let index = log.append(format!("entry-{i}").as_bytes());
assert_eq!(index, i, "append should return sequential 0-based indices");
}
}
#[test]
fn a_equiv_incremental_equals_batch() {
for n in 1u64..=33 {
let log_a = build_log(n);
let log_b = build_log(n);
assert_eq!(
log_a.root(),
log_b.root(),
"A-EQUIV failed for n={n}: two logs with same inputs produced different roots"
);
}
}
#[test]
fn deterministic_root() {
let build = || {
let mut log = Log::new(SimpleHasher);
for i in 0..20 {
log.append(format!("entry-{i}").as_bytes());
}
log.root()
};
assert_eq!(build(), build(), "same inputs must produce same root");
}
#[test]
fn two_leaf_structure() {
let mut log = Log::new(SimpleHasher);
log.append(b"alpha");
log.append(b"beta");
let expected = SimpleHasher.node(&SimpleHasher.leaf(b"alpha"), &SimpleHasher.leaf(b"beta"));
assert_eq!(log.root(), expected);
}
#[test]
fn domain_separation() {
let leaf = SimpleHasher.leaf(b"test");
let node = SimpleHasher.node(&SimpleHasher.leaf(b"a"), &SimpleHasher.leaf(b"b"));
assert_ne!(
leaf, node,
"leaf and node hashes must differ (domain separation)"
);
}
#[test]
fn power_of_two_sizes() {
for exp in 1..=5u32 {
let n = 1u64 << exp;
let log_a = build_log(n);
let log_b = build_log(n);
assert_eq!(
log_a.root(),
log_b.root(),
"power-of-two size {n} should produce deterministic root"
);
}
}