fix(m9/T32b): resolve $ref in InboundAPI runtime validators (no deploy-passes/runtime-400); diamond test; ref-annotation message
This commit is contained in:
+33
@@ -219,4 +219,37 @@ public class InboundApiSchemaRefTests
|
||||
Assert.Null(result.Schema);
|
||||
Assert.Empty(result.UnresolvedRefs);
|
||||
}
|
||||
|
||||
// ── Diamond: two sibling refs to the SAME name resolve (not a cycle) ───────
|
||||
|
||||
[Fact]
|
||||
public void ParseWithRefs_DiamondSiblingRefs_ResolveBothNotFalseCycle()
|
||||
{
|
||||
// Two sibling properties BOTH reference {"$ref":"lib:Shared"}. The shared
|
||||
// name is popped from the cycle guard after each subtree is resolved, so the
|
||||
// SECOND sibling must resolve too — a diamond is NOT a cycle and must not
|
||||
// trip the guard. Regression for the finally-pop semantics in ResolveLibRef.
|
||||
const string shared = """{"type":"object","properties":{"v":{"type":"integer"}},"required":["v"]}""";
|
||||
const string json =
|
||||
"""{"type":"object","properties":{"left":{"$ref":"lib:Shared"},"right":{"$ref":"lib:Shared"}}}""";
|
||||
|
||||
var result = InboundApiSchema.ParseWithRefs(
|
||||
json,
|
||||
name => name == "Shared" ? shared : null);
|
||||
|
||||
// Neither sibling should be reported unresolved — both resolved cleanly.
|
||||
Assert.Empty(result.UnresolvedRefs);
|
||||
Assert.NotNull(result.Schema);
|
||||
Assert.Equal(2, result.Schema!.Fields.Count);
|
||||
|
||||
foreach (var sibling in new[] { "left", "right" })
|
||||
{
|
||||
var field = Assert.Single(result.Schema.Fields, f => f.Name == sibling);
|
||||
Assert.Equal("object", field.Schema.Type);
|
||||
var inner = Assert.Single(field.Schema.Fields);
|
||||
Assert.Equal("v", inner.Name);
|
||||
Assert.True(inner.Required);
|
||||
Assert.Equal("integer", inner.Schema.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user