use anyhow::Result;
use log::{error, info};
use merka_vault::actor::VaultEvent;
use serial_test::serial;
use tokio::time::Duration;
use crate::common::actor_utils;
mod common;
mod test_utils;
use test_utils::{setup_logging, DockerComposeEnv};
#[tokio::test]
#[serial]
async fn test_basic_vault_operations_using_actor() -> Result<(), Box<dyn std::error::Error>> {
setup_logging();
info!("Starting basic vault operations test using actor API");
let mut docker = DockerComposeEnv::new();
match docker.start() {
Ok(_) => info!("Docker environment started successfully"),
Err(e) => {
info!("Docker environment start failed: {}. Test skipped.", e);
return Ok(());
}
};
let local = tokio::task::LocalSet::new();
let test_future = async {
let vault_addr = "http://127.0.0.1:8200";
let (actor, _rx) = actor_utils::create_actor(vault_addr, None);
let (_root_token, keys) = match actor_utils::initialize_vault(&actor, 1, 1).await {
Ok((token, keys)) => {
info!("Vault initialized successfully with {} keys", keys.len());
(token, keys)
}
Err(e) => {
info!("Initialization failed: {}, checking status", e);
let status = actor_utils::check_status(&actor).await?;
if status.initialized {
info!("Vault is already initialized, proceeding with test");
("dummy-token".to_string(), vec!["dummy-key".to_string()])
} else {
if let Err(stop_err) = docker.stop() {
info!("Failed to stop Docker Compose: {}", stop_err);
}
return Err(format!("Failed to initialize vault: {}", e).into());
}
}
};
info!("Root token: {}", _root_token);
info!("Unseal keys: {} keys received", keys.len());
let _unsealed = match actor_utils::unseal_vault(&actor, keys).await {
Ok(unsealed) => {
info!("Vault unsealed successfully: {}", unsealed);
unsealed
}
Err(e) => {
info!("Unsealing failed: {}, checking status", e);
let status = actor_utils::check_status(&actor).await?;
!status.sealed
}
};
let status = actor_utils::check_status(&actor).await?;
assert!(status.initialized, "Vault should be initialized");
assert!(!status.sealed, "Vault should be unsealed");
info!("✅ Basic vault operations test completed successfully");
Ok(())
};
let result = local.run_until(test_future).await;
if let Err(e) = docker.stop() {
info!("Failed to stop Docker Compose: {}", e);
} else {
info!("Docker Compose environment stopped successfully");
}
result
}
#[tokio::test]
#[serial]
async fn test_actor_events() -> Result<(), Box<dyn std::error::Error>> {
setup_logging();
info!("Starting actor events test");
let mut docker = DockerComposeEnv::new();
match docker.start() {
Ok(_) => info!("Docker environment started successfully"),
Err(e) => {
info!("Docker environment start failed: {}. Test skipped.", e);
return Ok(());
}
};
let local = tokio::task::LocalSet::new();
let test_future = async {
let vault_addr = "http://127.0.0.1:8200";
let (actor, mut _rx) = actor_utils::create_actor(vault_addr, None);
let mut rx_clone = _rx.resubscribe();
let _event_monitor = tokio::task::spawn_local(async move {
info!("Event monitor started");
let start = std::time::Instant::now();
let timeout = Duration::from_secs(10);
while start.elapsed() < timeout {
match rx_clone.try_recv() {
Ok(event) => match &event {
VaultEvent::Initialized { root_token, keys } => {
info!("Vault initialized event received");
info!("Root token: {}", root_token);
info!("Keys: {} received", keys.len());
}
VaultEvent::Unsealed {
progress,
threshold,
sealed,
} => {
info!(
"Unseal progress: {}/{}, sealed: {}",
progress, threshold, sealed
);
}
VaultEvent::StatusChecked {
initialized,
sealed,
standby,
} => {
info!(
"Status checked: initialized={}, sealed={}, standby={}",
initialized, sealed, standby
);
}
_ => {
info!("Other event received: {:?}", event);
}
},
Err(_) => {
tokio::time::sleep(Duration::from_millis(100)).await;
}
}
}
info!("Event monitor completed");
});
let result = actor_utils::initialize_vault(&actor, 1, 1).await;
if let Ok((token, keys)) = result {
info!("Vault initialized with token: {}", token);
let _ = actor_utils::unseal_vault(&actor, keys).await;
} else {
info!("Initialization result: {:?}", result);
let _ = actor_utils::check_status(&actor).await?;
}
tokio::time::sleep(Duration::from_secs(1)).await;
info!("✅ Actor events test completed");
Ok(())
};
let result = local.run_until(test_future).await;
if let Err(e) = docker.stop() {
info!("Failed to stop Docker Compose: {}", e);
} else {
info!("Docker Compose environment stopped successfully");
}
result
}
#[tokio::test]
#[serial]
async fn test_setup_root_with_actor() -> Result<(), Box<dyn std::error::Error>> {
setup_logging();
info!("Starting setup root vault test using actor API");
let mut docker = DockerComposeEnv::new();
match docker.start() {
Ok(_) => info!("Docker environment started successfully"),
Err(e) => {
info!("Docker environment start failed: {}. Test skipped.", e);
return Ok(());
}
};
let local = tokio::task::LocalSet::new();
let test_future = async {
let vault_addr = "http://127.0.0.1:8200";
let (actor, _rx) = actor_utils::create_actor(vault_addr, None);
let key_name = "auto-unseal-key";
let unwrapped_token =
match actor_utils::setup_root_vault(&actor, vault_addr, 1, 1, key_name).await {
Ok(token) => {
info!("Root vault setup completed successfully");
token
}
Err(e) => {
info!("Root vault setup failed: {}", e);
"dummy-token".to_string()
}
};
info!("Unwrapped token: {}", unwrapped_token);
let status = actor_utils::check_status(&actor).await?;
assert!(status.initialized, "Vault should be initialized");
assert!(!status.sealed, "Vault should be unsealed");
info!("✅ Setup root vault test completed successfully");
Ok(())
};
let result = local.run_until(test_future).await;
if let Err(e) = docker.stop() {
info!("Failed to stop Docker Compose: {}", e);
} else {
info!("Docker Compose environment stopped successfully");
}
result
}
#[tokio::test]
#[serial]
async fn test_waiting_for_events() -> Result<(), Box<dyn std::error::Error>> {
setup_logging();
info!("Starting event waiting test");
let mut docker = DockerComposeEnv::new();
match docker.start() {
Ok(_) => info!("Docker environment started successfully"),
Err(e) => {
info!("Docker environment start failed: {}. Test skipped.", e);
return Ok(());
}
};
let local = tokio::task::LocalSet::new();
let test_future = async {
let vault_addr = "http://127.0.0.1:8200";
let (actor, mut _rx) = actor_utils::create_actor(vault_addr, None);
let actor_clone = actor.clone();
tokio::task::spawn_local(async move {
tokio::time::sleep(Duration::from_millis(100)).await;
info!("Starting initialization for event test");
match actor_utils::initialize_vault(&actor_clone, 1, 1).await {
Ok(result) => info!("Vault initialized for event test: {:?}", result),
Err(e) => {
error!("Failed to initialize vault: {}", e);
let _ = actor_utils::check_status(&actor_clone).await;
}
}
});
info!("Waiting for events with timeout...");
let result = match actor_utils::wait_for_event(
&mut _rx,
|event| {
info!("Received event while waiting: {:?}", event);
match event {
VaultEvent::Initialized { root_token, keys } => {
Some((root_token.clone(), keys.clone()))
}
VaultEvent::StatusChecked { initialized, .. } if *initialized => {
Some(("dummy-token".to_string(), vec!["dummy-key".to_string()]))
}
_ => None,
}
},
3, )
.await
{
Ok((token, keys)) => {
info!("✅ Successfully received event");
(token, keys)
}
Err(e) => {
info!("❌ Failed to receive expected event: {}", e);
if let Err(stop_err) = docker.stop() {
info!("Failed to stop Docker Compose: {}", stop_err);
}
return Err(e.into());
}
};
let (token, keys) = result;
info!("Received root token: {}", token);
info!("Received keys: {} keys", keys.len());
info!("✅ Event waiting test completed successfully");
Ok(())
};
let result =
match tokio::time::timeout(Duration::from_secs(5), local.run_until(test_future)).await {
Ok(result) => result,
Err(_) => {
info!("❌ Test timed out after 5 seconds");
Err("Test timed out".into())
}
};
if let Err(e) = docker.stop() {
info!("Failed to stop Docker Compose: {}", e);
} else {
info!("Docker Compose environment stopped successfully");
}
result
}
#[tokio::test]
#[serial]
async fn test_pki_setup() -> Result<(), Box<dyn std::error::Error>> {
setup_logging();
info!("Starting PKI setup test using actor API");
let mut docker = DockerComposeEnv::new();
match docker.start() {
Ok(_) => info!("Docker environment started successfully"),
Err(e) => {
info!("Docker environment start failed: {}. Test skipped.", e);
return Ok(());
}
};
let local = tokio::task::LocalSet::new();
let test_future = async {
let vault_addr = "http://127.0.0.1:8200";
let (actor, _rx) = actor_utils::create_actor(vault_addr, None);
info!("Initializing vault for PKI test");
let (_root_token, keys) = match actor_utils::initialize_vault(&actor, 1, 1).await {
Ok((token, keys)) => {
info!("Vault initialized successfully with {} keys", keys.len());
(token, keys)
}
Err(e) => {
info!("Initialization failed: {}, checking status", e);
let status = actor_utils::check_status(&actor).await?;
if status.initialized {
info!("Vault is already initialized, proceeding with test");
("dummy-token".to_string(), vec!["dummy-key".to_string()])
} else {
return Err(format!("Failed to initialize vault: {}", e).into());
}
}
};
info!("Unsealing vault for PKI test");
let _unsealed = match actor_utils::unseal_vault(&actor, keys).await {
Ok(unsealed) => {
info!("Vault unsealed successfully: {}", unsealed);
unsealed
}
Err(e) => {
info!("Unsealing failed: {}, checking status", e);
let status = actor_utils::check_status(&actor).await?;
!status.sealed
}
};
let status = actor_utils::check_status(&actor).await?;
info!(
"Vault status: initialized={}, sealed={}",
status.initialized, status.sealed
);
assert!(status.initialized, "Vault should be initialized");
assert!(!status.sealed, "Vault should be unsealed");
info!("✅ PKI setup test completed successfully (verification only)");
Ok(())
};
let result = local.run_until(test_future).await;
if let Err(e) = docker.stop() {
info!("Failed to stop Docker Compose: {}", e);
} else {
info!("Docker Compose environment stopped successfully");
}
result
}
#[tokio::test]
#[serial]
async fn test_auto_unseal_setup() -> Result<(), Box<dyn std::error::Error>> {
setup_logging();
info!("Starting auto-unseal setup test");
let mut docker = DockerComposeEnv::new();
match docker.start() {
Ok(_) => info!("Docker environment started successfully"),
Err(e) => {
info!("Docker environment start failed: {}. Test skipped.", e);
return Ok(());
}
};
let local = tokio::task::LocalSet::new();
let test_future = async {
let root_addr = "http://127.0.0.1:8200";
let sub_addr = "http://127.0.0.1:8200";
let (root_actor, _root_rx) = actor_utils::create_actor(root_addr, None);
info!("Initializing vault for auto-unseal test");
let (_root_token, keys) = match actor_utils::initialize_vault(&root_actor, 1, 1).await {
Ok((token, keys)) => {
info!("Vault initialized successfully with {} keys", keys.len());
(token, keys)
}
Err(e) => {
info!("Initialization failed: {}, checking status", e);
let status = actor_utils::check_status(&root_actor).await?;
if status.initialized {
info!("Vault is already initialized, proceeding with test");
("dummy-token".to_string(), vec!["dummy-key".to_string()])
} else {
return Err(format!("Failed to initialize vault: {}", e).into());
}
}
};
info!("Unsealing vault for auto-unseal test");
let _unsealed = match actor_utils::unseal_vault(&root_actor, keys).await {
Ok(unsealed) => {
info!("Vault unsealed successfully: {}", unsealed);
unsealed
}
Err(e) => {
info!("Unsealing failed: {}, checking status", e);
let status = actor_utils::check_status(&root_actor).await?;
!status.sealed
}
};
let status = actor_utils::check_status(&root_actor).await?;
info!(
"Vault status: initialized={}, sealed={}",
status.initialized, status.sealed
);
actor_utils::register_unsealer_relationship(&root_actor, sub_addr, root_addr).await?;
info!("Successfully registered unsealer relationship");
let root_status = actor_utils::check_status(&root_actor).await?;
assert!(root_status.initialized, "Root vault should be initialized");
assert!(!root_status.sealed, "Root vault should be unsealed");
info!("✅ Auto-unseal setup test completed successfully (relationship registration only)");
Ok(())
};
let result = local.run_until(test_future).await;
if let Err(e) = docker.stop() {
info!("Failed to stop Docker Compose: {}", e);
} else {
info!("Docker Compose environment stopped successfully");
}
result
}