#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::*;
use crate::entities::{GtsConfig, GtsEntity};
use serde_json::json;
#[test]
fn test_gts_store_query_result_default() {
let result = GtsStoreQueryResult {
error: String::new(),
count: 0,
limit: 100,
results: vec![],
};
assert_eq!(result.count, 0);
assert_eq!(result.limit, 100);
assert!(result.error.is_empty());
assert!(result.results.is_empty());
}
#[test]
fn test_gts_store_query_result_serialization() {
let result = GtsStoreQueryResult {
error: String::new(),
count: 2,
limit: 10,
results: vec![json!({"id": "test1"}), json!({"id": "test2"})],
};
let json_value = serde_json::to_value(&result).expect("test");
let json = json_value.as_object().expect("test");
assert_eq!(json.get("count").expect("test").as_u64().expect("test"), 2);
assert_eq!(json.get("limit").expect("test").as_u64().expect("test"), 10);
assert!(json.get("results").expect("test").is_array());
}
#[test]
fn test_gts_store_new_without_reader() {
let store: GtsStore = GtsStore::new(None);
assert_eq!(store.items().count(), 0);
}
#[test]
fn test_gts_store_register_entity() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
let result = store.register(entity);
assert!(result.is_ok());
assert_eq!(store.items().count(), 1);
}
#[test]
fn test_gts_store_register_schema() {
let mut store = GtsStore::new(None);
let schema_content = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let result = store.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_content);
assert!(result.is_ok());
let entity = store.get("gts.vendor.package.namespace.type.v1.0~");
assert!(entity.is_some());
assert!(entity.expect("test").is_schema);
}
#[test]
fn test_gts_store_register_schema_invalid_id() {
let mut store = GtsStore::new(None);
let schema_content = json!({
"type": "object"
});
let result = store.register_schema(
"gts.vendor.package.namespace.type.v1.0", &schema_content,
);
assert!(result.is_err());
match result {
Err(StoreError::InvalidSchemaId) => {}
_ => panic!("Expected InvalidSchemaId error"),
}
}
#[test]
fn test_gts_store_get_schema_content() {
let mut store = GtsStore::new(None);
let schema_content = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_content)
.expect("test");
let result = store.get_schema_content("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_ok());
assert_eq!(result.expect("test"), schema_content);
}
#[test]
fn test_gts_store_get_schema_content_not_found() {
let mut store = GtsStore::new(None);
let result = store.get_schema_content("nonexistent~");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(id)) => {
assert_eq!(id, "nonexistent~");
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_gts_store_items_iterator() {
let mut store = GtsStore::new(None);
for i in 0..3 {
let schema_content = json!({
"$id": format!("gts.vendor.package.namespace.type.v{i}.0~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema(
&format!("gts.vendor.package.namespace.type.v{i}.0~"),
&schema_content,
)
.expect("test");
}
assert_eq!(store.items().count(), 3);
assert_eq!(store.items().count(), 3);
}
#[test]
fn test_gts_store_validate_instance_missing_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_err());
}
#[test]
fn test_gts_store_build_schema_graph() {
let mut store = GtsStore::new(None);
let schema_content = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_content)
.expect("test");
let graph = store.build_schema_graph("gts.vendor.package.namespace.type.v1.0~");
assert!(graph.is_object());
}
#[test]
fn test_gts_store_query_wildcard() {
let mut store = GtsStore::new(None);
for i in 0..3 {
let schema_content = json!({
"$id": format!("gts.vendor.package.namespace.type.v{i}.0~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
let schema_id = format!("gts.vendor.package.namespace.type.v{i}.0~");
store
.register_schema(&schema_id, &schema_content)
.expect("test");
}
let result = store.query("gts.vendor.*", 10);
assert_eq!(result.count, 3);
assert_eq!(result.results.len(), 3);
}
#[test]
fn test_gts_store_query_with_limit() {
let mut store = GtsStore::new(None);
for i in 0..5 {
let schema_content = json!({
"$id": format!("gts.vendor.package.namespace.type.v{i}.0~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema(
&format!("gts.vendor.package.namespace.type.v{i}.0~"),
&schema_content,
)
.expect("test");
}
let result = store.query("gts.vendor.*", 2);
assert_eq!(result.results.len(), 2);
assert!(result.count >= 2);
}
#[test]
fn test_store_error_display() {
let error = StoreError::ObjectNotFound("test_id".to_owned());
assert!(error.to_string().contains("test_id"));
let error = StoreError::SchemaNotFound("schema_id".to_owned());
assert!(error.to_string().contains("schema_id"));
let error = StoreError::EntityNotFound("entity_id".to_owned());
assert!(error.to_string().contains("entity_id"));
let error = StoreError::SchemaForInstanceNotFound("instance_id".to_owned());
assert!(error.to_string().contains("instance_id"));
}
#[test]
fn test_gts_store_cast() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "default": "test@example.com"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema_v2)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"type": "gts.vendor.package.namespace.type.v1.0~",
"name": "John"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_cast_missing_entity() {
let mut store = GtsStore::new(None);
let result = store.cast("nonexistent", "gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_err());
}
#[test]
fn test_gts_store_cast_missing_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.cast("gts.vendor.package.namespace.type.v1.0", "nonexistent~");
assert!(result.is_err());
}
#[test]
fn test_gts_store_is_minor_compatible() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema_v2)
.expect("test");
let result = store.is_minor_compatible(
"gts.vendor.package.namespace.type.v1.0~",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_backward_compatible);
}
#[test]
fn test_gts_store_get() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.get("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_some());
}
#[test]
fn test_gts_store_get_nonexistent() {
let mut store = GtsStore::new(None);
let result = store.get("nonexistent");
assert!(result.is_none());
}
#[test]
fn test_gts_store_query_exact_match() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let result = store.query("gts.vendor.package.namespace.type.v1.0~", 10);
assert_eq!(result.count, 1);
}
#[test]
fn test_gts_store_register_duplicate() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity1 = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
let entity2 = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity1).expect("test");
let result = store.register(entity2);
assert!(result.is_ok());
}
#[test]
fn test_gts_store_validate_instance_success() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1",
"type": "gts.vendor.package.namespace.type.v1.2~",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1");
assert!(result.is_ok());
}
#[test]
fn test_gts_store_validate_instance_missing_entity() {
let mut store = GtsStore::new(None);
let result = store.validate_instance("nonexistent");
assert!(result.is_err());
}
#[test]
fn test_gts_store_validate_instance_no_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_err());
}
#[test]
fn test_gts_store_register_schema_with_invalid_id() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "invalid",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
let result = store.register_schema("invalid", &schema);
assert!(result.is_err());
}
#[test]
fn test_gts_store_get_schema_content_missing() {
let mut store = GtsStore::new(None);
let result = store.get_schema_content("nonexistent~");
assert!(result.is_err());
}
#[test]
fn test_gts_store_query_empty() {
let store = GtsStore::new(None);
let result = store.query("gts.vendor.*", 10);
assert_eq!(result.count, 0);
assert_eq!(result.results.len(), 0);
}
#[test]
fn test_gts_store_items_empty() {
let store = GtsStore::new(None);
assert_eq!(store.items().count(), 0);
}
#[test]
fn test_gts_store_register_entity_without_id() {
let mut store = GtsStore::new(None);
let content = json!({
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
None,
None,
false,
String::new(),
None,
None,
);
let result = store.register(entity);
assert!(result.is_err());
}
#[test]
fn test_gts_store_build_schema_graph_missing() {
let mut store = GtsStore::new(None);
let graph = store.build_schema_graph("nonexistent~");
assert!(graph.is_object());
}
#[test]
fn test_gts_store_new_empty() {
let store = GtsStore::new(None);
assert_eq!(store.items().count(), 0);
}
#[test]
fn test_gts_store_cast_entity_without_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_err());
}
#[test]
fn test_gts_store_is_minor_compatible_missing_schemas() {
let mut store = GtsStore::new(None);
let result = store.is_minor_compatible("nonexistent1~", "nonexistent2~");
assert!(!result.is_backward_compatible);
}
#[test]
fn test_gts_store_validate_instance_with_refs() {
let mut store = GtsStore::new(None);
let base_schema = json!({
"$id": "gts://gts.vendor.package.namespace.base.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
}
});
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base.v1.0~"},
{
"type": "object",
"properties": {
"name": {"type": "string"}
}
}
]
});
store
.register_schema("gts.vendor.package.namespace.base.v1.0~", &base_schema)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"type": "gts.vendor.package.namespace.type.v1.0~",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_validate_instance_validation_failure() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"age": {"type": "number"}
},
"required": ["age"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"type": "gts.vendor.package.namespace.type.v1.0~",
"age": "not a number"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_err());
}
#[test]
fn test_gts_store_query_with_filters() {
let mut store = GtsStore::new(None);
for i in 0..5 {
let schema = json!({
"$id": format!("gts.vendor.package.namespace.type{i}.v1.0~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema(
&format!("gts.vendor.package.namespace.type{i}.v1.0~"),
&schema,
)
.expect("test");
}
let result = store.query("gts.vendor.package.namespace.type0.*", 10);
assert_eq!(result.count, 1);
}
#[test]
fn test_gts_store_register_multiple_schemas() {
let mut store = GtsStore::new(None);
for i in 0..10 {
let schema = json!({
"$id": format!("gts.vendor.package.namespace.type.v1.{i}~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
let result = store.register_schema(
&format!("gts.vendor.package.namespace.type.v1.{i}~"),
&schema,
);
assert!(result.is_ok());
}
assert_eq!(store.items().count(), 10);
}
#[test]
fn test_gts_store_cast_with_validation() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "default": "test@example.com"}
},
"required": ["name"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema_v2)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"type": "gts.vendor.package.namespace.type.v1.0~",
"name": "John"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_build_schema_graph_with_refs() {
let mut store = GtsStore::new(None);
let base_schema = json!({
"$id": "gts://gts.vendor.package.namespace.base.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
}
});
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base.v1.0~"}
]
});
store
.register_schema("gts.vendor.package.namespace.base.v1.0~", &base_schema)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let graph = store.build_schema_graph("gts.vendor.package.namespace.type.v1.0~");
assert!(graph.is_object());
}
#[test]
fn test_gts_store_get_schema_content_success() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let result = store.get_schema_content("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_ok());
assert_eq!(
result
.expect("test")
.get("type")
.expect("test")
.as_str()
.expect("test"),
"object"
);
}
#[test]
fn test_gts_store_register_entity_with_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"type": "gts.vendor.package.namespace.type.v1.0~",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
let result = store.register(entity);
assert!(result.is_ok());
}
#[test]
fn test_gts_store_query_result_structure() {
let result = GtsStoreQueryResult {
error: String::new(),
count: 0,
limit: 100,
results: vec![],
};
assert_eq!(result.count, 0);
assert_eq!(result.limit, 100);
assert!(result.results.is_empty());
}
#[test]
fn test_gts_store_error_variants() {
let err1 = StoreError::InvalidEntity;
assert!(!err1.to_string().is_empty());
let err2 = StoreError::InvalidSchemaId;
assert!(!err2.to_string().is_empty());
}
#[test]
fn test_gts_store_register_schema_overwrite() {
let mut store = GtsStore::new(None);
let schema1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let schema2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema2)
.expect("test");
let result = store.get_schema_content("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_ok());
let schema = result.expect("test");
assert!(
schema
.get("properties")
.expect("test")
.get("email")
.is_some()
);
}
#[test]
fn test_gts_store_cast_missing_source_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema)
.expect("test");
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_err());
}
#[test]
fn test_gts_store_query_multiple_patterns() {
let mut store = GtsStore::new(None);
let schema1 = json!({
"$id": "gts://gts.vendor1.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
let schema2 = json!({
"$id": "gts://gts.vendor2.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor1.package.namespace.type.v1.0~", &schema1)
.expect("test");
store
.register_schema("gts.vendor2.package.namespace.type.v1.0~", &schema2)
.expect("test");
let result1 = store.query("gts.vendor1.*", 10);
assert_eq!(result1.count, 1);
let result2 = store.query("gts.vendor2.*", 10);
assert_eq!(result2.count, 1);
let result3 = store.query("gts.*", 10);
assert_eq!(result3.count, 2);
}
#[test]
fn test_gts_store_validate_with_nested_refs() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.vendor.package.namespace.base.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
}
});
let middle = json!({
"$id": "gts://gts.vendor.package.namespace.middle.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base.v1.0~"},
{
"type": "object",
"properties": {
"name": {"type": "string"}
}
}
]
});
let top = json!({
"$id": "gts://gts.vendor.package.namespace.top.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.middle.v1.0~"},
{
"type": "object",
"properties": {
"email": {"type": "string"}
}
}
]
});
store
.register_schema("gts.vendor.package.namespace.base.v1.0~", &base)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.middle.v1.0~", &middle)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.top.v1.0~", &top)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.top.v1.0",
"name": "test",
"email": "test@example.com"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.top.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.top.v1.0");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_query_with_version_wildcard() {
let mut store = GtsStore::new(None);
for i in 0..3 {
let schema = json!({
"$id": format!("gts://gts.vendor.package.namespace.type.v{i}.0~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema(
&format!("gts.vendor.package.namespace.type.v{i}.0~"),
&schema,
)
.expect("test");
}
let result = store.query("gts.vendor.package.namespace.type.*", 10);
assert_eq!(result.count, 3);
}
#[test]
fn test_gts_store_cast_backward_incompatible() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v2.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number"}
},
"required": ["name", "age"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v2.0~", &schema_v2)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "John"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.type.v2.0~",
);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_items_iterator_multiple() {
let mut store = GtsStore::new(None);
for i in 0..5 {
let schema = json!({
"$id": format!("gts.vendor.package.namespace.type{i}.v1.0~"),
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema(
&format!("gts.vendor.package.namespace.type{i}.v1.0~"),
&schema,
)
.expect("test");
}
let count = store.items().count();
assert_eq!(count, 5);
}
#[test]
fn test_gts_store_compatibility_fully_compatible() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema_v2)
.expect("test");
let result = store.is_minor_compatible(
"gts.vendor.package.namespace.type.v1.0~",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_backward_compatible);
}
#[test]
fn test_gts_store_build_schema_graph_complex() {
let mut store = GtsStore::new(None);
let base1 = json!({
"$id": "gts://gts.vendor.package.namespace.base1.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
}
});
let base2 = json!({
"$id": "gts://gts.vendor.package.namespace.base2.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let combined = json!({
"$id": "gts://gts.vendor.package.namespace.combined.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base1.v1.0~"},
{"$ref": "gts://gts.vendor.package.namespace.base2.v1.0~"}
]
});
store
.register_schema("gts.vendor.package.namespace.base1.v1.0~", &base1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.base2.v1.0~", &base2)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.combined.v1.0~", &combined)
.expect("test");
let graph = store.build_schema_graph("gts.vendor.package.namespace.combined.v1.0~");
assert!(graph.is_object());
}
#[test]
fn test_gts_store_register_invalid_json_entity() {
let mut store = GtsStore::new(None);
let content = json!({"name": "test"});
let entity = GtsEntity::new(
None,
None,
&content,
None,
None,
false,
String::new(),
None,
None,
);
let result = store.register(entity);
assert!(result.is_err());
}
#[test]
fn test_gts_store_validate_with_complex_schema() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1, "maxLength": 100},
"age": {"type": "integer", "minimum": 0, "maximum": 150},
"email": {"type": "string", "format": "email"},
"tags": {
"type": "array",
"items": {"type": "string"},
"minItems": 1
}
},
"required": ["name", "age"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"tags": ["developer", "rust"]
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_validate_missing_required_field() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_err());
}
#[test]
fn test_gts_store_schema_with_properties_only() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {"type": "string"}
}
});
let result = store.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema);
assert!(result.is_ok());
}
#[test]
fn test_gts_store_query_no_results() {
let store = GtsStore::new(None);
let result = store.query("gts.nonexistent.*", 10);
assert_eq!(result.count, 0);
assert!(result.results.is_empty());
}
#[test]
fn test_gts_store_query_with_zero_limit() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let result = store.query("gts.vendor.*", 0);
assert_eq!(result.results.len(), 0);
}
#[test]
fn test_gts_store_cast_same_version() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.type.v1.0~",
);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_multiple_entities_same_schema() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
for i in 0..5 {
let content = json!({
"id": format!("gts.vendor.package.namespace.instance{i}.v1.0"),
"name": format!("test{i}")
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
}
let count = store.items().count();
assert!(count >= 5); }
#[test]
fn test_gts_store_get_schema_content_for_entity() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let result = store.get_schema_content("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_ok());
let retrieved = result.expect("test");
assert_eq!(
retrieved.get("type").expect("test").as_str().expect("test"),
"object"
);
}
#[test]
fn test_gts_store_compatibility_with_removed_properties() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number"},
"email": {"type": "string"}
}
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema_v2)
.expect("test");
let result = store.is_minor_compatible(
"gts.vendor.package.namespace.type.v1.0~",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_forward_compatible);
}
#[test]
fn test_gts_store_build_schema_graph_single_schema() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let graph = store.build_schema_graph("gts.vendor.package.namespace.type.v1.0~");
assert!(graph.is_object());
}
#[test]
fn test_gts_store_register_schema_without_id() {
let mut store = GtsStore::new(None);
let schema = json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
let result = store.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema);
assert!(result.is_ok());
}
#[test]
fn test_gts_store_validate_with_unresolvable_ref() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.nonexistent.v1.0~"}
]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_query_result_serialization_with_error() {
let result = GtsStoreQueryResult {
error: "Test error message".to_owned(),
count: 0,
limit: 10,
results: vec![],
};
let json_value = serde_json::to_value(&result).expect("test");
let json = json_value.as_object().expect("test");
assert_eq!(
json.get("error").expect("test").as_str().expect("test"),
"Test error message"
);
assert_eq!(json.get("count").expect("test").as_u64().expect("test"), 0);
}
#[test]
fn test_gts_store_resolve_schema_refs_with_merge() {
let mut store = GtsStore::new(None);
let base_schema = json!({
"$id": "gts://gts.vendor.package.namespace.base.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
}
});
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{
"$ref": "gts://gts.vendor.package.namespace.base.v1.0~",
"properties": {
"name": {"type": "string"}
}
}
]
});
store
.register_schema("gts.vendor.package.namespace.base.v1.0~", &base_schema)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_resolve_schema_refs_with_unresolvable_and_properties() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"data": {
"$ref": "gts://gts.vendor.package.namespace.nonexistent.v1.0~",
"type": "object"
}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"data": {}
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_cast_from_schema_entity() {
let mut store = GtsStore::new(None);
let schema_v1 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
let schema_v2 = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_v1)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.1~", &schema_v2)
.expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0~",
"gts.vendor.package.namespace.type.v1.1~",
);
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_gts_store_build_schema_graph_with_schema_id() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.instance.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let graph = store.build_schema_graph("gts.vendor.package.namespace.instance.v1.0");
assert!(graph.is_object());
let graph_obj = graph.as_object().expect("test");
assert!(graph_obj.contains_key("schema_id") || graph_obj.contains_key("errors"));
}
#[test]
fn test_gts_store_query_with_filter_brackets() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
for i in 0..3 {
let content = json!({
"id": format!("gts.vendor.package.namespace.item{i}.v1.0~abc.app.custom.item{i}.v1.0"),
"name": format!("item{i}"),
"status": if i % 2 == 0 { "active" } else { "inactive" }
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
}
let result = store.query("gts.vendor.*[status=active]", 10);
assert!(result.count >= 1);
}
#[test]
fn test_gts_store_query_with_wildcard_filter() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
for i in 0..3 {
let content = if i == 0 {
json!({
"id": format!("gts.vendor.package.namespace.items.v1.0~a.b._.{i}.v1"),
"name": format!("item{i}"),
"category": null
})
} else {
json!({
"id": format!("gts.vendor.package.namespace.items.v1.0~c.d.e.{i}.v1"),
"name": format!("item{i}"),
"category": format!("cat{i}")
})
};
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
}
let mut all_entities = Vec::new();
for i in 0..3 {
let id1 = format!("gts.vendor.package.namespace.items.v1.0~a.b._.{i}.v1");
let id2 = format!("gts.vendor.package.namespace.items.v1.0~c.d.e.{i}.v1");
if let Some(entity) = store.get(&id1) {
all_entities.push((id1, entity.content.get("category").cloned()));
}
if i > 0
&& let Some(entity) = store.get(&id2)
{
all_entities.push((id2, entity.content.get("category").cloned()));
}
}
let non_null_count = all_entities
.iter()
.filter(|(_, cat)| cat.is_some() && cat.as_ref().unwrap() != &serde_json::Value::Null)
.count();
assert_eq!(non_null_count, 2);
}
#[test]
fn test_gts_store_query_invalid_wildcard_pattern() {
let store = GtsStore::new(None);
let result = store.query("gts.vendor*", 10);
assert!(!result.error.is_empty());
assert!(result.error.contains("wildcard"));
}
#[test]
fn test_gts_store_query_invalid_gts_id() {
let store = GtsStore::new(None);
let result = store.query("invalid-id", 10);
assert!(!result.error.is_empty());
}
#[test]
fn test_gts_store_query_gts_id_no_segments() {
let store = GtsStore::new(None);
let result = store.query("gts", 10);
assert!(!result.error.is_empty());
}
#[test]
fn test_gts_store_validate_instance_invalid_gts_id() {
let mut store = GtsStore::new(None);
let result = store.validate_instance("invalid-id");
assert!(result.is_err());
}
#[test]
fn test_gts_store_validate_instance_invalid_schema() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "invalid_type"
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.instance.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.instance.v1.0");
assert!(result.is_err());
}
struct MockGtsReader {
entities: Vec<GtsEntity>,
index: usize,
}
impl MockGtsReader {
fn new(entities: Vec<GtsEntity>) -> Self {
MockGtsReader { entities, index: 0 }
}
}
impl GtsReader for MockGtsReader {
fn iter(&mut self) -> Box<dyn Iterator<Item = GtsEntity> + '_> {
Box::new(self.entities.clone().into_iter())
}
fn read_by_id(&self, entity_id: &str) -> Option<GtsEntity> {
self.entities
.iter()
.find(|e| e.gts_id.as_ref().map(|id| id.id.as_str()) == Some(entity_id))
.cloned()
}
fn reset(&mut self) {
self.index = 0;
}
}
#[test]
fn test_gts_store_with_reader() {
let cfg = GtsConfig::default();
let mut entities = Vec::new();
for i in 0..3 {
let content = json!({
"id": format!("gts.vendor.package.namespace.item{i}.v1.0"),
"name": format!("item{i}")
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
entities.push(entity);
}
let reader = MockGtsReader::new(entities);
let store = GtsStore::new(Some(Box::new(reader)));
assert_eq!(store.items().count(), 3);
}
#[test]
fn test_gts_store_get_from_reader() {
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.item.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
let reader = MockGtsReader::new(vec![entity]);
let mut store = GtsStore::new(Some(Box::new(reader)));
let result = store.get("gts.vendor.package.namespace.item.v1.0");
assert!(result.is_some());
}
#[test]
fn test_gts_store_reader_without_gts_id() {
let content = json!({
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
None,
None,
false,
String::new(),
None,
None,
);
let reader = MockGtsReader::new(vec![entity]);
let store = GtsStore::new(Some(Box::new(reader)));
assert_eq!(store.items().count(), 0);
}
#[test]
fn test_validate_schema_refs_valid_gts_uri() {
let schema = json!({
"$ref": "gts://gts.vendor.package.namespace.type.v1.0~"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_ok());
}
#[test]
fn test_validate_schema_refs_valid_local_ref() {
let schema = json!({
"$ref": "#/definitions/MyType"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_ok());
}
#[test]
fn test_validate_schema_refs_invalid_bare_gts_id() {
let schema = json!({
"$ref": "gts.vendor.package.namespace.type.v1.0~"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("must be a local ref"));
assert!(err.contains("gts://"));
}
#[test]
fn test_validate_schema_refs_invalid_http_uri() {
let schema = json!({
"$ref": "https://example.com/schema.json"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("must be a local ref"));
}
#[test]
fn test_validate_schema_refs_invalid_gts_id_in_uri() {
let schema = json!({
"$ref": "gts://invalid-gts-id"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("invalid GTS identifier"));
}
#[test]
fn test_validate_schema_refs_nested() {
let schema = json!({
"properties": {
"user": {
"$ref": "gts://gts.vendor.package.namespace.user.v1.0~"
},
"order": {
"$ref": "invalid-ref"
}
}
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("properties.order.$ref"));
}
#[test]
fn test_validate_schema_refs_in_array() {
let schema = json!({
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base.v1.0~"},
{"$ref": "not-valid-ref"}
]
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("allOf[1].$ref"));
}
#[test]
fn test_validate_schema_integration() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts.vendor.package.namespace.base.v1.0~"}
]
});
let result = store.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema);
assert!(result.is_ok());
let validation_result = store.validate_schema("gts.vendor.package.namespace.type.v1.0~");
assert!(validation_result.is_err());
let err = validation_result.unwrap_err().to_string();
assert!(err.contains("must be a local ref") || err.contains("gts://"));
}
#[test]
fn test_resolve_schema_refs_with_gts_uri_prefix() {
let mut store = GtsStore::new(None);
let base_schema = json!({
"$id": "gts://gts.vendor.package.namespace.base.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
}
});
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base.v1.0~"}
]
});
store
.register_schema("gts.vendor.package.namespace.base.v1.0~", &base_schema)
.expect("test");
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~instance.v1.0",
"type": "gts.vendor.package.namespace.type.v1.0~"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0~instance.v1.0");
let _ = result;
}
#[test]
fn test_validate_schema_refs_rejects_external_ref_without_gts_prefix() {
let schema = json!({
"$ref": "http://example.com/schema.json"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("must be a local ref") || err.contains("GTS URI"),
"Error should mention local ref or GTS URI requirement"
);
}
#[test]
fn test_validate_schema_refs_rejects_malformed_gts_id_in_ref() {
let schema = json!({
"$ref": "gts://invalid-gts-id"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("invalid GTS identifier") || err.contains("contains invalid"),
"Error should mention invalid GTS identifier"
);
}
#[test]
fn test_validate_schema_refs_accepts_valid_gts_ref() {
let schema = json!({
"$ref": "gts://gts.vendor.package.namespace.type.v1.0~"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_ok(), "Valid gts:// ref should be accepted");
}
#[test]
fn test_validate_schema_refs_accepts_local_json_pointer() {
let schema = json!({
"$ref": "#/definitions/Base"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_ok(), "Local JSON Pointer ref should be accepted");
}
#[test]
fn test_validate_schema_refs_accepts_root_json_pointer() {
let schema = json!({
"$ref": "#"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_ok(), "Root JSON Pointer ref should be accepted");
}
#[test]
fn test_validate_schema_refs_rejects_gts_colon_without_slashes() {
let schema = json!({
"$ref": "gts:gts.vendor.package.namespace.type.v1.0~"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("must be a local ref") || err.contains("GTS URI"),
"Error should mention local ref or GTS URI requirement"
);
}
#[test]
fn test_validate_schema_refs_deeply_nested_invalid_ref() {
let schema = json!({
"properties": {
"level1": {
"properties": {
"level2": {
"properties": {
"level3": {
"$ref": "invalid-external-ref"
}
}
}
}
}
}
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("properties.level1.properties.level2.properties.level3.$ref"),
"Error should report the correct nested path"
);
}
#[test]
fn test_validate_schema_refs_mixed_valid_and_invalid() {
let schema = json!({
"allOf": [
{"$ref": "gts://gts.vendor.package.namespace.base.v1.0~"},
{"$ref": "#/definitions/Local"},
{"$ref": "invalid-ref"}
]
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err(), "Should fail when any ref is invalid");
let err = result.unwrap_err().to_string();
assert!(
err.contains("allOf[2].$ref"),
"Should report the invalid ref path"
);
}
#[test]
fn test_validate_schema_refs_empty_string() {
let schema = json!({
"$ref": ""
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("must be a local ref") || err.contains("GTS URI"),
"Error should mention local ref or GTS URI requirement"
);
}
#[test]
fn test_validate_schema_refs_gts_prefix_but_empty_id() {
let schema = json!({
"$ref": "gts://"
});
let result = GtsStore::validate_schema_refs(&schema, "");
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(
err.contains("invalid GTS identifier") || err.contains("contains invalid"),
"Error should mention invalid GTS identifier"
);
}
#[test]
fn test_validate_schema_x_gts_refs_non_schema_id() {
let mut store = GtsStore::new(None);
let result = store.validate_schema_x_gts_refs("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(msg)) => {
assert!(msg.contains("is not a schema"));
assert!(msg.contains("must end with '~'"));
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_validate_schema_x_gts_refs_schema_not_found() {
let mut store = GtsStore::new(None);
let result = store.validate_schema_x_gts_refs("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(id)) => {
assert_eq!(id, "gts.vendor.package.namespace.type.v1.0~");
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_validate_schema_x_gts_refs_entity_not_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~",
"name": "test"
});
let gts_id = GtsID::new("gts.vendor.package.namespace.type.v1.0~").expect("test");
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
Some(gts_id),
false, String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.validate_schema_x_gts_refs("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(msg)) => {
assert!(msg.contains("is not a schema"));
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_validate_schema_x_gts_refs_validation_error() {
let mut store = GtsStore::new(None);
let schema_content = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"invalidRef": {
"type": "string",
"x-gts-ref": "invalid-gts-id" }
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_content)
.expect("test");
let result = store.validate_schema_x_gts_refs("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_err());
match result {
Err(StoreError::ValidationError(msg)) => {
assert!(msg.contains("x-gts-ref validation failed"));
}
_ => panic!("Expected ValidationError"),
}
}
#[test]
fn test_validate_schema_non_schema_id() {
let mut store = GtsStore::new(None);
let result = store.validate_schema("gts.vendor.package.namespace.type.v1.0");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(msg)) => {
assert!(msg.contains("is not a schema"));
assert!(msg.contains("must end with '~'"));
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_validate_schema_entity_not_schema() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~",
"name": "test"
});
let gts_id = GtsID::new("gts.vendor.package.namespace.type.v1.0~").expect("test");
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
Some(gts_id),
false, String::new(),
None,
None,
);
store.register(entity).expect("test");
let result = store.validate_schema("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(msg)) => {
assert!(msg.contains("is not a schema"));
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_validate_schema_content_not_object() {
let mut store = GtsStore::new(None);
let schema_content = json!(["not", "an", "object"]);
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema_content)
.expect("test");
let result = store.validate_schema("gts.vendor.package.namespace.type.v1.0~");
assert!(result.is_err());
match result {
Err(StoreError::SchemaNotFound(msg)) => {
assert!(msg.contains("is not a schema"));
}
_ => panic!("Expected SchemaNotFound error"),
}
}
#[test]
fn test_validate_instance_schema_compilation_error() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let invalid_schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "invalid-type-value" });
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &invalid_schema)
.expect("test");
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1");
assert!(result.is_err());
match result {
Err(StoreError::ValidationError(msg)) => {
assert!(msg.contains("Invalid schema"), "Actual: {msg}");
}
Err(e) => panic!("Expected ValidationError for invalid schema, got: {e:?}"),
_ => panic!("Expected an error"),
}
}
#[test]
fn test_validate_instance_validation_failed() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1");
assert!(result.is_err());
match result {
Err(StoreError::ValidationError(msg)) => {
assert!(msg.contains("Validation failed"));
}
other => panic!("Expected ValidationError for failed validation, got: {other:?}"),
}
}
#[test]
fn test_validate_instance_x_gts_ref_validation_failed() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let schema = json!({
"$id": "gts://gts.vendor.package.namespace.type.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"refField": {
"type": "string",
"x-gts-ref": "gts.vendor.package.namespace.other.v1.0~"
}
}
});
store
.register_schema("gts.vendor.package.namespace.type.v1.0~", &schema)
.expect("test");
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1",
"refField": "invalid-reference" });
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
Some("gts.vendor.package.namespace.type.v1.0~".to_owned()),
);
store.register(entity).expect("test");
let result = store.validate_instance("gts.vendor.package.namespace.type.v1.0~a.b.c.d.v1");
assert!(result.is_err());
match result {
Err(StoreError::ValidationError(msg)) => {
assert!(msg.contains("x-gts-ref validation failed"));
}
_ => panic!("Expected ValidationError for x-gts-ref validation"),
}
}
#[test]
fn test_cast_missing_schema_for_instance() {
let mut store = GtsStore::new(None);
let cfg = GtsConfig::default();
let content = json!({
"id": "gts.vendor.package.namespace.type.v1.0",
"name": "test"
});
let entity = GtsEntity::new(
None,
None,
&content,
Some(&cfg),
None,
false,
String::new(),
None,
None,
);
store.register(entity).expect("test");
let target_schema = json!({
"$id": "gts://gts.vendor.package.namespace.target.v1.0~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
});
store
.register_schema("gts.vendor.package.namespace.target.v1.0~", &target_schema)
.expect("test");
let result = store.cast(
"gts.vendor.package.namespace.type.v1.0",
"gts.vendor.package.namespace.target.v1.0~",
);
assert!(result.is_err());
match result {
Err(StoreError::SchemaForInstanceNotFound(id)) => {
assert_eq!(id, "gts.vendor.package.namespace.type.v1.0");
}
_ => panic!("Expected SchemaForInstanceNotFound error"),
}
}
#[test]
fn test_op12_single_segment_schema_always_valid() {
let mut store = GtsStore::new(None);
let schema = json!({
"$id": "gts://gts.x.test.base.user.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["userId"],
"properties": {
"userId": {"type": "string"},
"email": {"type": "string"}
}
});
store
.register_schema("gts.x.test.base.user.v1~", &schema)
.expect("register");
let result = store.validate_schema("gts.x.test.base.user.v1~");
assert!(
result.is_ok(),
"Single-segment schema should always pass chain validation"
);
}
#[test]
fn test_op12_derived_tightens_constraints_ok() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.base.user.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["userId", "email"],
"properties": {
"userId": {"type": "string", "format": "uuid"},
"email": {"type": "string", "format": "email"},
"tier": {"type": "string", "maxLength": 100}
}
});
store
.register_schema("gts.x.test12.base.user.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.base.user.v1~x.test12._.premium.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.base.user.v1~"},
{
"type": "object",
"properties": {
"tier": {"type": "string", "enum": ["gold", "platinum"]}
}
}
]
});
store
.register_schema("gts.x.test12.base.user.v1~x.test12._.premium.v1~", &derived)
.expect("register derived");
let result = store.validate_schema("gts.x.test12.base.user.v1~x.test12._.premium.v1~");
assert!(
result.is_ok(),
"Derived that tightens constraints should pass: {result:?}"
);
}
#[test]
fn test_op12_derived_adds_property_ok() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.base.user.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["userId"],
"properties": {
"userId": {"type": "string"}
}
});
store
.register_schema("gts.x.test12.base.user.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.base.user.v1~x.test12._.extended.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.base.user.v1~"},
{
"type": "object",
"properties": {
"extra": {"type": "string"}
}
}
]
});
store
.register_schema(
"gts.x.test12.base.user.v1~x.test12._.extended.v1~",
&derived,
)
.expect("register derived");
let result = store.validate_schema("gts.x.test12.base.user.v1~x.test12._.extended.v1~");
assert!(
result.is_ok(),
"Adding property to open base should pass: {result:?}"
);
}
#[test]
fn test_op12_additional_properties_false_violation() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.closed.account.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["accountId"],
"properties": {
"accountId": {"type": "string"},
"email": {"type": "string"}
},
"additionalProperties": false
});
store
.register_schema("gts.x.test12.closed.account.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.closed.account.v1~x.test12._.premium.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.closed.account.v1~"},
{
"type": "object",
"properties": {
"tier": {"type": "string"}
}
}
]
});
store
.register_schema(
"gts.x.test12.closed.account.v1~x.test12._.premium.v1~",
&derived,
)
.expect("register derived");
let result =
store.validate_schema_chain("gts.x.test12.closed.account.v1~x.test12._.premium.v1~");
assert!(
result.is_err(),
"Adding property when base has additionalProperties:false should fail"
);
}
#[test]
fn test_op12_loosened_max_length_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.str.field.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"value": {"type": "string", "maxLength": 128}
}
});
store
.register_schema("gts.x.test12.str.field.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.str.field.v1~x.test12._.loose.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.str.field.v1~"},
{
"type": "object",
"properties": {
"value": {"type": "string", "maxLength": 256}
}
}
]
});
store
.register_schema("gts.x.test12.str.field.v1~x.test12._.loose.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test12.str.field.v1~x.test12._.loose.v1~");
assert!(result.is_err(), "Loosened maxLength should fail");
}
#[test]
fn test_op12_loosened_maximum_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.num.field.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"size": {"type": "integer", "minimum": 0, "maximum": 100}
}
});
store
.register_schema("gts.x.test12.num.field.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.num.field.v1~x.test12._.loose.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.num.field.v1~"},
{
"type": "object",
"properties": {
"size": {"type": "integer", "minimum": 0, "maximum": 200}
}
}
]
});
store
.register_schema("gts.x.test12.num.field.v1~x.test12._.loose.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test12.num.field.v1~x.test12._.loose.v1~");
assert!(result.is_err(), "Loosened maximum should fail");
}
#[test]
fn test_op12_enum_expansion_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.enum.status.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["active", "inactive"]}
}
});
store
.register_schema("gts.x.test12.enum.status.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.enum.status.v1~x.test12._.expanded.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.enum.status.v1~"},
{
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["active", "inactive", "archived"]}
}
}
]
});
store
.register_schema(
"gts.x.test12.enum.status.v1~x.test12._.expanded.v1~",
&derived,
)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test12.enum.status.v1~x.test12._.expanded.v1~");
assert!(result.is_err(), "Enum expansion should fail");
}
#[test]
fn test_op12_3level_progressive_tightening_ok() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.cascade.msg.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["msgId"],
"properties": {
"msgId": {"type": "string"},
"payload": {"type": "string", "maxLength": 1024}
}
});
store
.register_schema("gts.x.test12.cascade.msg.v1~", &base)
.expect("register base");
let l2 = json!({
"$id": "gts://gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.cascade.msg.v1~"},
{
"type": "object",
"properties": {
"payload": {"type": "string", "maxLength": 512}
}
}
]
});
store
.register_schema("gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~", &l2)
.expect("register L2");
let l3 = json!({
"$id": "gts://gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~x.test12._.short.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~"},
{
"type": "object",
"properties": {
"payload": {"type": "string", "maxLength": 256}
}
}
]
});
store
.register_schema(
"gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~x.test12._.short.v1~",
&l3,
)
.expect("register L3");
let result = store.validate_schema_chain("gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~");
assert!(result.is_ok(), "L2 tightening should pass: {result:?}");
let result = store.validate_schema_chain(
"gts.x.test12.cascade.msg.v1~x.test12._.sms.v1~x.test12._.short.v1~",
);
assert!(
result.is_ok(),
"L3 progressive tightening should pass: {result:?}"
);
}
#[test]
fn test_op12_3level_l3_violates_l2() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.hier.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"size": {"type": "integer", "minimum": 0, "maximum": 1000}
}
});
store
.register_schema("gts.x.test12.hier.base.v1~", &base)
.expect("register base");
let l2 = json!({
"$id": "gts://gts.x.test12.hier.base.v1~x.test12._.medium.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.hier.base.v1~"},
{
"type": "object",
"properties": {
"size": {"type": "integer", "minimum": 100, "maximum": 500}
}
}
]
});
store
.register_schema("gts.x.test12.hier.base.v1~x.test12._.medium.v1~", &l2)
.expect("register L2");
let l3 = json!({
"$id": "gts://gts.x.test12.hier.base.v1~x.test12._.medium.v1~x.test12._.bad.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.hier.base.v1~x.test12._.medium.v1~"},
{
"type": "object",
"properties": {
"size": {"type": "integer", "minimum": 100, "maximum": 800}
}
}
]
});
store
.register_schema(
"gts.x.test12.hier.base.v1~x.test12._.medium.v1~x.test12._.bad.v1~",
&l3,
)
.expect("register L3");
let result = store.validate_schema_chain("gts.x.test12.hier.base.v1~x.test12._.medium.v1~");
assert!(result.is_ok(), "L2 should pass: {result:?}");
let result = store
.validate_schema_chain("gts.x.test12.hier.base.v1~x.test12._.medium.v1~x.test12._.bad.v1~");
assert!(result.is_err(), "L3 loosening L2 maximum should fail");
}
#[test]
fn test_op12_property_disabled_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test12.order.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["orderId", "customerId", "total"],
"properties": {
"orderId": {"type": "string"},
"customerId": {"type": "string"},
"total": {"type": "number", "minimum": 0}
}
});
store
.register_schema("gts.x.test12.order.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test12.order.base.v1~x.test12._.anon_order.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test12.order.base.v1~"},
{
"type": "object",
"properties": {
"customerId": false
}
}
]
});
store
.register_schema(
"gts.x.test12.order.base.v1~x.test12._.anon_order.v1~",
&derived,
)
.expect("register derived");
let result =
store.validate_schema_chain("gts.x.test12.order.base.v1~x.test12._.anon_order.v1~");
assert!(
result.is_err(),
"Disabling a property defined in base should fail"
);
}
#[test]
fn test_op12_derived_loosens_additional_properties_to_true() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test.addl.closed.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
},
"additionalProperties": false
});
store
.register_schema("gts.x.test.addl.closed.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test.addl.closed.v1~x.test._.open.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test.addl.closed.v1~"}
],
"additionalProperties": true
});
store
.register_schema("gts.x.test.addl.closed.v1~x.test._.open.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test.addl.closed.v1~x.test._.open.v1~");
assert!(
result.is_err(),
"Loosening additionalProperties from false to true should fail"
);
}
#[test]
fn test_op12_derived_omits_additional_properties() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test.addl.closed2.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {"type": "string"}
},
"additionalProperties": false
});
store
.register_schema("gts.x.test.addl.closed2.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test.addl.closed2.v1~x.test._.omit.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test.addl.closed2.v1~"}
]
});
store
.register_schema("gts.x.test.addl.closed2.v1~x.test._.omit.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test.addl.closed2.v1~x.test._.omit.v1~");
assert!(
result.is_err(),
"Omitting additionalProperties when base has false should fail"
);
}
#[test]
fn test_op12_derived_omits_const() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test.const.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"status": {"type": "string", "const": "active"}
}
});
store
.register_schema("gts.x.test.const.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test.const.base.v1~x.test._.loose.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.x.test.const.base.v1~"},
{
"properties": {
"status": {"type": "string"} }
}
]
});
store
.register_schema("gts.x.test.const.base.v1~x.test._.loose.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test.const.base.v1~x.test._.loose.v1~");
assert!(result.is_err(), "Omitting const should fail");
}
#[test]
fn test_op12_derived_omits_pattern() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test.pattern.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"email": {"type": "string", "pattern": "^[a-z]+@[a-z]+\\.[a-z]+$"}
}
});
store
.register_schema("gts.x.test.pattern.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test.pattern.base.v1~x.test._.loose.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.x.test.pattern.base.v1~"},
{
"properties": {
"email": {"type": "string"} }
}
]
});
store
.register_schema("gts.x.test.pattern.base.v1~x.test._.loose.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test.pattern.base.v1~x.test._.loose.v1~");
assert!(result.is_err(), "Omitting pattern should fail");
}
#[test]
fn test_op12_derived_omits_enum() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test.enum.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"role": {"type": "string", "enum": ["admin", "user"]}
}
});
store
.register_schema("gts.x.test.enum.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test.enum.base.v1~x.test._.loose.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.x.test.enum.base.v1~"},
{
"properties": {
"role": {"type": "string"} }
}
]
});
store
.register_schema("gts.x.test.enum.base.v1~x.test._.loose.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test.enum.base.v1~x.test._.loose.v1~");
assert!(result.is_err(), "Omitting enum should fail");
}
#[test]
fn test_op12_derived_omits_max_length() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test.maxlen.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string", "maxLength": 50}
}
});
store
.register_schema("gts.x.test.maxlen.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test.maxlen.base.v1~x.test._.loose.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{"$ref": "gts://gts.x.test.maxlen.base.v1~"},
{
"properties": {
"name": {"type": "string"} }
}
]
});
store
.register_schema("gts.x.test.maxlen.base.v1~x.test._.loose.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_chain("gts.x.test.maxlen.base.v1~x.test._.loose.v1~");
assert!(result.is_err(), "Omitting maxLength should fail");
}
#[test]
fn test_op13_traits_all_resolved_passes() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.tr.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"topicRef": {"type": "string"},
"retention": {"type": "string"}
}
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.tr.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.tr.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.tr.base.v1~"},
{
"type": "object",
"x-gts-traits": {
"topicRef": "gts.x.core.events.topic.v1~x.test._.orders.v1",
"retention": "P90D"
}
}
]
});
store
.register_schema("gts.x.test13.tr.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.tr.base.v1~x.test13._.leaf.v1~");
assert!(
result.is_ok(),
"All traits resolved should pass: {result:?}"
);
}
#[test]
fn test_op13_traits_defaults_fill_passes() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.dfl.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"properties": {
"retention": {"type": "string", "default": "P30D"},
"topicRef": {"type": "string", "default": "default_topic"}
}
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.dfl.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.dfl.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.dfl.base.v1~"},
{"type": "object"}
]
});
store
.register_schema("gts.x.test13.dfl.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.dfl.base.v1~x.test13._.leaf.v1~");
assert!(result.is_ok(), "Defaults should fill traits: {result:?}");
}
#[test]
fn test_op13_traits_missing_required_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.mis.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"properties": {
"topicRef": {"type": "string"},
"retention": {"type": "string", "default": "P30D"}
},
"required": ["topicRef"]
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.mis.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.mis.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.mis.base.v1~"},
{
"type": "object",
"x-gts-traits": {"retention": "P90D"}
}
]
});
store
.register_schema("gts.x.test13.mis.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.mis.base.v1~x.test13._.leaf.v1~");
assert!(result.is_err(), "Missing topicRef should fail");
}
#[test]
fn test_op13_traits_wrong_type_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.wt.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"properties": {
"maxRetries": {"type": "integer", "minimum": 0, "default": 3}
}
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.wt.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.wt.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.wt.base.v1~"},
{
"type": "object",
"x-gts-traits": {"maxRetries": "not_a_number"}
}
]
});
store
.register_schema("gts.x.test13.wt.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.wt.base.v1~x.test13._.leaf.v1~");
assert!(result.is_err(), "Wrong type should fail");
}
#[test]
fn test_op13_traits_no_traits_schema_passes() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.nt.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.nt.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.nt.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.nt.base.v1~"},
{"type": "object", "properties": {"extra": {"type": "string"}}}
]
});
store
.register_schema("gts.x.test13.nt.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.nt.base.v1~x.test13._.leaf.v1~");
assert!(
result.is_ok(),
"No traits schema means nothing to validate: {result:?}"
);
}
#[test]
fn test_store_resolve_schema_refs_empty_schema() {
let store = GtsStore::new(None);
let empty_schema = json!({});
let resolved = store.resolve_schema_refs(&empty_schema);
assert_eq!(resolved, empty_schema);
}
#[test]
fn test_store_resolve_schema_refs_null_value() {
let store = GtsStore::new(None);
let null_schema = Value::Null;
let resolved = store.resolve_schema_refs(&null_schema);
assert_eq!(resolved, null_schema);
}
#[test]
fn test_store_resolve_schema_refs_array_value() {
let store = GtsStore::new(None);
let array_schema = json!([1, 2, 3]);
let resolved = store.resolve_schema_refs(&array_schema);
assert_eq!(resolved, array_schema);
}
#[test]
fn test_store_resolve_schema_refs_primitive_value() {
let store = GtsStore::new(None);
let string_schema = json!("test");
let resolved = store.resolve_schema_refs(&string_schema);
assert_eq!(resolved, string_schema);
}
#[test]
fn test_store_resolve_schema_refs_nested_objects() {
let store = GtsStore::new(None);
let nested = json!({
"outer": {
"inner": {
"deep": "value"
}
}
});
let resolved = store.resolve_schema_refs(&nested);
assert_eq!(resolved, nested);
}
#[test]
fn test_store_items_iterator_size() {
let mut store = GtsStore::new(None);
assert_eq!(store.items().count(), 0);
store
.register_schema(
"gts.test.package.namespace.foo.v1~",
&json!({
"$id": "gts://gts.test.package.namespace.foo.v1~",
"type": "object"
}),
)
.unwrap();
assert_eq!(store.items().count(), 1);
}
#[test]
fn test_store_query_empty_expr() {
let store = GtsStore::new(None);
let result = store.query("", 10);
assert!(!result.error.is_empty());
}
#[test]
fn test_store_query_with_very_large_limit() {
let mut store = GtsStore::new(None);
store
.register_schema(
"gts.test.package.namespace.foo.v1~",
&json!({
"$id": "gts://gts.test.package.namespace.foo.v1~",
"type": "object"
}),
)
.unwrap();
let result = store.query("gts.test.package.namespace.foo.v1~", 10000);
assert!(result.error.is_empty());
assert_eq!(result.count, 1);
}
#[test]
fn test_store_register_schema_validates_type_id() {
let mut store = GtsStore::new(None);
let schema_id = "gts.test.package.namespace.minimal.v1~";
let result = store.register_schema(
schema_id,
&json!({
"$id": format!("gts://{schema_id}"),
"type": "object"
}),
);
assert!(result.is_ok());
let bad_id = "gts.test.bad.v1";
let result = store.register_schema(
bad_id,
&json!({
"$id": format!("gts://{bad_id}"),
"type": "object"
}),
);
assert!(result.is_err());
}
#[test]
fn test_store_build_schema_graph_with_nonexistent_id() {
let mut store = GtsStore::new(None);
let graph = store.build_schema_graph("gts.nonexistent.schema.v1~");
assert!(graph.is_object() || graph.is_null());
}
#[test]
fn test_store_error_debug_display() {
let err = StoreError::EntityNotFound("test_id".to_owned());
let debug_str = format!("{err:?}");
assert!(debug_str.contains("EntityNotFound"));
let display_str = format!("{err}");
assert!(display_str.contains("test_id"));
}
#[test]
fn test_store_error_variants() {
let err1 = StoreError::InvalidSchemaId;
assert!(format!("{err1}").contains('~'));
let err2 = StoreError::InvalidEntity;
assert!(format!("{err2:?}").contains("InvalidEntity"));
let err3 = StoreError::ValidationError("test error".to_owned());
assert!(format!("{err3}").contains("test error"));
}
#[test]
fn test_store_get_schema_content_returns_copy() {
let mut store = GtsStore::new(None);
let schema_id = "gts.test.package.namespace.copy.v1~";
let schema = json!({
"$id": format!("gts://{schema_id}"),
"type": "object",
"properties": {"field": {"type": "string"}}
});
store.register_schema(schema_id, &schema).unwrap();
let content1 = store.get_schema_content(schema_id).unwrap();
let content2 = store.get_schema_content(schema_id).unwrap();
assert_eq!(content1, content2);
}
#[test]
fn test_op13_traits_ref_based_trait_schema() {
let mut store = GtsStore::new(None);
let retention_trait = json!({
"$id": "gts://gts.x.test13.traits.retention.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"retention": {"type": "string", "default": "P30D"}
}
});
store
.register_schema("gts.x.test13.traits.retention.v1~", &retention_trait)
.expect("register retention trait");
let topic_trait = json!({
"$id": "gts://gts.x.test13.traits.topic.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"topicRef": {"type": "string"}
}
});
store
.register_schema("gts.x.test13.traits.topic.v1~", &topic_trait)
.expect("register topic trait");
let base = json!({
"$id": "gts://gts.x.test13.ref.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.traits.retention.v1~"},
{"$ref": "gts://gts.x.test13.traits.topic.v1~"}
]
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.ref.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.ref.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.ref.base.v1~"},
{
"type": "object",
"x-gts-traits": {
"topicRef": "gts.x.core.events.topic.v1~x.test._.orders.v1",
"retention": "P90D"
}
}
]
});
store
.register_schema("gts.x.test13.ref.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.ref.base.v1~x.test13._.leaf.v1~");
assert!(
result.is_ok(),
"$ref trait schemas should resolve and validate: {result:?}"
);
}
#[test]
fn test_op13_traits_ref_to_nonexistent_schema() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.badref.base.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.traits.nonexistent.v1~"}
]
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.badref.base.v1~", &base)
.expect("register base");
let derived = json!({
"$id": "gts://gts.x.test13.badref.base.v1~x.test13._.leaf.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.badref.base.v1~"},
{
"type": "object",
"x-gts-traits": {"foo": "bar"}
}
]
});
store
.register_schema("gts.x.test13.badref.base.v1~x.test13._.leaf.v1~", &derived)
.expect("register derived");
let result = store.validate_schema_traits("gts.x.test13.badref.base.v1~x.test13._.leaf.v1~");
assert!(
result.is_err(),
"Unresolvable $ref should cause validation error"
);
}
#[test]
fn test_op13_circular_ref_does_not_hang() {
let mut store = GtsStore::new(None);
let schema_a = json!({
"$id": "gts://gts.x.test13.circ.a.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.circ.b.v1~"}
]
},
"properties": {"id": {"type": "string"}}
});
let schema_b = json!({
"$id": "gts://gts.x.test13.circ.b.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.circ.a.v1~"}
],
"properties": {"name": {"type": "string"}}
});
store
.register_schema("gts.x.test13.circ.a.v1~", &schema_a)
.expect("register A");
store
.register_schema("gts.x.test13.circ.b.v1~", &schema_b)
.expect("register B");
let resolved = store.resolve_schema_refs(&schema_a);
assert!(resolved.is_object(), "should produce a valid object");
}
#[test]
fn test_resolve_schema_refs_checked_detects_duplicate_ref_in_allof() {
let mut store = GtsStore::new(None);
let trait_schema = json!({
"$id": "gts://gts.x.test.dup.trait.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"retention": {"type": "string"}
}
});
store
.register_schema("gts.x.test.dup.trait.v1~", &trait_schema)
.expect("register trait schema");
let trait_schema_value = json!({
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test.dup.trait.v1~"},
{"$ref": "gts://gts.x.test.dup.trait.v1~"}
]
});
let result = store.resolve_schema_refs_checked(&trait_schema_value);
assert!(
result.is_err(),
"resolve_schema_refs_checked should detect duplicate $ref in allOf, got: {result:?}",
);
let resolved = store.resolve_schema_refs(&trait_schema_value);
assert!(resolved.is_object(), "resolve_schema_refs should succeed");
}
#[test]
fn test_op13_change_default_in_mid_fails() {
let mut store = GtsStore::new(None);
let base = json!({
"$id": "gts://gts.x.test13.chdfl.event.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"properties": {
"retention": {
"type": "string",
"default": "P30D"
},
"topicRef": {
"type": "string"
}
}
},
"properties": {"id": {"type": "string"}}
});
store
.register_schema("gts.x.test13.chdfl.event.v1~", &base)
.expect("register base");
let mid = json!({
"$id": "gts://gts.x.test13.chdfl.event.v1~x.test13._.chdfl_mid.v1~",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"allOf": [
{"$ref": "gts://gts.x.test13.chdfl.event.v1~"},
{
"type": "object",
"x-gts-traits-schema": {
"type": "object",
"properties": {
"retention": {
"type": "string",
"default": "P90D"
}
}
},
"x-gts-traits": {
"topicRef": "gts.x.core.events.topic.v1~x.test13._.orders.v1"
}
}
]
});
store
.register_schema("gts.x.test13.chdfl.event.v1~x.test13._.chdfl_mid.v1~", &mid)
.expect("register mid");
let result =
store.validate_schema_traits("gts.x.test13.chdfl.event.v1~x.test13._.chdfl_mid.v1~");
assert!(
result.is_err(),
"Changing default in mid-level should fail, got: {result:?}"
);
}