mod fixture;
#[test]
fn test_proxy_config_types() {
use heliosdb_proxy::connection_pool::PoolConfig;
use heliosdb_proxy::{NodeEndpoint, NodeRole};
let config = PoolConfig {
min_connections: 5,
max_connections: 100,
..Default::default()
};
assert_eq!(config.max_connections, 100);
let node = NodeEndpoint::new("localhost", 5432).with_role(NodeRole::Primary);
assert_eq!(node.address(), "localhost:5432");
assert_eq!(node.role, NodeRole::Primary);
}
#[test]
fn test_node_id_uniqueness() {
use heliosdb_proxy::NodeId;
let ids: Vec<NodeId> = (0..100).map(|_| NodeId::new()).collect();
for i in 0..ids.len() {
for j in (i + 1)..ids.len() {
assert_ne!(ids[i], ids[j], "NodeId should be unique");
}
}
}
#[test]
fn test_module_01_connection_pooling_config() {
use heliosdb_proxy::config::{PoolingMode, PreparedStatementMode};
let session = heliosdb_proxy::config::PoolModeConfig::session_mode();
assert_eq!(session.mode, PoolingMode::Session);
assert_eq!(
session.prepared_statement_mode,
PreparedStatementMode::Named
);
let tx = heliosdb_proxy::config::PoolModeConfig::transaction_mode();
assert_eq!(tx.mode, PoolingMode::Transaction);
assert_eq!(tx.prepared_statement_mode, PreparedStatementMode::Track);
let stmt = heliosdb_proxy::config::PoolModeConfig::statement_mode();
assert_eq!(stmt.mode, PoolingMode::Statement);
assert_eq!(stmt.prepared_statement_mode, PreparedStatementMode::Disable);
for cfg in [&session, &tx, &stmt] {
assert!(cfg.max_pool_size > 0);
assert!(cfg.idle_timeout_secs > 0);
}
}
#[test]
fn test_module_02_load_balancer_config() {
use heliosdb_proxy::load_balancer::{
LoadBalancer, LoadBalancerConfig as LbCfg, RoutingStrategy,
};
let lb = LoadBalancer::new(LbCfg {
read_write_split: true,
read_strategy: RoutingStrategy::RoundRobin,
write_strategy: RoutingStrategy::PrimaryOnly,
..Default::default()
});
drop(lb);
let lb2 = LoadBalancer::new(LbCfg {
read_write_split: false,
read_strategy: RoutingStrategy::LatencyBased,
write_strategy: RoutingStrategy::PrimaryOnly,
..Default::default()
});
drop(lb2);
}
#[test]
fn test_module_03_health_checker_config() {
use heliosdb_proxy::config::HealthConfig;
use heliosdb_proxy::health_checker::{HealthChecker, HealthConfig as HcCfg};
let cfg = HealthConfig {
check_interval_secs: 10,
check_timeout_secs: 2,
failure_threshold: 5,
success_threshold: 3,
check_query: "SELECT pg_is_in_recovery()".to_string(),
};
assert_eq!(cfg.failure_threshold, 5);
assert_eq!(cfg.success_threshold, 3);
assert_eq!(cfg.check_query, "SELECT pg_is_in_recovery()");
assert_eq!(cfg.check_interval(), std::time::Duration::from_secs(10));
assert_eq!(cfg.check_timeout(), std::time::Duration::from_secs(2));
let _hc = HealthChecker::new(HcCfg {
detailed_checks: true,
check_query: "SELECT 1".to_string(),
..Default::default()
});
}
#[test]
fn test_module_04_request_pipeline_config() {
use heliosdb_proxy::pipeline::{PipelineConfig, RequestPipeline};
let cfg = PipelineConfig {
max_depth: 32,
enabled: true,
..Default::default()
};
assert!(cfg.enabled);
assert_eq!(cfg.max_depth, 32);
let pipeline = RequestPipeline::new(cfg);
assert_eq!(pipeline.depth(42), 0);
}
#[test]
fn test_module_05_batch_operations_config() {
use heliosdb_proxy::batch::{BatchConfig, InsertBatcher};
let cfg = BatchConfig {
max_batch_size: 50,
..Default::default()
};
let batcher = std::sync::Arc::new(InsertBatcher::new(cfg));
batcher
.add(
"events".to_string(),
vec!["id".to_string(), "name".to_string()],
vec![vec!["1".to_string(), "click".to_string()]],
"INSERT INTO events (id, name) VALUES (1, 'click')".to_string(),
)
.expect("add to batcher");
let stats = batcher.stats();
assert_eq!(stats.inserts_received, 1);
assert_eq!(stats.rows_received, 1);
}
#[tokio::test]
async fn test_module_06_failover_controller_config() {
use heliosdb_proxy::failover_controller::{
FailoverCandidate, FailoverConfig, FailoverController, FailoverState,
};
use heliosdb_proxy::{NodeEndpoint, NodeId};
let cfg = FailoverConfig {
auto_failover: true,
prefer_sync_standby: false,
detection_time: std::time::Duration::from_millis(10),
failover_timeout: std::time::Duration::from_secs(5),
max_lag_bytes: 16 * 1024 * 1024,
retry_failed: false,
max_retries: 0,
};
let controller = FailoverController::new(cfg);
let primary_id = NodeId::new();
controller.set_primary(primary_id).await;
assert_eq!(controller.get_primary().await, Some(primary_id));
assert!(matches!(controller.state().await, FailoverState::Normal));
let standby_id = NodeId::new();
controller
.register_candidate(FailoverCandidate {
node_id: standby_id,
endpoint: NodeEndpoint::new("127.0.0.1", 5434),
is_sync: false,
lag_bytes: 0,
priority: 100,
last_heartbeat: None,
})
.await;
controller
.on_primary_failed(primary_id)
.await
.expect("on_primary_failed");
assert_eq!(
controller.get_primary().await,
Some(standby_id),
"standby promoted to primary"
);
assert!(matches!(controller.state().await, FailoverState::Completed));
assert_eq!(controller.failover_count(), 1);
let history = controller.history().await;
assert_eq!(history.len(), 1);
assert_eq!(history[0].old_primary, primary_id);
assert_eq!(history[0].new_primary, Some(standby_id));
assert!(history[0].success);
assert!(history[0].ended_at.is_some());
controller.on_old_primary_recovered(primary_id).await;
if let Some(fx) = fixture::start_proxy_ha().await {
let (client, conn) = tokio_postgres::connect(
&format!(
"host=127.0.0.1 port={} user={} password={} dbname={}",
fx.proxy_port, fx.primary.user, fx.primary.password, fx.primary.dbname
),
tokio_postgres::NoTls,
)
.await
.expect("connect through HA proxy");
tokio::spawn(conn);
let rows = client
.query("SELECT 1 AS n", &[])
.await
.expect("query through HA proxy");
assert_eq!(rows[0].get::<_, i32>("n"), 1);
}
}
#[cfg(feature = "ha-tr")]
#[tokio::test]
async fn test_module_07_transaction_replay_config() {
use heliosdb_proxy::transaction_journal::{JournalValue, StatementType, TransactionJournal};
use heliosdb_proxy::NodeId;
let journal = TransactionJournal::new();
let tx_id = uuid::Uuid::new_v4();
let session_id = uuid::Uuid::new_v4();
let node = NodeId::new();
journal
.begin_transaction(tx_id, session_id, node, 0)
.await
.expect("begin_transaction");
journal
.log_statement(
tx_id,
"INSERT INTO t VALUES ($1)".to_string(),
vec![JournalValue::Int64(1)],
None,
None,
1,
)
.await
.expect("log_statement");
let j = journal.get_journal(&tx_id).await.expect("get_journal");
assert_eq!(j.entries.len(), 1);
assert!(j.has_mutations);
assert_eq!(j.entries[0].statement_type, StatementType::Insert);
journal.commit_transaction(tx_id).await.expect("commit");
assert!(journal.get_journal(&tx_id).await.is_none());
}
#[cfg(not(feature = "ha-tr"))]
#[test]
fn test_module_07_transaction_replay_config() {
let cfg = heliosdb_proxy::config::ProxyConfig::default();
let _ = cfg.tr_enabled;
}
#[cfg(feature = "ha-tr")]
#[tokio::test]
async fn test_module_08_session_migration_config() {
use heliosdb_proxy::session_migrate::{PreparedStatementInfo, SessionMigrate, SessionState};
use heliosdb_proxy::NodeId;
let mut migrate = SessionMigrate::new().with_max_sessions(100);
migrate.set_enabled(true);
let session_id = uuid::Uuid::new_v4();
let primary_id = NodeId::new();
let standby_id = NodeId::new();
let mut state = SessionState::new(
session_id,
"helios".into(),
"helios_test".into(),
primary_id,
);
state.set_parameter("search_path".into(), "public,ext".into());
state.set_parameter("timezone".into(), "UTC".into());
state.add_prepared_statement(PreparedStatementInfo {
name: "get_user".into(),
query: "SELECT id, name FROM users WHERE id = $1".into(),
param_types: vec!["int4".into()],
created_at: chrono::Utc::now(),
});
migrate
.register_session(state)
.await
.expect("register_session");
let s = migrate.get_session(&session_id).await.expect("get_session");
assert_eq!(s.user, "helios");
let sp = s.get_parameter("search_path").expect("search_path param");
assert!(
sp.contains("public") && sp.contains("ext"),
"search_path must contain both schemas: {sp:?}"
);
assert_eq!(s.prepared_statements.len(), 1);
let stmts = s.generate_restore_statements();
assert!(
stmts.iter().any(|s| s.starts_with("SET ")),
"restore stmts must include SET commands: {stmts:?}"
);
assert!(
stmts.iter().any(|s| s.starts_with("PREPARE ")),
"restore stmts must include PREPARE commands: {stmts:?}"
);
let result = migrate
.migrate_session(session_id, standby_id)
.await
.expect("migrate_session");
assert!(result.success, "migration must succeed: {:?}", result.error);
assert_eq!(result.target_node, standby_id);
let stats = migrate.stats().await;
assert!(stats.enabled);
if let Some(fx) = fixture::start_proxy_ha().await {
let (client, conn) = tokio_postgres::connect(
&format!(
"host=127.0.0.1 port={} user={} password={} dbname={}",
fx.proxy_port, fx.primary.user, fx.primary.password, fx.primary.dbname
),
tokio_postgres::NoTls,
)
.await
.expect("connect through HA proxy");
tokio::spawn(conn);
client
.execute("SET application_name = 'ha-migration-test'", &[])
.await
.expect("SET application_name");
let rows = client
.query("SHOW application_name", &[])
.await
.expect("SHOW application_name");
assert_eq!(rows[0].get::<_, &str>(0), "ha-migration-test");
}
}
#[cfg(not(feature = "ha-tr"))]
#[test]
fn test_module_08_session_migration_config() {
let cfg = heliosdb_proxy::config::ProxyConfig::default();
let _ = cfg.tr_enabled;
}
#[cfg(feature = "ha-tr")]
#[tokio::test]
async fn test_module_09_cursor_restore_config() {
use heliosdb_proxy::cursor_restore::{CursorDirection, CursorRestore, CursorState};
use heliosdb_proxy::NodeId;
let mut restore = CursorRestore::new().with_max_cursors(100);
restore.set_enabled(true);
let session_id = uuid::Uuid::new_v4();
let standby_id = NodeId::new();
let cursor = CursorState {
name: "cur_users".into(),
session_id,
query: "SELECT id, name FROM users ORDER BY id".into(),
parameters: vec![],
total_rows: Some(500),
position: 0,
scrollable: false,
with_hold: true,
direction: CursorDirection::Forward,
fetch_size: 50,
created_at: chrono::Utc::now(),
last_fetch: None,
closed: false,
};
restore.save_cursor(cursor).await.expect("save_cursor");
restore
.update_position("cur_users", 50)
.await
.expect("update_position");
let got = restore.get_cursor("cur_users").await.expect("get_cursor");
assert_eq!(got.position, 50);
assert_eq!(got.name, "cur_users");
assert_eq!(got.query, "SELECT id, name FROM users ORDER BY id");
assert!(got.with_hold);
let session_cursors = restore.get_session_cursors(&session_id).await;
assert_eq!(session_cursors.len(), 1);
let result = restore
.restore_cursor("cur_users", standby_id)
.await
.expect("restore_cursor");
assert!(result.success, "restore must succeed: {:?}", result.error);
assert_eq!(result.name, "cur_users");
let stats = restore.stats().await;
assert!(stats.enabled);
assert_eq!(stats.active_cursors, 1);
restore
.close_cursor("cur_users")
.await
.expect("close_cursor");
let stats2 = restore.stats().await;
assert_eq!(stats2.active_cursors, 0);
}
#[cfg(not(feature = "ha-tr"))]
#[test]
fn test_module_09_cursor_restore_config() {
let cfg = heliosdb_proxy::config::ProxyConfig::default();
let _ = cfg.tr_enabled;
}
#[tokio::test]
async fn test_module_10_switchover_buffer_config() {
use heliosdb_proxy::switchover_buffer::{BufferConfig, BufferState, SwitchoverBuffer};
let cfg = BufferConfig {
buffer_timeout: std::time::Duration::from_secs(30),
max_buffered_queries: 1000,
max_buffer_memory: 64 * 1024 * 1024,
allow_queries_during_drain: false,
};
let buf = SwitchoverBuffer::new(cfg);
assert_eq!(buf.state(), BufferState::Passthrough);
assert!(!buf.is_buffering());
assert!(buf.is_empty());
buf.start_buffering();
assert!(buf.is_buffering());
assert_eq!(buf.state(), BufferState::Buffering);
let _rx1 = buf
.buffer_query("SELECT 1".into(), vec![], 1)
.expect("buffer query 1");
let _rx2 = buf
.buffer_query("SELECT 2".into(), vec![], 2)
.expect("buffer query 2");
let _rx3 = buf
.buffer_query("INSERT INTO t VALUES (42)".into(), vec![], 3)
.expect("buffer query 3");
assert_eq!(buf.len(), 3);
let snap = buf.stats();
assert_eq!(snap.buffered_queries, 3);
assert_eq!(snap.replayed_queries, 0);
buf.stop_buffering();
assert_eq!(buf.state(), BufferState::Draining);
buf.drain(|_sql, _params| async { Ok(()) }).await;
assert_eq!(buf.state(), BufferState::Passthrough);
assert!(buf.is_empty());
let final_stats = buf.stats();
assert_eq!(final_stats.replayed_queries, 3);
assert_eq!(final_stats.failed_replays, 0);
assert_eq!(final_stats.timed_out_queries, 0);
buf.start_buffering();
let _rx4 = buf
.buffer_query("SELECT 99".into(), vec![], 4)
.expect("buffer query 4");
buf.fail_all("switchover aborted");
assert!(buf.is_empty());
}
#[test]
fn test_module_11_primary_tracker_config() {
use heliosdb_proxy::primary_tracker::PrimaryTracker;
let tracker = PrimaryTracker::new_standalone();
assert!(!tracker.has_primary());
let node_id = uuid::Uuid::new_v4();
tracker.set_primary(node_id, "pg-primary.local:5432".to_string());
tracker.confirm_primary();
assert!(tracker.has_primary());
assert_eq!(
tracker.get_primary_address(),
Some("pg-primary.local:5432".to_string())
);
tracker.clear_primary();
assert!(!tracker.has_primary());
}
#[cfg(feature = "ha-tr")]
#[tokio::test]
async fn test_module_12_transaction_journal_roundtrip() {
use heliosdb_proxy::transaction_journal::{JournalValue, TransactionJournal};
use heliosdb_proxy::NodeId;
let journal = TransactionJournal::new();
let tx1 = uuid::Uuid::new_v4();
let tx2 = uuid::Uuid::new_v4();
let session = uuid::Uuid::new_v4();
let node = NodeId::new();
journal
.begin_transaction(tx1, session, node, 0)
.await
.unwrap();
journal
.begin_transaction(tx2, session, node, 0)
.await
.unwrap();
journal
.log_statement(
tx1,
"UPDATE accounts SET balance = $1 WHERE id = $2".to_string(),
vec![JournalValue::Float64(99.0), JournalValue::Int64(7)],
Some(1),
Some(1),
1,
)
.await
.unwrap();
journal
.log_statement(
tx2,
"DELETE FROM sessions WHERE token = $1".to_string(),
vec![JournalValue::Text("tok-abc".to_string())],
Some(2),
Some(1),
1,
)
.await
.unwrap();
let j1 = journal.get_journal(&tx1).await.unwrap();
let j2 = journal.get_journal(&tx2).await.unwrap();
assert!(j1.has_mutations);
assert!(j2.has_mutations);
journal.rollback_transaction(tx1).await.unwrap();
journal.commit_transaction(tx2).await.unwrap();
assert!(journal.get_journal(&tx1).await.is_none());
assert!(journal.get_journal(&tx2).await.is_none());
}
#[cfg(not(feature = "ha-tr"))]
#[test]
fn test_module_12_transaction_journal_roundtrip() {
}
#[cfg(feature = "query-cache")]
#[tokio::test]
async fn test_module_13_query_cache_roundtrip() {
use heliosdb_proxy::cache::{CacheConfig, QueryCache};
let _cache = QueryCache::new(CacheConfig::default());
let Some(fx) = fixture::start_proxy().await else {
return;
};
let conn_str = format!(
"host=127.0.0.1 port={} user={} password={} dbname={}",
fx.proxy_port, fx.backend.user, fx.backend.password, fx.backend.dbname
);
let (client, connection) = tokio_postgres::connect(&conn_str, tokio_postgres::NoTls)
.await
.expect("connect through proxy");
tokio::spawn(connection);
let rows = client
.query("SELECT 1 + 1 AS result", &[])
.await
.expect("query 1");
assert_eq!(rows[0].get::<_, i32>("result"), 2);
let rows2 = client
.query("SELECT 1 + 1 AS result", &[])
.await
.expect("query 2");
assert_eq!(rows2[0].get::<_, i32>("result"), 2);
}
#[cfg(not(feature = "query-cache"))]
#[test]
fn test_module_13_query_cache_roundtrip() {
}
#[cfg(feature = "routing-hints")]
#[tokio::test]
async fn test_module_14_routing_hints_passthrough() {
use heliosdb_proxy::routing::HintParser;
let parser = HintParser::new();
let hints = parser.parse("/* route=primary */ SELECT 1");
let _stripped = parser.strip("/* route=primary */ SELECT 1");
let _ = hints;
let Some(fx) = fixture::start_proxy().await else {
return;
};
let conn_str = format!(
"host=127.0.0.1 port={} user={} password={} dbname={}",
fx.proxy_port, fx.backend.user, fx.backend.password, fx.backend.dbname
);
let (client, connection) = tokio_postgres::connect(&conn_str, tokio_postgres::NoTls)
.await
.expect("connect for routing-hints test");
tokio::spawn(connection);
let rows = client
.query("/* route=primary */ SELECT 2 AS n", &[])
.await
.expect("hinted query");
assert_eq!(rows[0].get::<_, i32>("n"), 2);
}
#[cfg(not(feature = "routing-hints"))]
#[test]
fn test_module_14_routing_hints_passthrough() {
}
#[cfg(feature = "lag-routing")]
#[tokio::test]
async fn test_module_15_lag_routing_fallback() {
use heliosdb_proxy::lag::LagRoutingConfig;
let _cfg = LagRoutingConfig::new();
let Some(fx) = fixture::start_proxy().await else {
return;
};
let conn_str = format!(
"host=127.0.0.1 port={} user={} password={} dbname={}",
fx.proxy_port, fx.backend.user, fx.backend.password, fx.backend.dbname
);
let (client, connection) = tokio_postgres::connect(&conn_str, tokio_postgres::NoTls)
.await
.expect("connect for lag-routing test");
tokio::spawn(connection);
let rows = client.query("SELECT 3 AS n", &[]).await.expect("query");
assert_eq!(rows[0].get::<_, i32>("n"), 3);
}
#[cfg(not(feature = "lag-routing"))]
#[test]
fn test_module_15_lag_routing_fallback() {
}
#[cfg(feature = "query-rewriting")]
#[test]
fn test_module_16_query_rewriter_transform() {
use heliosdb_proxy::rewriter::{QueryRewriter, RewriterConfig};
let rewriter = QueryRewriter::new(RewriterConfig::default());
let result = rewriter.rewrite("SELECT 1");
assert!(result.is_ok() || result.is_err()); }
#[cfg(not(feature = "query-rewriting"))]
#[test]
fn test_module_16_query_rewriter_transform() {
}
#[cfg(feature = "query-analytics")]
#[test]
fn test_module_17_query_analytics_config() {
use heliosdb_proxy::analytics::{AnalyticsConfig, QueryAnalytics};
let cfg = AnalyticsConfig {
enabled: true,
..Default::default()
};
assert!(cfg.enabled);
let _analytics = QueryAnalytics::new(cfg);
}
#[cfg(not(feature = "query-analytics"))]
#[test]
fn test_module_17_query_analytics_config() {
}
#[cfg(feature = "schema-routing")]
#[test]
fn test_module_18_schema_routing_config() {
use heliosdb_proxy::schema_routing::SchemaRoutingConfig;
let cfg = SchemaRoutingConfig::builder().build();
assert!(!cfg.auto_discover || cfg.auto_discover);
}
#[cfg(not(feature = "schema-routing"))]
#[test]
fn test_module_18_schema_routing_config() {
}
#[cfg(feature = "auth-proxy")]
#[test]
fn test_module_19_auth_proxy_config() {
use heliosdb_proxy::auth::{AuthConfig, AuthProxyBuilder};
let cfg = AuthConfig::default();
let _builder = AuthProxyBuilder::new();
let _ = cfg;
}
#[cfg(not(feature = "auth-proxy"))]
#[test]
fn test_module_19_auth_proxy_config() {
use heliosdb_proxy::config::AuthConfig;
let _cfg = AuthConfig::default();
}
#[cfg(feature = "rate-limiting")]
#[test]
fn test_module_20_rate_limiter_config() {
use heliosdb_proxy::rate_limit::{RateLimitConfig, RateLimiter};
let cfg = RateLimitConfig {
default_qps: 1000,
default_burst: 200,
enabled: true,
..Default::default()
};
assert!(cfg.enabled);
let _limiter = RateLimiter::new(cfg);
}
#[cfg(not(feature = "rate-limiting"))]
#[test]
fn test_module_20_rate_limiter_config() {
let config = heliosdb_proxy::config::ProxyConfig::default();
assert!(config.nodes.is_empty());
}
#[cfg(feature = "circuit-breaker")]
#[test]
fn test_module_21_circuit_breaker_config() {
use heliosdb_proxy::circuit_breaker::{CircuitBreaker, CircuitBreakerConfig};
let cfg = CircuitBreakerConfig::builder()
.failure_threshold(5)
.cooldown_secs(30)
.build();
let _cb = CircuitBreaker::new("test-node", cfg);
}
#[cfg(not(feature = "circuit-breaker"))]
#[test]
fn test_module_21_circuit_breaker_config() {
}
#[cfg(feature = "multi-tenancy")]
#[test]
fn test_module_22_multi_tenancy_config() {
use heliosdb_proxy::multi_tenancy::TenantManager;
let mgr = TenantManager::new();
assert_eq!(mgr.tenant_count(), 0);
}
#[cfg(not(feature = "multi-tenancy"))]
#[test]
fn test_module_22_multi_tenancy_config() {
}
#[cfg(feature = "wasm-plugins")]
#[test]
fn test_module_23_wasm_plugin_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
plugin_dir: "/tmp/helios-plugins-test".to_string(),
hot_reload: false,
memory_limit_mb: 32,
timeout_ms: 50,
max_plugins: 5,
fuel_metering: true,
fuel_limit: 500_000,
trust_root: None,
};
assert!(cfg.enabled);
assert_eq!(cfg.max_plugins, 5);
assert_eq!(cfg.memory_limit_mb, 32);
}
#[cfg(not(feature = "wasm-plugins"))]
#[test]
fn test_module_23_wasm_plugin_config() {
let cfg = heliosdb_proxy::config::ProxyConfig::default();
assert!(!cfg.plugins.enabled);
}
#[cfg(feature = "graphql-gateway")]
#[test]
fn test_module_24_graphql_gateway_config() {
use heliosdb_proxy::graphql::{GraphQLConfig, SchemaIntrospector};
let cfg = GraphQLConfig::default();
let _ = cfg;
let _introspector = SchemaIntrospector::new();
}
#[cfg(not(feature = "graphql-gateway"))]
#[test]
fn test_module_24_graphql_gateway_config() {
}
#[cfg(feature = "anomaly-detection")]
#[test]
fn test_module_25_anomaly_detection_config() {
use heliosdb_proxy::anomaly::{AnomalyConfig, AnomalyDetector};
let cfg = AnomalyConfig {
rate_window_secs: 30,
spike_z_threshold: 3.0,
event_buffer_size: 512,
emit_novel_queries: true,
..Default::default()
};
assert_eq!(cfg.event_buffer_size, 512);
let _detector = AnomalyDetector::new(cfg);
}
#[cfg(not(feature = "anomaly-detection"))]
#[test]
fn test_module_25_anomaly_detection_config() {
}
#[cfg(feature = "edge-proxy")]
#[test]
fn test_module_26_edge_mode_config() {
use heliosdb_proxy::edge::{EdgeCache, EdgeConfig};
let cfg = EdgeConfig::default();
let _ = cfg;
let _cache = EdgeCache::new(1024);
}
#[cfg(not(feature = "edge-proxy"))]
#[test]
fn test_module_26_edge_mode_config() {
}
#[cfg(feature = "wasm-plugins")]
#[test]
fn test_module_27_plugin_kv_isolation() {
use heliosdb_proxy::plugins::HostFunctionRegistry;
let registry = HostFunctionRegistry::new();
let _ = registry;
}
#[cfg(not(feature = "wasm-plugins"))]
#[test]
fn test_module_27_plugin_kv_isolation() {
}
#[cfg(feature = "wasm-plugins")]
#[test]
fn test_module_28_plugin_crypto_sha256() {
use heliosdb_proxy::plugins::HostFunctionRegistry;
let registry = HostFunctionRegistry::new();
let _ = registry;
}
#[cfg(not(feature = "wasm-plugins"))]
#[test]
fn test_module_28_plugin_crypto_sha256() {
}
#[test]
fn test_module_29_plugin_signatures_trust_root() {
use heliosdb_proxy::config::PluginToml;
let cfg_off = PluginToml {
trust_root: None,
..Default::default()
};
assert!(cfg_off.trust_root.is_none());
let cfg_on = PluginToml {
trust_root: Some("/etc/heliosproxy/trust".to_string()),
..Default::default()
};
assert!(cfg_on.trust_root.is_some());
}
#[cfg(feature = "wasm-plugins")]
#[test]
fn test_module_30_oci_artefact_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
plugin_dir: "/tmp/oci-plugins".to_string(),
trust_root: None,
..Default::default()
};
assert!(cfg.enabled);
assert!(!cfg.plugin_dir.is_empty());
}
#[cfg(not(feature = "wasm-plugins"))]
#[test]
fn test_module_30_oci_artefact_config() {
}
#[cfg(feature = "wasm-plugins")]
#[test]
fn test_module_31_plugin_route_block_config() {
use heliosdb_proxy::plugins::RouteResult;
let result = RouteResult::Block("denied by plugin".to_string());
assert!(matches!(result, RouteResult::Block(_)));
}
#[cfg(not(feature = "wasm-plugins"))]
#[test]
fn test_module_31_plugin_route_block_config() {
}
#[test]
fn test_module_32_plugin_trust_root_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
trust_root: Some("/keys/helios".to_string()),
..Default::default()
};
assert_eq!(cfg.trust_root.as_deref(), Some("/keys/helios"));
}
#[tokio::test]
async fn test_module_33_admin_ui_endpoint() {
let Some(fx) = fixture::start_proxy().await else {
return;
};
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
let addr = format!("127.0.0.1:{}", fx.admin_port);
match tokio::net::TcpStream::connect(&addr).await {
Ok(_stream) => {
}
Err(e) => {
eprintln!("[test_33] admin connect to {addr}: {e} (non-fatal)");
}
}
}
#[tokio::test]
async fn test_module_34_admin_rest_v2_endpoints() {
let Some(fx) = fixture::start_proxy().await else {
return;
};
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
let addr = format!("127.0.0.1:{}", fx.admin_port);
if let Ok(mut stream) = tokio::net::TcpStream::connect(&addr).await {
use tokio::io::{AsyncReadExt, AsyncWriteExt};
let req = format!("GET /health HTTP/1.1\r\nHost: {addr}\r\nConnection: close\r\n\r\n");
let _ = stream.write_all(req.as_bytes()).await;
let mut buf = vec![0u8; 512];
let n = stream.read(&mut buf).await.unwrap_or(0);
let response = String::from_utf8_lossy(&buf[..n]);
assert!(
response.starts_with("HTTP/") || n == 0,
"expected HTTP response, got: {response}"
);
}
let conn_str = format!(
"host=127.0.0.1 port={} user={} password={} dbname={}",
fx.proxy_port, fx.backend.user, fx.backend.password, fx.backend.dbname
);
if let Ok((client, conn)) = tokio_postgres::connect(&conn_str, tokio_postgres::NoTls).await {
tokio::spawn(conn);
let rows = client.query("SELECT 1 AS n", &[]).await.expect("query");
assert_eq!(rows[0].get::<_, i32>("n"), 1);
}
}
#[test]
fn test_module_35_plugin_cost_governor_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
plugin_dir: "/etc/heliosproxy/plugins".to_string(),
..Default::default()
};
assert!(cfg.enabled);
assert!(!cfg.plugin_dir.is_empty());
}
#[test]
fn test_module_36_plugin_ai_classifier_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
timeout_ms: 50,
..Default::default()
};
assert!(cfg.timeout_ms <= 100);
}
#[test]
fn test_module_37_plugin_token_budget_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
fuel_metering: true,
fuel_limit: 200_000,
..Default::default()
};
assert!(cfg.fuel_metering);
assert_eq!(cfg.fuel_limit, 200_000);
}
#[test]
fn test_module_38_plugin_llm_guardrail_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
max_plugins: 10,
..Default::default()
};
assert!(cfg.max_plugins >= 1);
}
#[test]
fn test_module_39_plugin_pgvector_router_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
..Default::default()
};
assert!(cfg.enabled);
}
#[test]
fn test_module_40_plugin_column_mask_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
memory_limit_mb: 16,
..Default::default()
};
assert_eq!(cfg.memory_limit_mb, 16);
}
#[test]
fn test_module_41_plugin_audit_chain_config() {
use heliosdb_proxy::config::PluginToml;
let cfg = PluginToml {
enabled: true,
hot_reload: false,
..Default::default()
};
assert!(!cfg.hot_reload);
}
#[test]
fn test_module_42_plugin_residency_router_config() {
use heliosdb_proxy::config::{PluginToml, ProxyConfig};
let cfg = ProxyConfig {
plugins: PluginToml {
enabled: true,
trust_root: Some("/keys".to_string()),
..Default::default()
},
..Default::default()
};
assert!(cfg.plugins.enabled);
assert!(cfg.plugins.trust_root.is_some());
}
#[test]
fn test_module_43_helios_plugin_cli_binary_exists() {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let candidates = ["target/debug/helios-plugin", "target/release/helios-plugin"];
let found = candidates
.iter()
.any(|p| std::path::Path::new(manifest_dir).join(p).exists());
if !found {
eprintln!("[test_43] helios-plugin binary not found in target/ — run `cargo build` first");
}
}
#[test]
#[ignore = "requires Kubernetes API server — not present in standard CI"]
fn test_module_44_k8s_operator_skipped() {}
#[test]
#[ignore = "requires Terraform binary — not present in standard CI"]
fn test_module_45_terraform_provider_skipped() {}
#[test]
#[ignore = "requires Pulumi SDK — not present in standard CI"]
fn test_module_46_pulumi_provider_skipped() {}