| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- //! 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
- }
- }
|