use amaters_core::Query;
use amaters_core::compute::{EncryptedU8, FheKeyPair};
use amaters_core::storage::MemoryStorage;
use amaters_core::traits::StorageEngine;
use amaters_core::types::{CipherBlob, Key, Predicate, col};
use amaters_net::server::AqlServiceImpl;
use std::sync::Arc;
mod common;
fn encrypt_u8(value: u8, keypair: &FheKeyPair) -> CipherBlob {
let encrypted = EncryptedU8::encrypt(value, keypair.client_key());
encrypted.to_cipher_blob().expect("Failed to serialize")
}
#[tokio::test]
async fn test_filter_query_basic() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(18, &keypair);
let predicate = Predicate::Gt(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(result.is_ok(), "Filter query should execute successfully");
}
#[tokio::test]
async fn test_filter_query_with_eq_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let _service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 25),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(25, &keypair);
let predicate = Predicate::Eq(col("age"), rhs_value);
assert!(matches!(predicate, Predicate::Eq(_, _)));
}
#[tokio::test]
async fn test_filter_query_with_lt_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(30, &keypair);
let predicate = Predicate::Lt(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(result.is_ok(), "Filter query should execute successfully");
}
#[tokio::test]
async fn test_filter_query_empty_result() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(100, &keypair);
let predicate = Predicate::Gt(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(result.is_ok(), "Filter query should execute successfully");
}
#[tokio::test]
async fn test_filter_query_on_empty_storage() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage);
let rhs_value = encrypt_u8(18, &keypair);
let predicate = Predicate::Gt(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(
result.is_ok(),
"Filter query on empty storage should succeed"
);
}
#[tokio::test]
async fn test_filter_query_with_lte_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(35, &keypair);
let predicate = Predicate::Lte(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(result.is_ok(), "Filter query should execute successfully");
}
#[tokio::test]
async fn test_filter_query_with_gte_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(25, &keypair);
let predicate = Predicate::Gte(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(result.is_ok(), "Filter query should execute successfully");
}
#[tokio::test]
#[ignore] async fn test_filter_query_complex_and_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs1 = encrypt_u8(18, &keypair);
let rhs2 = encrypt_u8(65, &keypair);
let pred1 = Predicate::Gt(col("age"), rhs1);
let pred2 = Predicate::Lt(col("age"), rhs2);
let predicate = Predicate::And(Box::new(pred1), Box::new(pred2));
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
let _ = result;
}
#[tokio::test]
#[ignore] async fn test_filter_query_complex_or_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 70),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs1 = encrypt_u8(18, &keypair);
let rhs2 = encrypt_u8(65, &keypair);
let pred1 = Predicate::Lt(col("age"), rhs1);
let pred2 = Predicate::Gt(col("age"), rhs2);
let predicate = Predicate::Or(Box::new(pred1), Box::new(pred2));
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
let _ = result;
}
#[tokio::test]
async fn test_filter_query_with_not_predicate() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
let test_ages = vec![
("user:1", 15u8),
("user:2", 25),
("user:3", 35),
("user:4", 25),
];
for (key_str, age) in &test_ages {
let key = Key::from_str(key_str);
let encrypted_age = encrypt_u8(*age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(25, &keypair);
let pred = Predicate::Eq(col("age"), rhs_value);
let predicate = Predicate::Not(Box::new(pred));
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let result = service.execute_query_internal(query).await;
assert!(result.is_ok(), "Filter query should execute successfully");
}
#[tokio::test]
async fn test_filter_performance_with_large_dataset() {
let keypair = FheKeyPair::generate().expect("Failed to generate keys");
keypair.set_as_global_server_key();
let storage = Arc::new(MemoryStorage::new());
let service = AqlServiceImpl::new(storage.clone());
for i in 0..100u8 {
let key = Key::from_str(&format!("user:{:03}", i));
let age = (i % 80) + 10; let encrypted_age = encrypt_u8(age, &keypair);
storage
.put(&key, &encrypted_age)
.await
.expect("Failed to insert");
}
let rhs_value = encrypt_u8(50, &keypair);
let predicate = Predicate::Gt(col("age"), rhs_value);
let query = Query::Filter {
collection: "users".to_string(),
predicate,
};
let start = std::time::Instant::now();
let result = service.execute_query_internal(query).await;
let duration = start.elapsed();
assert!(result.is_ok(), "Filter query should execute successfully");
println!("Filter query on 100 rows took: {:?}", duration);
}