use secure_data::config::SecretReference;
use secure_data::error::DataError;
use secure_data::resolve::resolve_secret;
#[tokio::test]
async fn test_resolve_env_happy_path() {
std::env::set_var("TEST_SECRET_M13", "my-secret");
let reference =
SecretReference::parse("env://TEST_SECRET_M13").expect("parsing env:// must succeed");
let result = resolve_secret(&reference).await;
let secret = result.expect("resolve_secret must succeed for valid env var");
assert_eq!(
secret.expose_secret(),
"my-secret",
"resolved value must match env var"
);
std::env::remove_var("TEST_SECRET_M13");
}
#[tokio::test]
async fn test_resolve_env_missing() {
std::env::remove_var("TEST_SECRET_M13_MISSING_XYZ");
let reference = SecretReference::parse("env://TEST_SECRET_M13_MISSING_XYZ")
.expect("parsing env:// must succeed");
let result = resolve_secret(&reference).await;
assert!(
matches!(result, Err(DataError::SecretNotFound { .. })),
"expected SecretNotFound, got: {result:?}"
);
}
#[tokio::test]
async fn test_resolve_kms_scheme_unsupported() {
let reference =
SecretReference::parse("kms://alias/my-key").expect("parsing kms:// must succeed");
let result = resolve_secret(&reference).await;
assert!(
matches!(result, Err(DataError::InvalidSecretReference { .. })),
"expected InvalidSecretReference for kms:// scheme, got: {result:?}"
);
}
#[cfg(feature = "vault")]
#[tokio::test]
async fn test_resolve_vault_happy_path() {
use std::io::{Read, Write};
use std::net::TcpListener;
let field_value = "my-vault-secret";
let body = format!(r#"{{"data":{{"password":"{field_value}"}}}}"#);
let response = format!(
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
body.len(),
body
);
let listener = TcpListener::bind("127.0.0.1:0").expect("bind mock vault server");
let port = listener.local_addr().unwrap().port();
std::thread::spawn(move || {
if let Ok((mut stream, _)) = listener.accept() {
let mut buf = [0u8; 8192];
let _ = stream.read(&mut buf);
let _ = stream.write_all(response.as_bytes());
}
});
std::env::set_var("VAULT_ADDR", format!("http://127.0.0.1:{port}"));
std::env::set_var("VAULT_TOKEN", "test-token");
let reference = SecretReference::parse("vault://kv/db-credentials#password")
.expect("parsing vault:// must succeed");
let result = resolve_secret(&reference).await;
let secret = result.expect("resolve_secret must succeed for vault:// with mock");
assert_eq!(
secret.expose_secret(),
field_value,
"resolved value must match mock response"
);
std::env::remove_var("VAULT_ADDR");
std::env::remove_var("VAULT_TOKEN");
}
#[cfg(not(feature = "vault"))]
#[tokio::test]
async fn test_resolve_vault_feature_not_enabled() {
let reference = SecretReference::parse("vault://kv/db-credentials#password")
.expect("parsing vault:// must succeed");
let result = resolve_secret(&reference).await;
assert!(
matches!(result, Err(DataError::ProviderUnavailable { .. })),
"expected ProviderUnavailable when vault feature not enabled, got: {result:?}"
);
}