Ver código fonte

Move kvstore validation tests to common module

Move kvstore validation unit tests from mint/test/kvstore.rs to the
shared database/kvstore.rs module where the validation functions are
defined. This consolidates the tests with their implementation.
Cesar Rodas 1 mês atrás
pai
commit
d5a934769f

+ 206 - 0
crates/cdk-common/src/database/kvstore.rs

@@ -133,3 +133,209 @@ pub trait KVStore: KVStoreDatabase {
         &self,
     ) -> Result<Box<dyn KVStoreTransaction<Self::Err> + Send + Sync>, Error>;
 }
+
+#[cfg(test)]
+mod tests {
+    use super::{
+        validate_kvstore_params, validate_kvstore_string, KVSTORE_NAMESPACE_KEY_ALPHABET,
+        KVSTORE_NAMESPACE_KEY_MAX_LEN,
+    };
+
+    #[test]
+    fn test_validate_kvstore_string_valid_inputs() {
+        // Test valid strings
+        assert!(validate_kvstore_string("").is_ok());
+        assert!(validate_kvstore_string("abc").is_ok());
+        assert!(validate_kvstore_string("ABC").is_ok());
+        assert!(validate_kvstore_string("123").is_ok());
+        assert!(validate_kvstore_string("test_key").is_ok());
+        assert!(validate_kvstore_string("test-key").is_ok());
+        assert!(validate_kvstore_string("test_KEY-123").is_ok());
+
+        // Test max length string
+        let max_length_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN);
+        assert!(validate_kvstore_string(&max_length_str).is_ok());
+    }
+
+    #[test]
+    fn test_validate_kvstore_string_invalid_length() {
+        // Test string too long
+        let too_long_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN + 1);
+        let result = validate_kvstore_string(&too_long_str);
+        assert!(result.is_err());
+        assert!(result
+            .unwrap_err()
+            .to_string()
+            .contains("exceeds maximum length"));
+    }
+
+    #[test]
+    fn test_validate_kvstore_string_invalid_characters() {
+        // Test invalid characters
+        let invalid_chars = vec![
+            "test@key",  // @
+            "test key",  // space
+            "test.key",  // .
+            "test/key",  // /
+            "test\\key", // \
+            "test+key",  // +
+            "test=key",  // =
+            "test!key",  // !
+            "test#key",  // #
+            "test$key",  // $
+            "test%key",  // %
+            "test&key",  // &
+            "test*key",  // *
+            "test(key",  // (
+            "test)key",  // )
+            "test[key",  // [
+            "test]key",  // ]
+            "test{key",  // {
+            "test}key",  // }
+            "test|key",  // |
+            "test;key",  // ;
+            "test:key",  // :
+            "test'key",  // '
+            "test\"key", // "
+            "test<key",  // <
+            "test>key",  // >
+            "test,key",  // ,
+            "test?key",  // ?
+            "test~key",  // ~
+            "test`key",  // `
+        ];
+
+        for invalid_str in invalid_chars {
+            let result = validate_kvstore_string(invalid_str);
+            assert!(result.is_err(), "Expected '{}' to be invalid", invalid_str);
+            assert!(result
+                .unwrap_err()
+                .to_string()
+                .contains("invalid characters"));
+        }
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_valid() {
+        // Test valid parameter combinations
+        assert!(validate_kvstore_params("primary", "secondary", Some("key")).is_ok());
+        assert!(validate_kvstore_params("primary", "", Some("key")).is_ok());
+        assert!(validate_kvstore_params("", "", Some("key")).is_ok());
+        assert!(validate_kvstore_params("p1", "s1", Some("different_key")).is_ok());
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_empty_namespace_rules() {
+        // Test empty namespace rules: if primary is empty, secondary must be empty too
+        let result = validate_kvstore_params("", "secondary", Some("key"));
+        assert!(result.is_err());
+        assert!(result
+            .unwrap_err()
+            .to_string()
+            .contains("If primary_namespace is empty"));
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_collision_prevention() {
+        // Test collision prevention between keys and namespaces
+        let test_cases = vec![
+            ("primary", "secondary", "primary"), // key matches primary namespace
+            ("primary", "secondary", "secondary"), // key matches secondary namespace
+        ];
+
+        for (primary, secondary, key) in test_cases {
+            let result = validate_kvstore_params(primary, secondary, Some(key));
+            assert!(
+                result.is_err(),
+                "Expected collision for key '{}' with namespaces '{}'/'{}'",
+                key,
+                primary,
+                secondary
+            );
+            let error_msg = result.unwrap_err().to_string();
+            assert!(error_msg.contains("conflicts with namespace"));
+        }
+
+        // Test that a combined namespace string would be invalid due to the slash character
+        let result = validate_kvstore_params("primary", "secondary", Some("primary_secondary"));
+        assert!(result.is_ok(), "This should be valid - no actual collision");
+    }
+
+    #[test]
+    fn test_validate_kvstore_params_invalid_strings() {
+        // Test invalid characters in any parameter
+        let result = validate_kvstore_params("primary@", "secondary", Some("key"));
+        assert!(result.is_err());
+
+        let result = validate_kvstore_params("primary", "secondary!", Some("key"));
+        assert!(result.is_err());
+
+        let result = validate_kvstore_params("primary", "secondary", Some("key with space"));
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_alphabet_constants() {
+        // Verify the alphabet constant is as expected
+        assert_eq!(
+            KVSTORE_NAMESPACE_KEY_ALPHABET,
+            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
+        );
+        assert_eq!(KVSTORE_NAMESPACE_KEY_MAX_LEN, 120);
+    }
+
+    #[test]
+    fn test_alphabet_coverage() {
+        // Test that all valid characters are actually accepted
+        for ch in KVSTORE_NAMESPACE_KEY_ALPHABET.chars() {
+            let test_str = ch.to_string();
+            assert!(
+                validate_kvstore_string(&test_str).is_ok(),
+                "Character '{}' should be valid",
+                ch
+            );
+        }
+    }
+
+    #[test]
+    fn test_namespace_segmentation_examples() {
+        // Test realistic namespace segmentation scenarios
+
+        // Valid segmentation examples
+        let valid_examples = vec![
+            ("wallets", "user123", "balance"),
+            ("quotes", "mint", "quote_12345"),
+            ("keysets", "", "active_keyset"),
+            ("", "", "global_config"),
+            ("auth", "session_456", "token"),
+            ("mint_info", "", "version"),
+        ];
+
+        for (primary, secondary, key) in valid_examples {
+            assert!(
+                validate_kvstore_params(primary, secondary, Some(key)).is_ok(),
+                "Valid example should pass: '{}'/'{}'/'{}'",
+                primary,
+                secondary,
+                key
+            );
+        }
+    }
+
+    #[test]
+    fn test_per_namespace_uniqueness() {
+        // This test documents the requirement that implementations should ensure
+        // per-namespace key uniqueness. The validation function doesn't enforce
+        // database-level uniqueness (that's handled by the database schema),
+        // but ensures naming conflicts don't occur between keys and namespaces.
+
+        // These should be valid (different namespaces)
+        assert!(validate_kvstore_params("ns1", "sub1", Some("key1")).is_ok());
+        assert!(validate_kvstore_params("ns2", "sub1", Some("key1")).is_ok()); // same key, different primary namespace
+        assert!(validate_kvstore_params("ns1", "sub2", Some("key1")).is_ok()); // same key, different secondary namespace
+
+        // These should fail (collision within namespace)
+        assert!(validate_kvstore_params("ns1", "sub1", Some("ns1")).is_err()); // key conflicts with primary namespace
+        assert!(validate_kvstore_params("ns1", "sub1", Some("sub1")).is_err()); // key conflicts with secondary namespace
+    }
+}

+ 0 - 207
crates/cdk-common/src/database/mint/test/kvstore.rs

@@ -1,207 +0,0 @@
-//! Tests for KV store validation requirements
-
-#[cfg(test)]
-mod tests {
-    use crate::database::mint::{
-        validate_kvstore_params, validate_kvstore_string, KVSTORE_NAMESPACE_KEY_ALPHABET,
-        KVSTORE_NAMESPACE_KEY_MAX_LEN,
-    };
-
-    #[test]
-    fn test_validate_kvstore_string_valid_inputs() {
-        // Test valid strings
-        assert!(validate_kvstore_string("").is_ok());
-        assert!(validate_kvstore_string("abc").is_ok());
-        assert!(validate_kvstore_string("ABC").is_ok());
-        assert!(validate_kvstore_string("123").is_ok());
-        assert!(validate_kvstore_string("test_key").is_ok());
-        assert!(validate_kvstore_string("test-key").is_ok());
-        assert!(validate_kvstore_string("test_KEY-123").is_ok());
-
-        // Test max length string
-        let max_length_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN);
-        assert!(validate_kvstore_string(&max_length_str).is_ok());
-    }
-
-    #[test]
-    fn test_validate_kvstore_string_invalid_length() {
-        // Test string too long
-        let too_long_str = "a".repeat(KVSTORE_NAMESPACE_KEY_MAX_LEN + 1);
-        let result = validate_kvstore_string(&too_long_str);
-        assert!(result.is_err());
-        assert!(result
-            .unwrap_err()
-            .to_string()
-            .contains("exceeds maximum length"));
-    }
-
-    #[test]
-    fn test_validate_kvstore_string_invalid_characters() {
-        // Test invalid characters
-        let invalid_chars = vec![
-            "test@key",  // @
-            "test key",  // space
-            "test.key",  // .
-            "test/key",  // /
-            "test\\key", // \
-            "test+key",  // +
-            "test=key",  // =
-            "test!key",  // !
-            "test#key",  // #
-            "test$key",  // $
-            "test%key",  // %
-            "test&key",  // &
-            "test*key",  // *
-            "test(key",  // (
-            "test)key",  // )
-            "test[key",  // [
-            "test]key",  // ]
-            "test{key",  // {
-            "test}key",  // }
-            "test|key",  // |
-            "test;key",  // ;
-            "test:key",  // :
-            "test'key",  // '
-            "test\"key", // "
-            "test<key",  // <
-            "test>key",  // >
-            "test,key",  // ,
-            "test?key",  // ?
-            "test~key",  // ~
-            "test`key",  // `
-        ];
-
-        for invalid_str in invalid_chars {
-            let result = validate_kvstore_string(invalid_str);
-            assert!(result.is_err(), "Expected '{}' to be invalid", invalid_str);
-            assert!(result
-                .unwrap_err()
-                .to_string()
-                .contains("invalid characters"));
-        }
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_valid() {
-        // Test valid parameter combinations
-        assert!(validate_kvstore_params("primary", "secondary", Some("key")).is_ok());
-        assert!(validate_kvstore_params("primary", "", Some("key")).is_ok());
-        assert!(validate_kvstore_params("", "", Some("key")).is_ok());
-        assert!(validate_kvstore_params("p1", "s1", Some("different_key")).is_ok());
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_empty_namespace_rules() {
-        // Test empty namespace rules: if primary is empty, secondary must be empty too
-        let result = validate_kvstore_params("", "secondary", Some("key"));
-        assert!(result.is_err());
-        assert!(result
-            .unwrap_err()
-            .to_string()
-            .contains("If primary_namespace is empty"));
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_collision_prevention() {
-        // Test collision prevention between keys and namespaces
-        let test_cases = vec![
-            ("primary", "secondary", "primary"), // key matches primary namespace
-            ("primary", "secondary", "secondary"), // key matches secondary namespace
-        ];
-
-        for (primary, secondary, key) in test_cases {
-            let result = validate_kvstore_params(primary, secondary, Some(key));
-            assert!(
-                result.is_err(),
-                "Expected collision for key '{}' with namespaces '{}'/'{}'",
-                key,
-                primary,
-                secondary
-            );
-            let error_msg = result.unwrap_err().to_string();
-            assert!(error_msg.contains("conflicts with namespace"));
-        }
-
-        // Test that a combined namespace string would be invalid due to the slash character
-        let result = validate_kvstore_params("primary", "secondary", Some("primary_secondary"));
-        assert!(result.is_ok(), "This should be valid - no actual collision");
-    }
-
-    #[test]
-    fn test_validate_kvstore_params_invalid_strings() {
-        // Test invalid characters in any parameter
-        let result = validate_kvstore_params("primary@", "secondary", Some("key"));
-        assert!(result.is_err());
-
-        let result = validate_kvstore_params("primary", "secondary!", Some("key"));
-        assert!(result.is_err());
-
-        let result = validate_kvstore_params("primary", "secondary", Some("key with space"));
-        assert!(result.is_err());
-    }
-
-    #[test]
-    fn test_alphabet_constants() {
-        // Verify the alphabet constant is as expected
-        assert_eq!(
-            KVSTORE_NAMESPACE_KEY_ALPHABET,
-            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
-        );
-        assert_eq!(KVSTORE_NAMESPACE_KEY_MAX_LEN, 120);
-    }
-
-    #[test]
-    fn test_alphabet_coverage() {
-        // Test that all valid characters are actually accepted
-        for ch in KVSTORE_NAMESPACE_KEY_ALPHABET.chars() {
-            let test_str = ch.to_string();
-            assert!(
-                validate_kvstore_string(&test_str).is_ok(),
-                "Character '{}' should be valid",
-                ch
-            );
-        }
-    }
-
-    #[test]
-    fn test_namespace_segmentation_examples() {
-        // Test realistic namespace segmentation scenarios
-
-        // Valid segmentation examples
-        let valid_examples = vec![
-            ("wallets", "user123", "balance"),
-            ("quotes", "mint", "quote_12345"),
-            ("keysets", "", "active_keyset"),
-            ("", "", "global_config"),
-            ("auth", "session_456", "token"),
-            ("mint_info", "", "version"),
-        ];
-
-        for (primary, secondary, key) in valid_examples {
-            assert!(
-                validate_kvstore_params(primary, secondary, Some(key)).is_ok(),
-                "Valid example should pass: '{}'/'{}'/'{}'",
-                primary,
-                secondary,
-                key
-            );
-        }
-    }
-
-    #[test]
-    fn test_per_namespace_uniqueness() {
-        // This test documents the requirement that implementations should ensure
-        // per-namespace key uniqueness. The validation function doesn't enforce
-        // database-level uniqueness (that's handled by the database schema),
-        // but ensures naming conflicts don't occur between keys and namespaces.
-
-        // These should be valid (different namespaces)
-        assert!(validate_kvstore_params("ns1", "sub1", Some("key1")).is_ok());
-        assert!(validate_kvstore_params("ns2", "sub1", Some("key1")).is_ok()); // same key, different primary namespace
-        assert!(validate_kvstore_params("ns1", "sub2", Some("key1")).is_ok()); // same key, different secondary namespace
-
-        // These should fail (collision within namespace)
-        assert!(validate_kvstore_params("ns1", "sub1", Some("ns1")).is_err()); // key conflicts with primary namespace
-        assert!(validate_kvstore_params("ns1", "sub1", Some("sub1")).is_err()); // key conflicts with secondary namespace
-    }
-}

+ 0 - 1
crates/cdk-common/src/database/mint/test/mod.rs

@@ -17,7 +17,6 @@ use crate::database::KVStoreDatabase;
 use crate::mint::MintKeySetInfo;
 
 mod keys;
-mod kvstore;
 mod mint;
 mod proofs;
 mod saga;