use sqlitegraph::backend::native::types::NativeBackendError;
use sqlitegraph::backend::native::{decode_persistent_header, get_slice_safe};
#[test]
fn test_get_slice_safe_bounds_checking() {
let data = vec![1, 2, 3, 4, 5];
let result = get_slice_safe(&data, 1, 3);
assert!(result.is_ok());
assert_eq!(result.unwrap(), &[2, 3, 4]);
let result = get_slice_safe(&data, 3, 3); assert!(result.is_err());
match result.unwrap_err() {
NativeBackendError::InvalidHeader { field, reason } => {
assert_eq!(field, "header_data");
assert!(reason.contains("slice access out of bounds"));
assert!(reason.contains("start=3"));
assert!(reason.contains("len=3"));
assert!(reason.contains("data_len=5"));
}
other => panic!("Expected InvalidHeader error, got: {:?}", other),
}
let result = get_slice_safe(&data, 2, 3); assert!(result.is_ok());
assert_eq!(result.unwrap(), &[3, 4, 5]);
let result = get_slice_safe(&data, 5, 1); assert!(result.is_err());
}
#[test]
fn test_decode_header_with_80_bytes() {
let mut header_data = vec![0u8; 80];
header_data[0..8].copy_from_slice(b"SQLTGRPH");
header_data[8..12].copy_from_slice(&2u32.to_be_bytes());
let result = decode_persistent_header(&header_data);
match result {
Ok(_) => println!("Header decoded successfully"),
Err(e) => {
println!("Header decode failed with error (acceptable): {:?}", e);
match e {
NativeBackendError::InvalidHeader { .. } => {
}
other => {
println!("Error type: {:?}", other);
}
}
}
}
}
#[test]
fn test_decode_header_with_too_few_bytes() {
let header_data = vec![0u8; 79];
let result = decode_persistent_header(&header_data);
assert!(result.is_err());
match result.unwrap_err() {
NativeBackendError::FileTooSmall { size, min_size } => {
assert_eq!(size, 79);
assert_eq!(min_size, 80);
}
other => panic!("Expected FileTooSmall error, got: {:?}", other),
}
}
#[test]
fn test_no_panic_on_any_input() {
let test_cases = vec![
vec![], vec![0u8; 10], vec![0u8; 79], vec![0u8; 80], vec![0u8; 81], vec![0xFF; 100], ];
for (i, test_data) in test_cases.iter().enumerate() {
println!("Test case {}: {} bytes", i, test_data.len());
let result = std::panic::catch_unwind(|| decode_persistent_header(test_data));
match result {
Ok(Ok(_)) => {
println!(" → Success");
}
Ok(Err(e)) => {
println!(" → Error (acceptable): {:?}", e);
}
Err(panic_info) => {
panic!(
"PANIC in test case {} with {} bytes: {:?}",
i,
test_data.len(),
panic_info
);
}
}
}
}