From e674f5cad945a9c9ddf9de84d83a94bcb5bb1d3f Mon Sep 17 00:00:00 2001 From: vickydotbat Date: Sun, 21 Jun 2026 15:01:03 +0200 Subject: [PATCH] =?UTF-8?q?test(topdata):=20parity=20guard=20=E2=80=94=20c?= =?UTF-8?q?dn=5Fchannel=20yields=20accessory=20rows=20with=20no=20wrapper/?= =?UTF-8?q?env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- internal/topdata/parity_guard_test.go | 56 +++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 internal/topdata/parity_guard_test.go diff --git a/internal/topdata/parity_guard_test.go b/internal/topdata/parity_guard_test.go new file mode 100644 index 0000000..0408f85 --- /dev/null +++ b/internal/topdata/parity_guard_test.go @@ -0,0 +1,56 @@ +package topdata + +import ( + "testing" + + "git.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project" +) + +// PARITY GUARD: a bare project (no manifest_file, no NWN_ROOT, no token) with a +// cdn_channel consumer must produce accessory rows. If accessory resolution ever +// drifts back out of Crucible into a wrapper, this fails. +func TestParityGuardCDNChannelProducesAccessoryRows(t *testing.T) { + root := testProjectRoot(t) + srv := cdnServer(t, map[string]string{ + "/releases/haks/channels.json": `{"current":"v1.0.0"}`, + "/releases/haks/v1.0.0/vfxs.yml": `assets: + - path: vfxs/head_accessories/hat/hfx_bandana.mdl + restype: mdl + sha256: aaa + - path: vfxs/chest_accessories/cape/cfx_cloak.mdl + restype: mdl + sha256: bbb +`, + }) + t.Setenv("BUNNY_CDN_BASE", srv.URL) + t.Setenv("SOW_TOPDATA_ASSET_CHANNEL", "current") + // Prove R3: no NWN_ROOT in the environment. + t.Setenv("NWN_ROOT", "") + + c := cdnConsumer() + c.Source.CDNBaseEnv = "BUNNY_CDN_BASE" + c.Source.ChannelEnv = "SOW_TOPDATA_ASSET_CHANNEL" + c.AccessoryVisualeffects.ModelColumn = "Imp_HeadCon_Node" + + p := testProject(root) + p.Config.Autogen.Consumers = []project.AutogenConsumerConfig{c} + + collected := []nativeCollectedDataset{{ + Dataset: nativeDataset{Name: "visualeffects", Kind: nativeDatasetBase}, + Columns: []string{"Label", "Imp_HeadCon_Node", "Imp_Root_S_Node"}, + Rows: nil, + LockData: map[string]int{}, + }} + + got, err := applyAutogenConsumers(p, collected, nil) + if err != nil { + t.Fatalf("applyAutogenConsumers failed: %v", err) + } + if len(got[0].Rows) != 2 { + t.Fatalf("PARITY GUARD: expected 2 accessory rows, got %d (%#v)", len(got[0].Rows), got[0].Rows) + } + wantKey := "visualeffects:head_accessories/hat/hfx_bandana.mdl" + if _, ok := got[0].LockData[wantKey]; !ok { + t.Fatalf("PARITY GUARD: expected lock id for %s, got %#v", wantKey, got[0].LockData) + } +}