#[cfg(feature = "production")]
mod tests {
use blvm_consensus::script::*;
#[test]
fn test_script_cache_hit() {
let script_sig = vec![0x51];
let script_pubkey = vec![0x51, 0x51];
let result1 = verify_script(&script_sig, &script_pubkey, None, 0).unwrap();
let result2 = verify_script(&script_sig, &script_pubkey, None, 0).unwrap();
assert_eq!(result1, result2, "Cached results must match original");
}
#[test]
fn test_script_cache_different_scripts() {
let script_sig1 = vec![0x51];
let script_pubkey1 = vec![0x51, 0x51];
let script_sig2 = vec![0x52];
let script_pubkey2 = vec![0x52, 0x52];
let result1 = verify_script(&script_sig1, &script_pubkey1, None, 0).unwrap();
let result2 = verify_script(&script_sig2, &script_pubkey2, None, 0).unwrap();
let result1_repeat = verify_script(&script_sig1, &script_pubkey1, None, 0).unwrap();
assert_eq!(result1, result1_repeat, "Cache must preserve script-specific results");
}
#[test]
fn test_hash_cache_op_hash160() {
let input = vec![0x51, 0x52, 0x53];
let script = vec![0x51, 0x51, 0x51, 0x51, 0x51, 0xa9];
let mut stack1 = Vec::new();
for _ in 0..5 {
stack1.push(input.clone());
}
let result1 = eval_script(&script, &mut stack1, 0).unwrap();
let mut stack2 = Vec::new();
for _ in 0..5 {
stack2.push(input.clone());
}
let result2 = eval_script(&script, &mut stack2, 0).unwrap();
assert_eq!(result1, result2, "Hash cache must produce identical results");
}
#[test]
fn test_hash_cache_op_hash256() {
let input = vec![0x51, 0x52, 0x53];
let script = vec![0x51, 0x51, 0x51, 0x51, 0x51, 0xaa];
let mut stack1 = Vec::new();
for _ in 0..5 {
stack1.push(input.clone());
}
let result1 = eval_script(&script, &mut stack1, 0).unwrap();
let mut stack2 = Vec::new();
for _ in 0..5 {
stack2.push(input.clone());
}
let result2 = eval_script(&script, &mut stack2, 0).unwrap();
assert_eq!(result1, result2, "Hash cache must produce identical results");
}
#[test]
fn test_hash_cache_distinguishes_operations() {
let input = vec![0x51, 0x52, 0x53];
let script_hash160 = vec![0x51, 0x51, 0x51, 0x51, 0x51, 0xa9]; let script_hash256 = vec![0x51, 0x51, 0x51, 0x51, 0x51, 0xaa];
let mut stack1 = Vec::new();
for _ in 0..5 {
stack1.push(input.clone());
}
let result_hash160 = eval_script(&script_hash160, &mut stack1, 0).unwrap();
let mut stack2 = Vec::new();
for _ in 0..5 {
stack2.push(input.clone());
}
let result_hash256 = eval_script(&script_hash256, &mut stack2, 0).unwrap();
assert!(result_hash160 == true || result_hash160 == false);
assert!(result_hash256 == true || result_hash256 == false);
}
#[test]
fn test_stack_pool_reuse() {
let script1 = vec![0x51, 0x51];
let script2 = vec![0x52, 0x52];
let result1 = verify_script(&script1, &vec![0x51], None, 0).unwrap();
let result2 = verify_script(&script2, &vec![0x52], None, 0).unwrap();
let result3 = verify_script(&script1, &vec![0x51], None, 0).unwrap();
assert_eq!(result1, result3, "Stack pooling must not affect results");
assert!(result1 == true || result1 == false);
assert!(result2 == true || result2 == false);
}
#[test]
fn test_cache_performance_indicator() {
use std::time::Instant;
let script_sig = vec![0x51];
let script_pubkey = vec![0x51, 0x51];
let start1 = Instant::now();
let _result1 = verify_script(&script_sig, &script_pubkey, None, 0).unwrap();
let duration1 = start1.elapsed();
let start2 = Instant::now();
let _result2 = verify_script(&script_sig, &script_pubkey, None, 0).unwrap();
let duration2 = start2.elapsed();
assert!(duration2.as_micros() <= duration1.as_micros() + 1000,
"Cache hit should be fast ({}us vs {}us)",
duration2.as_micros(), duration1.as_micros());
}
#[test]
fn test_cache_with_witness() {
let script_sig = vec![0x51];
let script_pubkey = vec![0x51];
let witness = Some(vec![0x52]);
let result1 = verify_script(&script_sig, &script_pubkey, witness.as_ref(), 0).unwrap();
let result2 = verify_script(&script_sig, &script_pubkey, witness.as_ref(), 0).unwrap();
assert_eq!(result1, result2, "Cache must work with witness data");
}
}