#[cfg(feature = "retry")]
mod retry_integration {
use dbnexus::{RetryPolicy, is_idempotent_operation};
#[test]
fn test_retry_policy_with_db_config() {
let policy = RetryPolicy::default();
assert_eq!(policy.max_retries, 3);
assert!(is_idempotent_operation("SELECT * FROM users"));
assert!(!is_idempotent_operation("INSERT INTO users VALUES (1)"));
}
}
#[cfg(feature = "failover")]
mod failover_integration {
use dbnexus::FailoverConfig;
#[test]
fn test_failover_config_with_multiple_urls() {
let config = FailoverConfig {
urls: vec![
"postgres://primary:5432/db".to_string(),
"postgres://replica1:5432/db".to_string(),
"postgres://replica2:5432/db".to_string(),
],
health_check_query: Some("SELECT 1".to_string()),
failover_threshold: 3,
};
assert_eq!(config.urls.len(), 3);
}
}
#[cfg(feature = "replica-routing")]
mod replica_integration {
use dbnexus::ReplicaConfig;
#[test]
fn test_replica_config_with_lag_threshold() {
let config = ReplicaConfig {
replica_urls: vec!["postgres://replica:5432/db".to_string()],
max_lag_seconds: 5.0,
lag_check_interval_secs: 10,
};
assert!((config.max_lag_seconds - 5.0).abs() < f64::EPSILON);
}
}
#[cfg(feature = "scatter-gather")]
mod scatter_integration {
use dbnexus::{AggregateFunction, AggregateValue, PartialFailurePolicy, ScatterResult, ShardError};
#[test]
fn test_scatter_result_aggregation() {
let result = ScatterResult {
shard_row_counts: vec![(0, 100), (1, 200), (2, 150)],
failed_shards: vec![ShardError {
shard_id: 3,
error: "timeout".to_string(),
}],
aggregated: Some(AggregateValue::Count(450)),
};
assert_eq!(result.shard_row_counts.len(), 3);
assert_eq!(result.failed_shards.len(), 1);
}
#[test]
fn test_partial_failure_policies() {
assert_ne!(PartialFailurePolicy::Fail, PartialFailurePolicy::BestEffort);
}
#[test]
fn test_aggregate_function_types() {
let _count = AggregateFunction::Count;
let _sum = AggregateFunction::Sum("amount".to_string());
let _avg = AggregateFunction::Avg("price".to_string());
let _min = AggregateFunction::Min("score".to_string());
let _max = AggregateFunction::Max("score".to_string());
}
}
#[cfg(feature = "saga")]
mod saga_integration {
use dbnexus::{InMemorySagaLog, SagaError, SagaLog, SagaStatus};
#[test]
fn test_saga_lifecycle() {
let store = InMemorySagaLog::new();
let log = SagaLog {
saga_id: "e2e-test-saga".to_string(),
status: SagaStatus::Running,
steps: vec![],
};
store.insert(log);
let retrieved = store.get("e2e-test-saga").unwrap();
assert_eq!(retrieved.status, SagaStatus::Running);
store.update_status("e2e-test-saga", SagaStatus::Completed);
let final_log = store.get("e2e-test-saga").unwrap();
assert_eq!(final_log.status, SagaStatus::Completed);
}
#[test]
fn test_saga_error_types() {
let exec_err = SagaError::ExecutionFailed("test".to_string());
let comp_err = SagaError::CompensationFailed("test".to_string());
let timeout_err = SagaError::Timeout("test".to_string());
assert!(format!("{exec_err}").contains("execution failed"));
assert!(format!("{comp_err}").contains("compensation failed"));
assert!(format!("{timeout_err}").contains("timeout"));
}
}
#[cfg(feature = "distributed-id")]
mod distributed_id_integration {
use std::collections::HashSet;
use std::sync::Arc;
use std::thread;
use dbnexus::{DistributedIdGenerator, SnowflakeIdGenerator};
#[test]
fn test_snowflake_id_e2e() {
let id_gen = Arc::new(SnowflakeIdGenerator::new(42, 1_700_000_000_000).unwrap());
let mut handles = Vec::new();
for _ in 0..5 {
let gen_clone = Arc::clone(&id_gen);
handles.push(thread::spawn(move || {
(0..200)
.map(|_| gen_clone.next_id().expect("ID generation should succeed"))
.collect::<Vec<_>>()
}));
}
let mut all_ids = HashSet::new();
for handle in handles {
for id in handle.join().unwrap() {
assert!(all_ids.insert(id), "Duplicate ID: {id}");
}
}
assert_eq!(all_ids.len(), 1000);
}
#[test]
fn test_id_parse_roundtrip() {
let id_gen = SnowflakeIdGenerator::new(99, 1_700_000_000_000).unwrap();
let id = id_gen.next_id().expect("ID generation should succeed");
let components = id_gen.parse_id(id);
assert_eq!(components.machine_id, 99);
assert!(components.timestamp_ms > 0);
}
}