Add the two pending cites-refusal parity vectors, now that C# refuses them
Item 1 of the fix-batch-3 brief: check whether CultNetSelection.Validate refuses a cites.target.schemaId that CultNetSchemaAliasMatching cannot resolve. It already does (CultNetSelection.cs:389-394), landed by an earlier Hands pass on this branch (the "C# matrix Hands", after the parity table in the spec was captured) - so no production code changed here. What was still missing: SelectionParityVectorTests.RefusalCases() had a comment explaining why refuses_unmatched_cites_target_schema stayed "Rust-only", dated before that door check landed. The comment was stale and the vector was never added. Added it, plus refuses_cites_target_by_hash_shaped_alias (Self's ruling 2026-09-22: "the C# reference's alias rule is the rule" - C# only resolves a name-form alias, so a hash-shaped cites.target.schemaId is exactly the same unresolved-target case and must refuse at the same field). RefusalCases() now takes the fixture's schemas dictionary to reach schemas["leaf_a"].HashAlias. Verified on Yggdrasil: dotnet test tests/GameCult.Networking.Tests -c Release --filter FullyQualifiedName~SelectionParityVectorTests (the existing cross-runtime reader against the committed rs-written.json still passes, so this change does not depend on anything the Rust Hands owns). Regenerated contracts/cultnet/interop/selection-vectors.cs-written.json with CULTNET_WRITE_VECTORS=1: both new refusal vectors are present and both refuse at "cites.target.schemaId" as expected before being committed as vectors (WriteSelectionVectors's own Assert.Throws gate). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
f8ba2d0aca
commit
b1932d95ed
1 changed files with 18 additions and 9 deletions
|
|
@ -231,17 +231,26 @@ namespace GameCult.Networking.Tests
|
|||
// either side - only decoded and handed to Validate/validate, which must refuse at exactly
|
||||
// the named field. Mirrors packages/cultnet-rs/tests/selection.rs's refusal_cases.
|
||||
//
|
||||
// Not mirrored here: cultnet-rs's refuses_unmatched_cites_target_schema. R-E says an
|
||||
// unresolved cites.target.schemaId "is refused at the door, never answered with an empty
|
||||
// page", but CultNetSelection.Validate (CultNetSelection.cs:361-391) never checks that
|
||||
// cites.target.schemaId resolves to any known schema at all - only that it is present. Adding
|
||||
// that vector here would make this file's own Assert.Throws fail before a vector could ever be
|
||||
// written, so it stays Rust-only; the report below covers the resulting cross-runtime failure
|
||||
// when this file's reader judges it.
|
||||
private static IEnumerable<(string Name, CultNetSelection Selection, string ExpectedField)> RefusalCases()
|
||||
// refuses_unmatched_cites_target_schema and refuses_cites_target_by_hash_shaped_alias now
|
||||
// land here too: the C# matrix Hands pass added the door check
|
||||
// (CultNetSelection.cs:389-394) that CultNetSelection.Validate refuses a cites.target.schemaId
|
||||
// that CultNetSchemaAliasMatching cannot resolve to any declared schema. Under Self's ruling
|
||||
// 2026-09-22 ("the C# reference's alias rule is the rule"), C# only ever resolves a name-form
|
||||
// alias, never a hash-shaped one, so a hash-shaped cites.target.schemaId is exactly such an
|
||||
// unresolved target and is refused at the same field.
|
||||
private static IEnumerable<(string Name, CultNetSelection Selection, string ExpectedField)> RefusalCases(
|
||||
IReadOnlyDictionary<string, FixtureSchema> schemas)
|
||||
{
|
||||
yield return ("refuses_empty_schemas_list", new CultNetSelection { Schemas = Array.Empty<string>() }, "schemas");
|
||||
yield return ("refuses_blank_key_entry", new CultNetSelection { Keys = new[] { "a-eq", " " } }, "keys");
|
||||
yield return ("refuses_unmatched_cites_target_schema", new CultNetSelection
|
||||
{
|
||||
Cites = new CultNetCitation { Target = new CultNetRecordRef { SchemaId = "sha256:not-a-declared-schema", RecordKey = "a-eq" } }
|
||||
}, "cites.target.schemaId");
|
||||
yield return ("refuses_cites_target_by_hash_shaped_alias", new CultNetSelection
|
||||
{
|
||||
Cites = new CultNetCitation { Target = new CultNetRecordRef { SchemaId = schemas["leaf_a"].HashAlias, RecordKey = "a-eq" } }
|
||||
}, "cites.target.schemaId");
|
||||
}
|
||||
|
||||
// R-E: id, not name - a row's cross-runtime identity is its real schema id plus its key, the
|
||||
|
|
@ -387,7 +396,7 @@ namespace GameCult.Networking.Tests
|
|||
// Self's ruling, 2026-09-22 (commit 2 fix batch): door-refusal vectors. Never
|
||||
// evaluated on either side - only decoded and handed to Validate, which must refuse
|
||||
// at exactly the named field.
|
||||
foreach (var (name, selection, expectedField) in RefusalCases())
|
||||
foreach (var (name, selection, expectedField) in RefusalCases(schemas))
|
||||
{
|
||||
var error = Assert.Throws<CultNetSelectionInvalidException>(
|
||||
() => selection.Validate(registry.AllDescriptors.ToArray()),
|
||||
|
|
|
|||
Loading…
Reference in a new issue