use anchor_lang::solana_program::hash::hashv;
use rand::{prelude::SliceRandom, thread_rng};
use crate::{blob::Blob, compute_blob_digest, initial_hash, CHUNK_SIZE};
fn test(blob: Vec<u8>) {
println!(
"Running test with blob size {} ({} chunks)",
blob.len(),
blob.len().div_ceil(CHUNK_SIZE as usize)
);
let mut blober = Blob::new(0, 0, blob.len() as u32, 0);
let mut chunks = blob
.chunks(CHUNK_SIZE as usize)
.enumerate()
.map(|(i, chunk)| (i as u16, chunk))
.collect::<Vec<_>>();
chunks.shuffle(&mut thread_rng());
for (i, chunk) in &chunks {
blober.insert(0, *i, chunk);
}
let expected_blob_digest = compute_blob_digest(&chunks);
assert_eq!(&expected_blob_digest, blober.blob_digest());
}
#[test]
fn specific_blob_sizes() {
let test_cases = [
Vec::new(),
vec![0u8; 1],
vec![0u8; CHUNK_SIZE as usize - 1],
vec![0u8; CHUNK_SIZE as usize],
vec![0u8; CHUNK_SIZE as usize + 1],
vec![0u8; CHUNK_SIZE as usize - 1],
vec![0u8; CHUNK_SIZE as usize],
vec![0u8; CHUNK_SIZE as usize + 1],
];
for blob in test_cases {
test(blob);
}
}
#[test]
fn test_blob() {
let mut acc = Blob::new(0, 0, CHUNK_SIZE as u32 * 5, 0);
let mut current_digest = initial_hash();
assert_eq!(current_digest, acc.digest);
acc.insert(0, 0, &[0u8; CHUNK_SIZE as usize]);
current_digest = hashv(&[
¤t_digest,
0_u16.to_le_bytes().as_ref(),
&[0u8; CHUNK_SIZE as usize],
])
.to_bytes();
assert_eq!(current_digest, acc.digest);
acc.insert(0, 2, &[2u8; CHUNK_SIZE as usize]);
current_digest = hashv(&[
¤t_digest,
2_u16.to_le_bytes().as_ref(),
&[2u8; CHUNK_SIZE as usize],
])
.to_bytes();
assert_eq!(current_digest, acc.digest);
acc.insert(0, 3, &[3u8; CHUNK_SIZE as usize]);
current_digest = hashv(&[
¤t_digest,
3_u16.to_le_bytes().as_ref(),
&[3u8; CHUNK_SIZE as usize],
])
.to_bytes();
assert_eq!(current_digest, acc.digest);
acc.insert(0, 1, &[1u8; CHUNK_SIZE as usize]);
current_digest = hashv(&[
¤t_digest,
1_u16.to_le_bytes().as_ref(),
&[1u8; CHUNK_SIZE as usize],
])
.to_bytes();
assert_eq!(current_digest, acc.digest);
acc.insert(0, 4, &[4u8; CHUNK_SIZE as usize]);
current_digest = hashv(&[
¤t_digest,
4_u16.to_le_bytes().as_ref(),
&[4u8; CHUNK_SIZE as usize],
])
.to_bytes();
assert_eq!(current_digest, acc.digest);
assert_eq!(acc.blob_digest(), ¤t_digest);
}