use lib_q_keccak::{
OptimizationLevel,
fast_loop_absorb_optimized,
p1600_optimized,
};
#[test]
fn test_optimization_level_best_available() {
let best = OptimizationLevel::best_available();
assert!(best.is_available());
}
#[test]
fn test_optimization_level_is_available() {
assert!(OptimizationLevel::Reference.is_available());
let _ = OptimizationLevel::Basic.is_available();
let _ = OptimizationLevel::Advanced.is_available();
let _ = OptimizationLevel::Maximum.is_available();
}
#[test]
fn test_p1600_optimized_reference() {
let mut state1 = [0u64; 25];
let mut state2 = [0u64; 25];
state1[0] = 0x1234567890ABCDEF;
state2[0] = 0x1234567890ABCDEF;
lib_q_keccak::keccak_p(&mut state1, 24);
p1600_optimized(&mut state2, OptimizationLevel::Reference);
assert_eq!(state1, state2);
}
#[test]
fn test_p1600_optimized_all_levels() {
for level in &[
OptimizationLevel::Reference,
OptimizationLevel::Basic,
OptimizationLevel::Advanced,
OptimizationLevel::Maximum,
] {
if !level.is_available() {
continue;
}
let mut state = [0u64; 25];
state[0] = 0x1234567890ABCDEF;
p1600_optimized(&mut state, *level);
assert_ne!(state[0], 0x1234567890ABCDEF);
assert!(state.iter().any(|&x| x != 0));
}
}
#[test]
fn test_fast_loop_absorb_optimized_reference() {
let mut state = [0u64; 25];
let data = b"This is test data for the fast loop absorption function";
let offset = fast_loop_absorb_optimized(&mut state, data, OptimizationLevel::Reference);
assert!(offset > 0);
assert_ne!(state[0], 0);
}
#[test]
fn test_fast_loop_absorb_optimized_all_levels() {
for level in &[
OptimizationLevel::Reference,
OptimizationLevel::Basic,
OptimizationLevel::Advanced,
OptimizationLevel::Maximum,
] {
if !level.is_available() {
continue;
}
let mut state = [0u64; 25];
let data = b"This is test data for fast loop absorption testing with different optimization levels";
let offset = fast_loop_absorb_optimized(&mut state, data, *level);
assert!(offset > 0);
assert_ne!(state[0], 0);
}
}
#[test]
fn test_fast_loop_absorb_empty_data() {
let mut state = [0u64; 25];
let data = b"";
let offset = fast_loop_absorb_optimized(&mut state, data, OptimizationLevel::Reference);
assert_eq!(offset, 0);
assert_eq!(state[0], 0);
}
#[test]
fn test_fast_loop_absorb_small_data() {
let mut state = [0u64; 25];
let data = b"1234567";
let offset = fast_loop_absorb_optimized(&mut state, data, OptimizationLevel::Reference);
assert_eq!(offset, 0);
}
#[test]
fn test_fast_loop_absorb_exact_lane_size() {
let mut state = [0u64; 25];
let data = b"12345678";
let offset = fast_loop_absorb_optimized(&mut state, data, OptimizationLevel::Reference);
assert_eq!(offset, 8);
assert_ne!(state, [0u64; 25]);
}
#[test]
fn test_fast_loop_absorb_multiple_lanes() {
let mut state = [0u64; 25];
let data = b"1234567812345678123456781234567812345678";
let offset = fast_loop_absorb_optimized(&mut state, data, OptimizationLevel::Reference);
assert_eq!(offset, 40);
assert_ne!(state, [0u64; 25]);
}
#[test]
fn test_fast_loop_absorb_partial_lanes() {
let mut state = [0u64; 25];
let data = b"1234567812345678123";
let offset = fast_loop_absorb_optimized(&mut state, data, OptimizationLevel::Reference);
assert_eq!(offset, 16);
assert_ne!(state, [0u64; 25]);
}
#[cfg(all(feature = "simd", keccak_portable_simd))]
mod simd_tests {
use lib_q_keccak::OptimizationLevel;
use lib_q_keccak::parallel::p1600_parallel;
#[test]
fn test_parallel_processing_reference() {
let mut states = [[0u64; 25]; 4];
for (i, state) in states.iter_mut().enumerate() {
state[0] = 0x1234567890ABCDEF + i as u64;
}
let original_values: Vec<u64> = states.iter().map(|s| s[0]).collect();
p1600_parallel(&mut states, OptimizationLevel::Reference);
for (i, state) in states.iter().enumerate() {
assert_ne!(state[0], original_values[i]);
}
}
#[test]
fn test_parallel_processing_all_levels() {
for level in &[
OptimizationLevel::Reference,
OptimizationLevel::Basic,
OptimizationLevel::Advanced,
OptimizationLevel::Maximum,
] {
if !level.is_available() {
continue;
}
let mut states = [[0u64; 25]; 8];
for (i, state) in states.iter_mut().enumerate() {
state[0] = 0x1234567890ABCDEF + i as u64;
}
let original_values: Vec<u64> = states.iter().map(|s| s[0]).collect();
p1600_parallel(&mut states, *level);
for (i, state) in states.iter().enumerate() {
assert_ne!(state[0], original_values[i]);
}
}
}
#[test]
fn test_parallel_processing_different_sizes() {
let mut states1 = [[0u64; 25]; 1];
states1[0][0] = 0x1234567890ABCDEF;
p1600_parallel(&mut states1, OptimizationLevel::Reference);
assert_ne!(states1[0][0], 0x1234567890ABCDEF);
let mut states2 = [[0u64; 25]; 2];
states2[0][0] = 0x1234567890ABCDEF;
states2[1][0] = 0xFEDCBA0987654321;
p1600_parallel(&mut states2, OptimizationLevel::Reference);
assert_ne!(states2[0][0], 0x1234567890ABCDEF);
assert_ne!(states2[1][0], 0xFEDCBA0987654321);
let mut states3 = [[0u64; 25]; 3];
for (i, state) in states3.iter_mut().enumerate() {
state[0] = 0x1234567890ABCDEF + i as u64;
}
p1600_parallel(&mut states3, OptimizationLevel::Reference);
for (i, state) in states3.iter().enumerate() {
assert_ne!(state[0], 0x1234567890ABCDEF + i as u64);
}
let mut states7 = [[0u64; 25]; 7];
for (i, state) in states7.iter_mut().enumerate() {
state[0] = 0x1234567890ABCDEF + i as u64;
}
p1600_parallel(&mut states7, OptimizationLevel::Reference);
for (i, state) in states7.iter().enumerate() {
assert_ne!(state[0], 0x1234567890ABCDEF + i as u64);
}
}
}
#[cfg(all(feature = "simd", feature = "multithreading"))]
mod multithreading_tests {
use lib_q_keccak::OptimizationLevel;
use lib_q_keccak::parallel::p1600_multithreaded;
#[test]
fn test_multithreaded_processing() {
let states = [[0u64; 25]; 4];
let mut states = states;
for (i, state) in states.iter_mut().enumerate() {
state[0] = 0x1234567890ABCDEF + i as u64;
}
let original_values: Vec<u64> = states.iter().map(|s| s[0]).collect();
let result = p1600_multithreaded(&states, OptimizationLevel::Reference);
assert!(result.is_ok());
let processed_states = result.unwrap();
for (i, state) in processed_states.iter().enumerate() {
assert_ne!(state[0], original_values[i]);
}
}
}