Skip to content

Commit 6a8d744

Browse files
committed
fix: correct directional schema compatibility checks
- inline GTS ID references in retained schema definitions - compare const, boolean, bounds, and inferred types by directional inclusion - add regression coverage for compatibility verdicts and dangling local refs Signed-off-by: Aviator 5 <ai.agent.tor@gmail.com>
1 parent 47ad07d commit 6a8d744

3 files changed

Lines changed: 397 additions & 39 deletions

File tree

gts-macros/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,9 @@ pub fn struct_to_gts_schema(attr: TokenStream, item: TokenStream) -> TokenStream
15071507
}
15081508

15091509
inline_gts_id_refs(&mut properties);
1510+
if let Some(definitions) = definitions.as_mut() {
1511+
inline_gts_id_refs(definitions);
1512+
}
15101513
};
15111514

15121515
let prune_unused_definitions = quote! {

gts-macros/tests/integration_tests.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
mod inheritance_tests;
1111

12-
use gts::{GtsConfig, GtsEntity, GtsId, GtsInstanceId, GtsSchema};
12+
use gts::{GtsConfig, GtsEntity, GtsId, GtsInstanceId, GtsSchema, GtsTypeId};
1313
use gts_macros::{gts_id, struct_to_gts_schema};
1414
/// Event Topic (Stream) definition for testing GTS schema generation.
1515
/// Inspired by examples/examples/events/schemas/gts.x.core.events.topic.v1~.schema.json
@@ -55,6 +55,25 @@ pub struct ProductV1 {
5555
pub warehouse_location: String,
5656
}
5757

58+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
59+
pub struct NestedGtsIds {
60+
pub type_id: GtsTypeId,
61+
pub instance_id: GtsInstanceId,
62+
}
63+
64+
#[derive(Debug, Clone)]
65+
#[struct_to_gts_schema(
66+
dir_path = "schemas",
67+
base = true,
68+
type_id = gts_id!("x.test.entities.nested_ids.v1~"),
69+
description = "Entity whose retained definition contains GTS ID references",
70+
properties = "id,nested"
71+
)]
72+
pub struct NestedGtsIdsV1 {
73+
pub id: GtsInstanceId,
74+
pub nested: NestedGtsIds,
75+
}
76+
5877
// =============================================================================
5978
// Tests for 3.a) GTS_SCHEMA_JSON - JSON Schema with proper $id
6079
// =============================================================================
@@ -140,6 +159,45 @@ fn test_schema_json_is_valid_json() {
140159
assert_eq!(product_schema["type"], "object");
141160
}
142161

162+
#[test]
163+
fn test_gts_id_refs_are_inlined_inside_retained_definitions() {
164+
fn contains_gts_id_ref(value: &serde_json::Value) -> bool {
165+
match value {
166+
serde_json::Value::Object(object) => {
167+
let is_gts_id_ref = object
168+
.get("$ref")
169+
.and_then(serde_json::Value::as_str)
170+
.is_some_and(|reference| {
171+
reference.ends_with("/GtsInstanceId")
172+
|| reference.ends_with("/GtsTypeId")
173+
|| reference.ends_with("/GtsSchemaId")
174+
});
175+
is_gts_id_ref || object.values().any(contains_gts_id_ref)
176+
}
177+
serde_json::Value::Array(values) => values.iter().any(contains_gts_id_ref),
178+
_ => false,
179+
}
180+
}
181+
182+
let schema = NestedGtsIdsV1::gts_schema_with_refs();
183+
assert!(
184+
schema["definitions"]["NestedGtsIds"].is_object(),
185+
"the nested definition must remain reachable"
186+
);
187+
assert!(
188+
!contains_gts_id_ref(&schema),
189+
"generated schema contains a dangling GTS-ID definition reference: {schema}"
190+
);
191+
192+
let mut store = gts::GtsStore::new();
193+
store
194+
.register_schema(NestedGtsIdsV1::TYPE_ID, &schema)
195+
.expect("generated schema should register");
196+
store
197+
.validate_schema(NestedGtsIdsV1::TYPE_ID)
198+
.expect("generated schema should have no unresolved local references");
199+
}
200+
143201
#[test]
144202
fn test_schema_json_required_fields() {
145203
let topic_schema: serde_json::Value =

0 commit comments

Comments
 (0)