#[cfg(test)]
use crate::{MerkleProof, MerkleTree};
use sha2::{Digest, Sha256};
fn create_test_data(count: usize) -> Vec<Vec<u8>> {
(0..count)
.map(|i| format!("Test data {}", i).into_bytes())
.collect()
}
#[test]
fn test_empty_tree() {
let tree = MerkleTree::new(Vec::new());
assert!(tree.is_empty());
assert_eq!(tree.len(), 0);
assert!(tree.root_hash().is_none());
assert_eq!(tree.root_hash_hex(), "Empty tree");
}
#[test]
fn test_single_node_tree() {
let data = vec![b"Single node".to_vec()];
let tree = MerkleTree::new(data.clone());
assert!(!tree.is_empty());
assert_eq!(tree.len(), 1);
let expected_hash = Sha256::digest(&data[0]).to_vec();
assert_eq!(tree.root_hash().unwrap(), expected_hash);
}
#[test]
fn test_multiple_nodes_tree() {
let data = create_test_data(4);
let tree = MerkleTree::new(data.clone());
assert_eq!(tree.len(), 4);
assert!(tree.root_hash().is_some());
let hash0 = Sha256::digest(&data[0]).to_vec();
let hash1 = Sha256::digest(&data[1]).to_vec();
let hash2 = Sha256::digest(&data[2]).to_vec();
let hash3 = Sha256::digest(&data[3]).to_vec();
let mut hasher = Sha256::new();
hasher.update(&hash0);
hasher.update(&hash1);
let hash01 = hasher.finalize().to_vec();
let mut hasher = Sha256::new();
hasher.update(&hash2);
hasher.update(&hash3);
let hash23 = hasher.finalize().to_vec();
let mut hasher = Sha256::new();
hasher.update(&hash01);
hasher.update(&hash23);
let expected_root = hasher.finalize().to_vec();
assert_eq!(tree.root_hash().unwrap(), expected_root);
}
#[test]
fn test_odd_number_of_nodes() {
let data = create_test_data(3);
let tree = MerkleTree::new(data.clone());
assert_eq!(tree.len(), 4);
let hash0 = Sha256::digest(&data[0]).to_vec();
let hash1 = Sha256::digest(&data[1]).to_vec();
let hash2 = Sha256::digest(&data[2]).to_vec();
let hash3 = hash2.clone();
let mut hasher = Sha256::new();
hasher.update(&hash0);
hasher.update(&hash1);
let hash01 = hasher.finalize().to_vec();
let mut hasher = Sha256::new();
hasher.update(&hash2);
hasher.update(&hash3);
let hash23 = hasher.finalize().to_vec();
let mut hasher = Sha256::new();
hasher.update(&hash01);
hasher.update(&hash23);
let expected_root = hasher.finalize().to_vec();
assert_eq!(tree.root_hash().unwrap(), expected_root);
}
#[test]
fn test_proof_generation_and_verification() {
let data = create_test_data(8);
let tree = MerkleTree::new(data.clone());
for (i, item) in data.iter().enumerate() {
let proof = tree.generate_proof(item).unwrap();
let root_hash = tree.root_hash().unwrap();
let is_valid = MerkleTree::verify_proof(item, &proof, &root_hash);
assert!(is_valid, "Proof for item {} should be valid", i);
}
}
#[test]
fn test_proof_verification_fails_for_tampered_data() {
let data = create_test_data(8);
let tree = MerkleTree::new(data.clone());
let item = &data[3];
let proof = tree.generate_proof(item).unwrap();
let root_hash = tree.root_hash().unwrap();
let mut tampered_item = item.clone();
tampered_item[0] ^= 1;
let is_valid = MerkleTree::verify_proof(&tampered_item, &proof, &root_hash);
assert!(!is_valid, "Proof should not be valid for tampered data");
}
#[test]
fn test_proof_verification_fails_for_tampered_proof() {
let data = create_test_data(8);
let tree = MerkleTree::new(data.clone());
let item = &data[3];
let mut proof = tree.generate_proof(item).unwrap();
let root_hash = tree.root_hash().unwrap();
if !proof.is_empty() {
let mut tampered_hash = proof[0].0.clone();
tampered_hash[0] ^= 1; proof[0] = (tampered_hash, proof[0].1);
}
let is_valid = MerkleTree::verify_proof(item, &proof, &root_hash);
assert!(!is_valid, "Proof should not be valid when tampered with");
}
#[test]
fn test_large_tree() {
let data = create_test_data(1000);
let tree = MerkleTree::new(data.clone());
assert_eq!(tree.len(), 1000);
let item = &data[456]; let proof = tree.generate_proof(item).unwrap();
let root_hash = tree.root_hash().unwrap();
let is_valid = MerkleTree::verify_proof(item, &proof, &root_hash);
assert!(is_valid, "Proof should be valid for large tree");
let max_proof_length = (1000_f64).log2().ceil() as usize;
assert!(
proof.len() <= max_proof_length,
"Proof length {} should not exceed log2(n) = {}",
proof.len(),
max_proof_length
);
}
#[test]
fn test_proof_for_nonexistent_data() {
let data = create_test_data(8);
let tree = MerkleTree::new(data.clone());
let nonexistent_data = b"This data doesn't exist".to_vec();
let proof = tree.generate_proof(&nonexistent_data);
assert!(proof.is_none(), "Proof should be None for nonexistent data");
}
#[test]
fn test_tree_clone() {
let data = create_test_data(8);
let tree = MerkleTree::new(data.clone());
let tree_clone = tree.clone();
assert_eq!(tree.root_hash(), tree_clone.root_hash());
assert_eq!(tree.len(), tree_clone.len());
}
#[test]
fn test_different_trees_produce_different_roots() {
let data1 = create_test_data(8);
let tree1 = MerkleTree::new(data1.clone());
let mut data2 = data1.clone();
data2[0] = b"Different data".to_vec();
let tree2 = MerkleTree::new(data2.clone());
assert_ne!(tree1.root_hash(), tree2.root_hash());
}
#[test]
fn test_proof_cross_verification_fails() {
let data1 = create_test_data(8);
let tree1 = MerkleTree::new(data1.clone());
let mut data2 = data1.clone();
data2[3] = b"Different data".to_vec();
let tree2 = MerkleTree::new(data2.clone());
let item = &data1[2]; let proof1 = tree1.generate_proof(item).unwrap();
let root_hash2 = tree2.root_hash().unwrap();
let is_valid = MerkleTree::verify_proof(item, &proof1, &root_hash2);
assert!(!is_valid, "Cross-tree verification should fail");
}
#[test]
fn test_merkle_proof_type() {
let data = create_test_data(4);
let tree = MerkleTree::new(data.clone());
let proof: Option<MerkleProof> = tree.generate_proof(&data[0]);
assert!(proof.is_some());
let root_hash = tree.root_hash().unwrap();
let is_valid = MerkleTree::verify_proof(&data[0], &proof.unwrap(), &root_hash);
assert!(is_valid);
}