From a8b47f6185fc54864ee49149d244a59b4f9c03f0 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sat, 5 Sep 2026 03:38:07 +0000 Subject: [PATCH] Strengthen Notarius determinism tests --- internal/config/notarius_test.go | 102 +++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 26 deletions(-) diff --git a/internal/config/notarius_test.go b/internal/config/notarius_test.go index a5cbf12..b13f24d 100644 --- a/internal/config/notarius_test.go +++ b/internal/config/notarius_test.go @@ -297,37 +297,87 @@ func TestNotariusValidationFailureDoesNotMutateConfig(t *testing.T) { } } -func TestNotariusNormalizationIsIndependentOfMapInsertionOrder(t *testing.T) { - first := validNotariusConfig() - first.References = make(map[string]string) - first.References[" party "] = " narratio.input.party " - first.References["chunk . players"] = " narratio.input.players " - first.Outputs = make(map[string]NotariusOutputConfig) - first.Outputs[" npc_registry "] = NotariusOutputConfig{ - LaneID: " npc-registry ", MediaType: " application/json ", - SchemaID: " notarius.dnd.npc_registry ", SchemaVersion: " v1 ", +func TestNotariusNormalizationProducesCanonicalValues(t *testing.T) { + cfg := validNotariusConfig() + cfg.References = map[string]string{ + " party ": " narratio.input.party ", + "chunk . players": " narratio.input.players ", } - first.Outputs["spells"] = NotariusOutputConfig{ - LaneID: " spells ", MediaType: " application/json ", - SchemaID: " notarius.dnd.spells ", SchemaVersion: " v1 ", + cfg.Outputs = map[string]NotariusOutputConfig{ + " npc_registry ": { + LaneID: " npc-registry ", MediaType: " application/json ", + SchemaID: " notarius.dnd.npc_registry ", SchemaVersion: " v1 ", + }, + "spells": { + LaneID: " spells ", MediaType: " application/json ", + SchemaID: " notarius.dnd.spells ", SchemaVersion: " v1 ", + }, } - second := validNotariusConfig() - second.References = make(map[string]string) - second.References["chunk . players"] = " narratio.input.players " - second.References[" party "] = " narratio.input.party " - second.Outputs = make(map[string]NotariusOutputConfig) - second.Outputs["spells"] = first.Outputs["spells"] - second.Outputs[" npc_registry "] = first.Outputs[" npc_registry "] + if err := validateNotarius(cfg, nil); err != nil { + t.Fatalf("validateNotarius() error = %v", err) + } + wantReferences := map[string]string{ + "party": "narratio.input.party", + "chunk.players": "narratio.input.players", + } + if !reflect.DeepEqual(cfg.References, wantReferences) { + t.Fatalf("references = %#v, want %#v", cfg.References, wantReferences) + } + if _, ok := cfg.Outputs[" npc_registry "]; ok { + t.Fatal("outputs retain unnormalized key") + } + if got := cfg.Outputs["npc_registry"]; got.LaneID != "npc-registry" || got.MediaType != "application/json" || got.SchemaID != "notarius.dnd.npc_registry" || got.SchemaVersion != "v1" { + t.Fatalf("normalized npc_registry output = %#v", got) + } +} - if err := validateNotarius(first, nil); err != nil { - t.Fatalf("validateNotarius(first) error = %v", err) +func TestNotariusDiagnosticsUseSortedMapKeys(t *testing.T) { + tests := []struct { + name string + configure func(*NotariusConfig, []string) + wantField string + }{ + { + name: "references", + configure: func(cfg *NotariusConfig, keys []string) { + cfg.References = make(map[string]string, len(keys)) + for _, key := range keys { + cfg.References[key] = "narratio.input.unsupported" + } + }, + wantField: "pipeline.notarius.references.alpha", + }, + { + name: "outputs", + configure: func(cfg *NotariusConfig, keys []string) { + cfg.References = nil + cfg.Outputs = make(map[string]NotariusOutputConfig, len(keys)) + for _, key := range keys { + cfg.Outputs[key] = NotariusOutputConfig{LaneID: key} + } + }, + wantField: "pipeline.notarius.outputs.alpha.media_type", + }, } - if err := validateNotarius(second, nil); err != nil { - t.Fatalf("validateNotarius(second) error = %v", err) - } - if !reflect.DeepEqual(first, second) { - t.Fatalf("normalized configs differ:\nfirst: %#v\nsecond: %#v", first, second) + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + orders := [][]string{{"zeta", "alpha"}, {"alpha", "zeta"}} + diagnostics := make([]string, 0, len(orders)) + for _, keys := range orders { + cfg := validNotariusConfig() + test.configure(cfg, keys) + err := validateNotarius(cfg, nil) + if err == nil || !strings.Contains(err.Error(), test.wantField) { + t.Fatalf("validateNotarius() error = %v, want field %q", err, test.wantField) + } + diagnostics = append(diagnostics, err.Error()) + } + if diagnostics[0] != diagnostics[1] { + t.Fatalf("equivalent maps produced different diagnostics:\nfirst: %s\nsecond: %s", diagnostics[0], diagnostics[1]) + } + }) } }