-
Notifications
You must be signed in to change notification settings - Fork 0
Move test code from src/ to tests/ directory #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,9 +9,9 @@ use super::secret_backend::{SecretBackend, SecretData}; | |||||
|
|
||||||
| /// AWS Secrets Manager client | ||||||
| pub struct AwsSecretsClient { | ||||||
| client: SecretsManagerClient, | ||||||
| pub client: SecretsManagerClient, | ||||||
| #[allow(dead_code)] // Kept for potential future use (logging, debugging) | ||||||
| region: String, | ||||||
| pub region: String, | ||||||
| } | ||||||
|
|
||||||
| impl AwsSecretsClient { | ||||||
|
|
@@ -36,7 +36,7 @@ impl AwsSecretsClient { | |||||
| } | ||||||
|
|
||||||
| /// Convert AWS tags to metadata HashMap | ||||||
| fn tags_to_metadata(&self, tags: &[Tag]) -> HashMap<String, String> { | ||||||
| pub fn tags_to_metadata(&self, tags: &[Tag]) -> HashMap<String, String> { | ||||||
| tags.iter() | ||||||
| .filter_map(|tag| { | ||||||
| tag.key() | ||||||
|
|
@@ -46,7 +46,7 @@ impl AwsSecretsClient { | |||||
| } | ||||||
|
|
||||||
| /// Convert metadata HashMap to AWS tags | ||||||
| fn metadata_to_tags(&self, metadata: &HashMap<String, String>) -> Vec<Tag> { | ||||||
| pub fn metadata_to_tags(&self, metadata: &HashMap<String, String>) -> Vec<Tag> { | ||||||
| metadata | ||||||
| .iter() | ||||||
| .map(|(k, v)| Tag::builder().key(k).value(v).build()) | ||||||
|
|
@@ -249,115 +249,18 @@ impl SecretBackend for AwsSecretsClient { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| #[cfg(test)] | ||||||
| mod tests { | ||||||
| use super::*; | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_tags_to_metadata() { | ||||||
| let client = AwsSecretsClient { | ||||||
| client: create_test_client(), | ||||||
| region: "us-east-1".to_string(), | ||||||
| }; | ||||||
|
|
||||||
| let tags = vec![ | ||||||
| Tag::builder().key("rotation_enabled").value("true").build(), | ||||||
| Tag::builder() | ||||||
| .key("last_rotated") | ||||||
| .value("2023-01-01T00:00:00Z") | ||||||
| .build(), | ||||||
| Tag::builder() | ||||||
| .key("target_username") | ||||||
| .value("testuser") | ||||||
| .build(), | ||||||
| ]; | ||||||
|
|
||||||
| let metadata = client.tags_to_metadata(&tags); | ||||||
| assert_eq!(metadata.get("rotation_enabled"), Some(&"true".to_string())); | ||||||
| assert_eq!( | ||||||
| metadata.get("last_rotated"), | ||||||
| Some(&"2023-01-01T00:00:00Z".to_string()) | ||||||
| ); | ||||||
| assert_eq!( | ||||||
| metadata.get("target_username"), | ||||||
| Some(&"testuser".to_string()) | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_tags_to_metadata_empty() { | ||||||
| let client = AwsSecretsClient { | ||||||
| client: create_test_client(), | ||||||
| region: "us-east-1".to_string(), | ||||||
| }; | ||||||
|
|
||||||
| let tags = vec![]; | ||||||
| let metadata = client.tags_to_metadata(&tags); | ||||||
| assert!(metadata.is_empty()); | ||||||
| } | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_metadata_to_tags() { | ||||||
| let client = AwsSecretsClient { | ||||||
| client: create_test_client(), | ||||||
| region: "us-east-1".to_string(), | ||||||
| }; | ||||||
|
|
||||||
| let mut metadata = HashMap::new(); | ||||||
| metadata.insert("rotation_enabled".to_string(), "true".to_string()); | ||||||
| metadata.insert( | ||||||
| "last_rotated".to_string(), | ||||||
| "2023-01-01T00:00:00Z".to_string(), | ||||||
| ); | ||||||
| metadata.insert("target_username".to_string(), "testuser".to_string()); | ||||||
|
|
||||||
| let tags = client.metadata_to_tags(&metadata); | ||||||
| assert_eq!(tags.len(), 3); | ||||||
|
|
||||||
| // Verify tag values | ||||||
| let tag_map: HashMap<String, String> = tags | ||||||
| .iter() | ||||||
| .filter_map(|tag| { | ||||||
| tag.key() | ||||||
| .and_then(|k| tag.value().map(|v| (k.to_string(), v.to_string()))) | ||||||
| }) | ||||||
| .collect(); | ||||||
|
|
||||||
| assert_eq!(tag_map.get("rotation_enabled"), Some(&"true".to_string())); | ||||||
| assert_eq!( | ||||||
| tag_map.get("last_rotated"), | ||||||
| Some(&"2023-01-01T00:00:00Z".to_string()) | ||||||
| ); | ||||||
| assert_eq!( | ||||||
| tag_map.get("target_username"), | ||||||
| Some(&"testuser".to_string()) | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| #[test] | ||||||
| fn test_metadata_to_tags_empty() { | ||||||
| let client = AwsSecretsClient { | ||||||
| client: create_test_client(), | ||||||
| region: "us-east-1".to_string(), | ||||||
| }; | ||||||
|
|
||||||
| let metadata = HashMap::new(); | ||||||
| let tags = client.metadata_to_tags(&metadata); | ||||||
| assert!(tags.is_empty()); | ||||||
| } | ||||||
|
|
||||||
| // Helper function to create a test client | ||||||
| // Note: This creates a real client but tests don't actually call AWS APIs | ||||||
| // In a real scenario, you'd use a mock client | ||||||
| fn create_test_client() -> SecretsManagerClient { | ||||||
| // Use tokio runtime for async initialization | ||||||
| let rt = tokio::runtime::Runtime::new().unwrap(); | ||||||
| let config = rt.block_on(async { | ||||||
| aws_config::defaults(aws_config::BehaviorVersion::latest()) | ||||||
| .region(Region::new("us-east-1")) | ||||||
| .load() | ||||||
| .await | ||||||
| }); | ||||||
| SecretsManagerClient::new(&config) | ||||||
| } | ||||||
| // Helper function to create a test client | ||||||
| // Note: This creates a real client but tests don't actually call AWS APIs | ||||||
| // In a real scenario, you'd use a mock client | ||||||
| #[allow(dead_code)] // Used in tests | ||||||
|
||||||
| #[allow(dead_code)] // Used in tests | |
| #[cfg(any(test, feature = "test-helpers"))] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,10 +7,12 @@ mod file; | |
| mod secret_backend; | ||
| mod vault; | ||
|
|
||
| pub use aws_secrets::AwsSecretsClient; | ||
| #[allow(unused_imports)] // Used in tests | ||
| pub use aws_secrets::{AwsSecretsClient, create_test_client}; | ||
|
Comment on lines
+10
to
+11
|
||
| pub use file::FileBackend; | ||
| pub use secret_backend::SecretBackend; | ||
| pub use vault::{VaultBackend, VaultClient}; | ||
| #[allow(unused_imports)] // Used in tests | ||
| pub use vault::{VaultBackend, VaultClient, SecretMetadata, VaultSecretData, VaultWriteRequest}; | ||
|
Comment on lines
+14
to
+15
|
||
|
|
||
| /// Backend type enumeration | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ use super::secret_backend::{SecretBackend, SecretData}; | |
| #[derive(Clone)] | ||
| pub struct VaultClient { | ||
| client: Client, | ||
| address: String, | ||
| pub address: String, | ||
|
||
| token: String, | ||
| } | ||
|
|
||
|
|
@@ -31,10 +31,10 @@ struct VaultResponse<T> { | |
| } | ||
|
|
||
| #[derive(Debug, Serialize, Deserialize)] | ||
| struct VaultWriteRequest { | ||
| data: HashMap<String, String>, | ||
| pub struct VaultWriteRequest { | ||
| pub data: HashMap<String, String>, | ||
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| options: Option<HashMap<String, String>>, | ||
| pub options: Option<HashMap<String, String>>, | ||
|
Comment on lines
+34
to
+37
|
||
| } | ||
|
|
||
| impl VaultClient { | ||
|
|
@@ -262,103 +262,3 @@ impl SecretBackend for VaultBackend { | |
| "HashiCorp Vault" | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn test_vault_client_new() { | ||
| let client = VaultClient::new( | ||
| "http://localhost:8200".to_string(), | ||
| "test-token".to_string(), | ||
| ); | ||
| assert!(client.is_ok()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_vault_url_construction() { | ||
| let client = VaultClient::new( | ||
| "http://localhost:8200".to_string(), | ||
| "test-token".to_string(), | ||
| ) | ||
| .unwrap(); | ||
|
|
||
| // Test read URL | ||
| let read_url = format!("{}/v1/{}/data/{}", client.address, "secret", "myapp/db"); | ||
| assert_eq!(read_url, "http://localhost:8200/v1/secret/data/myapp/db"); | ||
|
|
||
| // Test write URL | ||
| let write_url = format!("{}/v1/{}/data/{}", client.address, "secret", "myapp/db"); | ||
| assert_eq!(write_url, "http://localhost:8200/v1/secret/data/myapp/db"); | ||
|
|
||
| // Test metadata URL | ||
| let meta_url = format!("{}/v1/{}/metadata/{}", client.address, "secret", "myapp/db"); | ||
| assert_eq!( | ||
| meta_url, | ||
| "http://localhost:8200/v1/secret/metadata/myapp/db" | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_vault_secret_metadata_parsing() { | ||
| let mut custom_meta = HashMap::new(); | ||
| custom_meta.insert("rotation_enabled".to_string(), "true".to_string()); | ||
| custom_meta.insert( | ||
| "last_rotated".to_string(), | ||
| "2023-01-01T00:00:00Z".to_string(), | ||
| ); | ||
|
|
||
| let metadata = SecretMetadata { | ||
| custom_metadata: Some(custom_meta.clone()), | ||
| }; | ||
|
|
||
| assert_eq!( | ||
| metadata | ||
| .custom_metadata | ||
| .as_ref() | ||
| .unwrap() | ||
| .get("rotation_enabled"), | ||
| Some(&"true".to_string()) | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_vault_secret_data_structure() { | ||
| let mut data = HashMap::new(); | ||
| data.insert("password".to_string(), "secret123".to_string()); | ||
| data.insert("username".to_string(), "admin".to_string()); | ||
|
|
||
| let mut custom_meta = HashMap::new(); | ||
| custom_meta.insert("rotation_enabled".to_string(), "true".to_string()); | ||
|
|
||
| let secret_data = VaultSecretData { | ||
| data: data.clone(), | ||
| metadata: Some(SecretMetadata { | ||
| custom_metadata: Some(custom_meta), | ||
| }), | ||
| }; | ||
|
|
||
| assert_eq!( | ||
| secret_data.data.get("password"), | ||
| Some(&"secret123".to_string()) | ||
| ); | ||
| assert_eq!(secret_data.data.get("username"), Some(&"admin".to_string())); | ||
| assert!(secret_data.metadata.is_some()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_vault_write_request_serialization() { | ||
| let mut data = HashMap::new(); | ||
| data.insert("password".to_string(), "newpass".to_string()); | ||
|
|
||
| let request = VaultWriteRequest { | ||
| data: data.clone(), | ||
| options: None, | ||
| }; | ||
|
|
||
| // Verify structure | ||
| assert_eq!(request.data.get("password"), Some(&"newpass".to_string())); | ||
| assert!(request.options.is_none()); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These internal struct fields are being exposed as public solely to allow integration tests to construct instances directly using struct literal syntax. This exposes AWS SDK implementation details (the
SecretsManagerClient) as part of the public API.A better approach would be to add a test-only constructor function like
new_with_clientmarked with#[cfg(test)]that accepts a client and region, keeping the fields private. Alternatively, sinceAwsSecretsClient::new()already exists as a public constructor, the tests could be refactored to use it instead of direct struct construction.