#![allow(
clippy::panic,
clippy::unwrap_used,
clippy::expect_used,
clippy::shadow_unrelated,
clippy::assertions_on_result_states
)]
use super::super::registry::*;
use crate::{schema::Schema, *};
use serde_json::json;
type String = Rc<str>;
type SchemaRegistryError = RegistryError;
#[test]
fn test_schema_registry_new() {
let registry = SchemaRegistry::new("test");
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
}
#[test]
fn test_schema_registry_register_success() {
let registry = SchemaRegistry::new("test");
let schema = create_test_schema();
let result = registry.register("test_schema", schema.clone());
assert!(result.is_ok());
assert_eq!(registry.len(), 1);
assert!(registry.contains("test_schema"));
}
#[test]
fn test_schema_registry_register_duplicate() {
let registry = SchemaRegistry::new("test");
let schema = create_test_schema();
let result1 = registry.register("test_schema", schema.clone());
assert!(result1.is_ok());
let result2 = registry.register("test_schema", schema);
assert!(result2.is_err());
if let Err(SchemaRegistryError::AlreadyExists { name, .. }) = result2 {
assert_eq!(name, "test_schema".into());
} else {
panic!("Expected AlreadyExists error");
}
}
#[test]
fn test_schema_registry_get() {
let registry = SchemaRegistry::new("test");
let schema = create_test_schema();
assert!(registry.get("non_existent").is_none());
registry.register("test_schema", schema.clone()).unwrap();
let retrieved = registry.get("test_schema");
assert!(retrieved.is_some());
let retrieved_schema = retrieved.unwrap();
assert!(Rc::ptr_eq(&schema, &retrieved_schema));
}
#[test]
fn test_schema_registry_remove() {
let registry = SchemaRegistry::new("test");
let schema = create_test_schema();
assert!(registry.remove("non_existent").is_none());
registry.register("test_schema", schema.clone()).unwrap();
assert_eq!(registry.len(), 1);
let removed = registry.remove("test_schema");
assert!(removed.is_some());
assert_eq!(registry.len(), 0);
assert!(!registry.contains("test_schema"));
let removed_schema = removed.unwrap();
assert!(Rc::ptr_eq(&schema, &removed_schema));
}
#[test]
fn test_schema_registry_list_names() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
assert!(registry.list_names().is_empty());
let schema1 = create_test_schema();
let schema2 = create_test_schema();
registry.register("schema_a", schema1).unwrap();
registry.register("schema_b", schema2).unwrap();
let names = registry.list_names();
assert_eq!(names.len(), 2);
assert!(names.contains(&"schema_a".into()));
assert!(names.contains(&"schema_b".into()));
}
#[test]
fn test_schema_registry_clear() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
registry.register("schema1", schema.clone()).unwrap();
registry.register("schema2", schema).unwrap();
assert_eq!(registry.len(), 2);
registry.clear();
assert!(registry.is_empty());
assert_eq!(registry.len(), 0);
assert!(registry.list_names().is_empty());
}
#[test]
fn test_error_display() {
let error = SchemaRegistryError::AlreadyExists {
name: "test_schema".into(),
registry: "test".into(),
};
let error_message = format!("{error}");
assert_eq!(
error_message,
"test registration failed: An item with the name 'test_schema' is already registered."
);
let invalid_error = SchemaRegistryError::InvalidName {
name: " ".into(),
registry: "test".into(),
};
let invalid_error_message = format!("{invalid_error}");
assert_eq!(invalid_error_message, "test registration failed: The name ' ' is invalid (empty or whitespace-only names are not allowed).");
}
#[test]
#[cfg(feature = "std")]
fn test_concurrent_access() {
use std::sync::Barrier;
use std::thread;
let test_registry = Rc::new(SchemaRegistry::new("TestSchemaRegistry"));
let barrier = Rc::new(Barrier::new(4));
let mut handles = vec![];
for i in 0..4 {
let barrier = Rc::clone(&barrier);
let registry = Rc::clone(&test_registry);
let handle = thread::spawn(move || {
let schema = create_test_schema();
barrier.wait();
let name = format!("schema_{i}");
registry.register(name, schema)
});
handles.push(handle);
}
let results: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();
for result in results {
assert!(result.is_ok());
}
assert_eq!(test_registry.len(), 4);
}
#[test]
#[cfg(feature = "std")]
fn test_concurrent_duplicate_registration() {
use std::sync::Barrier;
use std::thread;
let test_registry = Rc::new(SchemaRegistry::new("TestSchemaRegistry"));
let barrier = Rc::new(Barrier::new(3));
let mut handles = vec![];
for _ in 0..3 {
let barrier = Rc::clone(&barrier);
let registry = Rc::clone(&test_registry);
let handle = thread::spawn(move || {
let schema = create_test_schema();
barrier.wait();
registry.register("duplicate_name", schema)
});
handles.push(handle);
}
let results: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();
let successes = results.iter().filter(|r| r.is_ok()).count();
let failures = results.iter().filter(|r| r.is_err()).count();
assert_eq!(successes, 1);
assert_eq!(failures, 2);
assert_eq!(test_registry.len(), 1);
}
fn create_test_schema() -> Rc<Schema> {
let schema_json = json!({
"type": "string",
"description": "A test schema"
});
let schema = Schema::from_serde_json_value(schema_json).unwrap();
Rc::new(schema)
}
#[test]
fn test_empty_schema_name() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let result = registry.register("", schema);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
SchemaRegistryError::InvalidName { .. }
));
assert!(!registry.contains(""));
assert_eq!(registry.len(), 0);
assert!(registry.is_empty());
}
#[test]
fn test_unicode_schema_names() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let unicode_names = vec![
"схема", "スキーマ", "模式", "🚀schema", "café-münü", "ñoño", ];
for name in &unicode_names {
let result = registry.register(*name, schema.clone());
assert!(
result.is_ok(),
"Failed to register schema with name: {name}"
);
assert!(registry.contains(name));
}
assert_eq!(registry.len(), unicode_names.len());
let listed_names = registry.list_names();
for name in &unicode_names {
let name: String = (*name).into();
assert!(listed_names.contains(&name));
}
}
#[test]
fn test_very_long_schema_name() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let long_name: String = "a".repeat(1000).into();
let result = registry.register(long_name.clone(), schema);
assert!(result.is_ok());
assert!(registry.contains(&long_name));
let retrieved = registry.get(&long_name);
assert!(retrieved.is_some());
}
#[test]
fn test_special_character_schema_names() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let special_names = vec![
"schema-with-dashes",
"schema_with_underscores",
"schema.with.dots",
"schema:with:colons",
"schema/with/slashes",
"schema with spaces",
"schema\twith\ttabs",
"schema\nwith\nnewlines",
"UPPERCASE_SCHEMA",
"MixedCaseSchema",
"123numeric456",
"!@#$%^&*()",
"\"quoted\"",
"'single-quoted'",
"[bracketed]",
"{curly}",
"(parentheses)",
];
for name in &special_names {
let result = registry.register(*name, schema.clone());
assert!(
result.is_ok(),
"Failed to register schema with name: {name}"
);
assert!(registry.contains(name));
}
assert_eq!(registry.len(), special_names.len());
}
#[test]
fn test_whitespace_only_names() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let whitespace_names = vec![
" ", "\t", "\n", "\r", " ", "\t\t", " \t\n\r ", ];
for name in &whitespace_names {
let result = registry.register(*name, schema.clone());
assert!(
result.is_err(),
"Expected error for whitespace name: {name:?}"
);
assert!(matches!(
result.unwrap_err(),
SchemaRegistryError::InvalidName { .. }
));
assert!(!registry.contains(name));
}
assert_eq!(registry.len(), 0);
}
#[test]
fn test_valid_names_with_whitespace() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let valid_names = vec![
"schema name", " schema", "schema ", "my\tschema", "multi word schema", ];
for name in &valid_names {
let result = registry.register(*name, schema.clone());
assert!(result.is_ok(), "Expected success for valid name: {name:?}");
assert!(registry.contains(name));
}
assert_eq!(registry.len(), valid_names.len());
}
#[test]
fn test_same_schema_different_names() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let names = vec!["name1", "name2", "name3"];
for name in &names {
let result = registry.register(*name, schema.clone());
assert!(result.is_ok());
}
assert_eq!(registry.len(), names.len());
for name in &names {
let retrieved = registry.get(name).unwrap();
assert!(Rc::ptr_eq(&schema, &retrieved));
}
}
#[test]
fn test_register_after_remove_and_clear() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
registry.register("test", schema.clone()).unwrap();
assert!(registry.contains("test"));
registry.remove("test");
assert!(!registry.contains("test"));
let result = registry.register("test", schema.clone());
assert!(result.is_ok());
assert!(registry.contains("test"));
registry.clear();
assert!(registry.is_empty());
let result = registry.register("test", schema);
assert!(result.is_ok());
assert!(registry.contains("test"));
}
#[test]
fn test_case_sensitive_names() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
let case_variants = vec!["test", "Test", "TEST", "tEsT"];
for name in &case_variants {
let result = registry.register(*name, schema.clone());
assert!(
result.is_ok(),
"Failed to register schema with name: {name}"
);
}
assert_eq!(registry.len(), case_variants.len());
for name in &case_variants {
assert!(registry.contains(name));
let retrieved = registry.get(name);
assert!(retrieved.is_some());
}
}
#[test]
fn test_error_after_schema_removal() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema = create_test_schema();
registry.register("test", schema.clone()).unwrap();
registry.remove("test");
let result = registry.register("test", schema);
assert!(result.is_ok());
}
#[test]
fn test_mixed_operations_sequence() {
let registry = SchemaRegistry::new("TestSchemaRegistry");
let schema1 = create_test_schema();
let schema2 = create_test_schema();
registry.register("a", schema1.clone()).unwrap();
registry.register("b", schema2.clone()).unwrap();
assert_eq!(registry.len(), 2);
assert!(registry.register("a", schema1.clone()).is_err());
assert_eq!(registry.len(), 2);
registry.remove("a");
assert_eq!(registry.len(), 1);
registry.register("a", schema1).unwrap();
assert_eq!(registry.len(), 2);
registry.clear();
assert!(registry.is_empty());
assert!(registry.list_names().is_empty());
}