#[test]
fn test_gqa_kv_dim_calculation() {
let config = create_kv_gqa_config();
assert_eq!(config.head_dim(), 8);
assert_eq!(config.kv_dim(), 16);
}
#[test]
fn test_gqa_cache_size_smaller() {
let mha_config = create_kv_test_config();
let gqa_config = create_kv_gqa_config();
let max_positions = 512;
let mha_cache = StreamingKVCache::new(
mha_config.num_layers,
max_positions,
mha_config.num_kv_heads,
mha_config.head_dim(),
);
let gqa_cache = StreamingKVCache::new(
gqa_config.num_layers,
max_positions,
gqa_config.num_kv_heads,
gqa_config.head_dim(),
);
assert!(gqa_cache.memory_bytes() < mha_cache.memory_bytes());
}
#[test]
fn test_gqa_forward_with_cache_full_sequence() {
let config = create_kv_gqa_config();
let mut model = GpuModel::new(config.clone()).expect("test value should be present");
let mock = MockExecutor::new("gqa_full_seq");
model.with_test_executor(Box::new(mock));
let mut cache = StreamingKVCache::new(
config.num_layers,
128,
config.num_kv_heads,
config.head_dim(),
);
let token_ids: Vec<usize> = (0..20).map(|i| i % config.vocab_size).collect();
let result = model.forward_gpu_with_cache(&token_ids, &mut cache);
assert!(result.is_ok());
assert_eq!(cache.len(), 20);
}
#[test]
fn test_forward_with_cache_boundary_token() {
let config = create_kv_single_layer_config();
let mut model = GpuModel::new(config.clone()).expect("test value should be present");
let mock = MockExecutor::new("boundary_token");
model.with_test_executor(Box::new(mock));
let mut cache = StreamingKVCache::new(
config.num_layers,
64,
config.num_kv_heads,
config.head_dim(),
);
let max_valid_token = config.vocab_size - 1;
let result = model.forward_gpu_with_cache(&[max_valid_token], &mut cache);
assert!(result.is_ok());
}
#[test]
fn test_incremental_with_empty_cache() {
let config = create_kv_single_layer_config();
let mut model = GpuModel::new(config.clone()).expect("test value should be present");
let mock = MockExecutor::new("empty_cache");
model.with_test_executor(Box::new(mock));
let mut cache = StreamingKVCache::new(
config.num_layers,
64,
config.num_kv_heads,
config.head_dim(),
);
let result = model.forward_gpu_incremental(1, &mut cache);
assert!(result.is_ok());
assert_eq!(cache.len(), 1);
}
#[test]
fn test_full_inference_workflow() {
let config = create_kv_test_config();
let mut model = GpuModel::new(config.clone()).expect("test value should be present");
let mock = MockExecutor::new("full_workflow");
model.with_test_executor(Box::new(mock));
let mut cache = StreamingKVCache::new(
config.num_layers,
128,
config.num_kv_heads,
config.head_dim(),
);
let prompt = vec![1, 2, 3, 4, 5];
let prefill_result = model.forward_gpu_with_cache(&prompt, &mut cache);
assert!(prefill_result.is_ok());
assert_eq!(cache.len(), prompt.len());
for i in 0..10 {
let token = (i + 6) % config.vocab_size;
let decode_result = model.forward_gpu_incremental(token, &mut cache);
assert!(decode_result.is_ok());
}
assert_eq!(cache.len(), prompt.len() + 10);
}
#[test]
fn test_repeated_generations_with_cache_clear() {
let config = create_kv_single_layer_config();
let mut model = GpuModel::new(config.clone()).expect("test value should be present");
let mock = MockExecutor::new("repeated_gen");
model.with_test_executor(Box::new(mock));
let mut cache = StreamingKVCache::new(
config.num_layers,
64,
config.num_kv_heads,
config.head_dim(),
);
for run in 0..3 {
cache.clear();
assert!(cache.is_empty());
let prompt = vec![run % config.vocab_size];
let result = model.forward_gpu_with_cache(&prompt, &mut cache);
assert!(result.is_ok(), "Run {} failed", run);
for i in 0..5 {
let token = (run + i + 1) % config.vocab_size;
let result = model.forward_gpu_incremental(token, &mut cache);
assert!(result.is_ok(), "Incremental {} in run {} failed", i, run);
}
}
}
#[test]
fn test_kv_cache_with_different_configs() {
let configs = vec![
create_kv_test_config(),
create_kv_gqa_config(),
create_kv_single_layer_config(),
create_kv_deep_config(),
];
for (i, config) in configs.into_iter().enumerate() {
let mut model = GpuModel::new(config.clone()).expect("test value should be present");
let mock = MockExecutor::new(&format!("config_{}", i));
model.with_test_executor(Box::new(mock));
let mut cache = StreamingKVCache::new(
config.num_layers,
64,
config.num_kv_heads,
config.head_dim(),
);
let result = model.forward_gpu_with_cache(&[1, 2], &mut cache);
assert!(result.is_ok(), "Config {} failed", i);
assert_eq!(cache.len(), 2, "Config {} cache length mismatch", i);
}
}