#![cfg_attr(docsrs, feature(doc_cfg))]
pub use amaters_core as core;
pub use amaters_net as net;
pub use amaters_cluster as cluster;
pub use amaters_sdk_rust as sdk;
pub mod prelude {
pub use amaters_core::{AmateRSError, ErrorContext, Result as CoreResult};
pub use amaters_core::{
CipherBlob, ColumnRef, Key, Predicate, Query, QueryBuilder, Update, col,
};
pub use amaters_core::StorageEngine;
pub use amaters_net::{NetError, NetResult};
pub use amaters_net::{AqlServerBuilder, AqlServiceImpl};
pub use amaters_cluster::{RaftError, RaftResult};
pub use amaters_cluster::{
Command, LogEntry, LogIndex, NodeId, NodeState, RaftConfig, RaftLog, RaftNode, Term,
};
pub use amaters_cluster::{
AppendEntriesRequest, AppendEntriesResponse, RequestVoteRequest, RequestVoteResponse,
};
pub use amaters_cluster::{CandidateState, LeaderState, PersistentState, VolatileState};
pub use amaters_sdk_rust::{AmateRSClient, QueryResult, ServerInfo};
pub use amaters_sdk_rust::{ClientConfig, RetryConfig, TlsConfig};
pub use amaters_sdk_rust::{Result as SdkResult, SdkError};
pub use amaters_sdk_rust::{FheEncryptor, FheKeys};
pub use amaters_sdk_rust::{FilterBuilder, FluentQueryBuilder, PredicateBuilder, query};
}
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const NAME: &str = env!("CARGO_PKG_NAME");
#[cfg(test)]
mod tests {
use crate::cluster;
use crate::core;
use crate::net;
use crate::sdk;
use crate::{NAME, VERSION};
#[test]
fn test_version() {
assert!(VERSION.contains('.'), "VERSION should be semver format");
assert_eq!(NAME, "amaters");
}
#[test]
fn test_module_access() {
let _ = core::VERSION;
let _ = net::VERSION;
let _ = cluster::VERSION;
let _ = sdk::VERSION;
}
#[test]
fn test_prelude_imports() {
use crate::prelude::*;
let key = Key::from_str("test");
assert!(!key.as_bytes().is_empty());
}
#[test]
fn test_prelude_core_error_types() {
use crate::prelude::*;
let ctx = ErrorContext::new("test error".to_string());
let err = AmateRSError::ValidationError(ctx);
let msg = format!("{}", err);
assert!(!msg.is_empty());
}
#[test]
fn test_prelude_core_types() {
use crate::prelude::*;
let key = Key::from_str("test_key");
assert_eq!(key.as_bytes(), b"test_key");
let blob = CipherBlob::new(vec![1, 2, 3]);
assert_eq!(blob.len(), 3);
assert_eq!(blob.as_bytes(), &[1, 2, 3]);
let cr = col("my_column");
assert_eq!(cr.name, "my_column");
let _get = Query::Get {
collection: "users".into(),
key: Key::from_str("k"),
};
let _filter = Query::Filter {
collection: "users".into(),
predicate: Predicate::Eq(col("x"), CipherBlob::new(vec![1])),
};
let _range = Query::Range {
collection: "data".into(),
start: Key::from_str("a"),
end: Key::from_str("z"),
};
let q = QueryBuilder::new("test").get(Key::from_str("k"));
match q {
Query::Get { collection, .. } => assert_eq!(collection, "test"),
_ => panic!("Expected Get query"),
}
}
#[test]
fn test_prelude_cluster_types() {
use crate::prelude::*;
let config = RaftConfig::new(1, vec![1, 2, 3]);
assert_eq!(config.node_id, 1);
let cmd = Command::from_str("SET key value");
assert!(!cmd.data.is_empty());
let entry = LogEntry::new(1, 1, cmd);
assert_eq!(entry.index, 1);
assert_eq!(entry.term, 1);
let state = NodeState::Follower;
assert_eq!(state, NodeState::Follower);
let _: NodeId = 1;
let _: Term = 1;
let _: LogIndex = 1;
}
#[test]
fn test_prelude_cluster_rpc_types() {
use crate::prelude::*;
let rvr = RequestVoteRequest {
term: 1,
candidate_id: 1,
last_log_index: 0,
last_log_term: 0,
};
assert_eq!(rvr.term, 1);
let rvresp = RequestVoteResponse {
term: 1,
vote_granted: true,
leader_hint: None,
};
assert!(rvresp.vote_granted);
let aer = AppendEntriesRequest {
term: 1,
leader_id: 1,
prev_log_index: 0,
prev_log_term: 0,
entries: vec![],
leader_commit: 0,
fencing_token: None,
};
assert_eq!(aer.leader_id, 1);
let aeresp = AppendEntriesResponse {
term: 1,
success: true,
last_log_index: 0,
conflict_index: None,
conflict_term: None,
leader_hint: None,
fencing_token: None,
};
assert!(aeresp.success);
}
#[test]
fn test_prelude_cluster_state_types() {
use crate::prelude::*;
let ps = PersistentState::new();
assert_eq!(ps.current_term, 0);
let vs = VolatileState::new();
assert_eq!(vs.node_state, NodeState::Follower);
}
#[test]
fn test_prelude_sdk_config_types() {
use crate::prelude::*;
let config = ClientConfig::default();
assert!(!config.server_addr.is_empty() || config.server_addr.is_empty());
let retry = RetryConfig::default();
let _ = retry.max_retries;
let _tls = TlsConfig::default();
}
#[test]
fn test_prelude_sdk_query_builder() {
use crate::prelude::*;
let q = query("users").get(Key::from_str("user:1"));
match q {
Query::Get { collection, key } => {
assert_eq!(collection, "users");
assert_eq!(key.as_bytes(), b"user:1");
}
_ => panic!("Expected Get query"),
}
let fb = FluentQueryBuilder::new("test");
let q = fb.set(Key::from_str("k"), CipherBlob::new(vec![1]));
match q {
Query::Set { collection, .. } => assert_eq!(collection, "test"),
_ => panic!("Expected Set query"),
}
let q = query("users")
.where_clause()
.eq(col("status"), CipherBlob::new(vec![1]))
.and(Predicate::Gt(col("age"), CipherBlob::new(vec![18])))
.build();
match q {
Query::Filter { collection, .. } => assert_eq!(collection, "users"),
_ => panic!("Expected Filter query"),
}
}
#[test]
fn test_prelude_net_error_types() {
use crate::prelude::*;
let _err: NetError = NetError::Timeout("test".to_string());
let _result: NetResult<()> = Ok(());
}
#[test]
fn test_prelude_sdk_error_types() {
use crate::prelude::*;
let _err: SdkError = SdkError::Connection("test".to_string());
let _result: SdkResult<()> = Ok(());
}
#[test]
fn test_reexport_core_types_consistency() {
let key_via_facade = core::Key::from_str("test");
let key_via_direct = amaters_core::Key::from_str("test");
assert_eq!(key_via_facade.as_bytes(), key_via_direct.as_bytes());
let blob_via_facade = core::CipherBlob::new(vec![1, 2, 3]);
let blob_via_direct = amaters_core::CipherBlob::new(vec![1, 2, 3]);
assert_eq!(blob_via_facade.as_bytes(), blob_via_direct.as_bytes());
}
#[test]
fn test_reexport_net_consistency() {
assert_eq!(net::VERSION, amaters_net::VERSION);
}
#[test]
fn test_reexport_cluster_consistency() {
assert_eq!(cluster::VERSION, amaters_cluster::VERSION);
assert_eq!(cluster::NAME, amaters_cluster::NAME);
}
#[test]
fn test_reexport_sdk_consistency() {
assert_eq!(sdk::VERSION, amaters_sdk_rust::VERSION);
}
#[test]
fn test_cross_crate_key_compatibility() {
let key = core::Key::from_str("cross_crate_key");
let q = sdk::query("test").get(key);
match q {
core::Query::Get { key, .. } => {
assert_eq!(key.as_bytes(), b"cross_crate_key");
}
_ => panic!("Expected Get query"),
}
}
#[test]
fn test_cross_crate_cipher_blob_compatibility() {
let blob = core::CipherBlob::new(vec![10, 20, 30]);
let q = sdk::query("test").set(core::Key::from_str("k"), blob);
match q {
core::Query::Set { value, .. } => {
assert_eq!(value.as_bytes(), &[10, 20, 30]);
}
_ => panic!("Expected Set query"),
}
}
#[test]
fn test_cross_crate_predicate_compatibility() {
let pred = core::Predicate::Eq(core::col("status"), core::CipherBlob::new(vec![1]));
let q = sdk::query("users").filter(pred);
match q {
core::Query::Filter { predicate, .. } => match predicate {
core::Predicate::Eq(col_ref, value) => {
assert_eq!(col_ref.name, "status");
assert_eq!(value.as_bytes(), &[1]);
}
_ => panic!("Expected Eq predicate"),
},
_ => panic!("Expected Filter query"),
}
}
#[test]
fn test_cross_crate_query_with_planner() {
let q = sdk::query("users").get(core::Key::from_str("user:1"));
let planner = core::compute::QueryPlanner::new();
let plan = planner.plan(&q);
assert!(plan.is_ok(), "Planning should succeed for Get query");
}
#[test]
fn test_feature_flags_defined() {
}
#[test]
fn test_storage_engine_accessible() {
fn _check_trait_via_prelude() {
use crate::prelude::StorageEngine;
fn _takes_engine<T: StorageEngine>(_e: &T) {}
}
fn _check_trait_via_core() {
use crate::core::StorageEngine;
fn _takes_engine<T: StorageEngine>(_e: &T) {}
}
}
#[test]
fn test_storage_types_accessible_via_facade() {
let _ = std::mem::size_of::<core::storage::LsmTreeConfig>();
let _ = std::mem::size_of::<core::storage::MemtableConfig>();
let _ = std::mem::size_of::<core::storage::SSTableConfig>();
let _ = std::mem::size_of::<core::storage::CompactionConfig>();
let _ = std::mem::size_of::<core::storage::BloomFilterConfig>();
let _ = std::mem::size_of::<core::storage::BlockCacheConfig>();
}
#[test]
fn test_compute_types_accessible_via_facade() {
let _ = std::mem::size_of::<core::compute::QueryPlanner>();
let _ = std::mem::size_of::<core::compute::PhysicalPlan>();
let _ = std::mem::size_of::<core::compute::LogicalPlan>();
let _ = std::mem::size_of::<core::compute::PlanCost>();
let _ = std::mem::size_of::<core::compute::CircuitBuilder>();
let _ = std::mem::size_of::<core::compute::FheExecutor>();
}
#[test]
fn test_cluster_types_accessible_via_facade() {
let _ = std::mem::size_of::<cluster::RaftConfig>();
let _ = std::mem::size_of::<cluster::Command>();
let _ = std::mem::size_of::<cluster::LogEntry>();
let _ = std::mem::size_of::<cluster::RaftLog>();
let _ = std::mem::size_of::<cluster::PersistentState>();
let _ = std::mem::size_of::<cluster::VolatileState>();
let _ = std::mem::size_of::<cluster::Snapshot>();
let _ = std::mem::size_of::<cluster::SnapshotConfig>();
}
#[test]
fn test_sdk_types_accessible_via_facade() {
let _ = std::mem::size_of::<sdk::ClientConfig>();
let _ = std::mem::size_of::<sdk::RetryConfig>();
let _ = std::mem::size_of::<sdk::TlsConfig>();
let _ = std::mem::size_of::<sdk::FheKeys>();
let _ = std::mem::size_of::<sdk::QueryCacheConfig>();
}
#[test]
fn test_compression_accessible_via_facade() {
use core::storage::compression::{CompressionType, compress_block, decompress_block};
let data = b"test data for compression";
let compressed =
compress_block(data, CompressionType::Lz4).expect("LZ4 compression should succeed");
let decompressed = decompress_block(&compressed, CompressionType::Lz4, data.len())
.expect("LZ4 decompression should succeed");
assert_eq!(&decompressed, &data[..]);
}
#[test]
fn test_lsm_tree_via_facade() {
use core::storage::LsmTree;
let dir = std::env::temp_dir().join("amaters_facade_lsm_test");
if dir.exists() {
std::fs::remove_dir_all(&dir).ok();
}
let tree = LsmTree::new(&dir).expect("LsmTree creation should succeed");
let key = core::Key::from_str("facade_test");
let value = core::CipherBlob::new(vec![42, 43, 44]);
tree.put(key.clone(), value.clone())
.expect("put should succeed");
let retrieved = tree
.get(&key)
.expect("get should succeed")
.expect("key should exist");
assert_eq!(retrieved.as_bytes(), &[42, 43, 44]);
tree.delete(key.clone()).expect("delete should succeed");
let gone = tree.get(&key).expect("get should succeed");
assert!(gone.is_none());
tree.close().expect("close should succeed");
std::fs::remove_dir_all(&dir).ok();
}
#[test]
fn test_query_planner_via_facade() {
use core::compute::planner::QueryPlanner;
let planner = QueryPlanner::new();
let q = core::QueryBuilder::new("items").filter(core::Predicate::Gt(
core::col("price"),
core::CipherBlob::new(vec![100]),
));
let plan = planner.plan(&q).expect("planning should succeed");
let cost = planner.estimate_cost(&plan);
assert!(cost.total_cost > 0.0, "Cost should be positive");
assert!(cost.estimated_rows > 0, "Should estimate some rows");
}
#[test]
fn test_raft_config_via_facade() {
let config = cluster::RaftConfig::new(1, vec![1, 2, 3]);
let node = cluster::RaftNode::new(config);
assert!(node.is_ok(), "RaftNode creation should succeed");
}
}