package bnp import ( "path/filepath" "slices" "strings" "testing" abiv1 "git.dev.alexdunmow.com/block/pluginsdk/abi/v1" "google.golang.org/protobuf/proto" ) func TestHooksPresentIncludesLoadOnce(t *testing.T) { hooks := hooksPresent(&abiv1.PluginManifest{LoadOnceKeys: []string{"defaults.v1"}}) if !slices.Contains(hooks, "load-once") { t.Fatalf("hooksPresent() = %v, want load-once", hooks) } } func TestValidateLoadOnceManifest(t *testing.T) { tests := []struct { name string keys []string ok bool }{ {name: "valid", keys: []string{"documentation-main-menu.v1"}, ok: true}, {name: "uppercase", keys: []string{"DocumentationMenu.v1"}}, {name: "duplicate", keys: []string{"menu.v1", "menu.v1"}}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { err := ValidateLoadOnceManifest(&abiv1.PluginManifest{LoadOnceKeys: test.keys}) if test.ok && err != nil { t.Fatalf("ValidateLoadOnceManifest() error = %v", err) } if !test.ok && err == nil { t.Fatal("ValidateLoadOnceManifest() error = nil") } }) } } func TestVerifyRejectsDuplicateLoadOnceKeys(t *testing.T) { manifestBytes, err := proto.Marshal(&abiv1.PluginManifest{ AbiVersion: 1, Name: "fixture", Version: "1.0.0", LoadOnceKeys: []string{"defaults.v1", "defaults.v1"}, }) if err != nil { t.Fatalf("marshal manifest: %v", err) } out := filepath.Join(t.TempDir(), "fixture.bnp") _, err = packArtifact(out, []packEntry{ {ArtifactPath: fileWasm, Data: []byte("wasm")}, {ArtifactPath: fileMod, Data: []byte("[plugin]\nname = \"fixture\"\nversion = \"1.0.0\"\n")}, {ArtifactPath: fileManifest, Data: manifestBytes}, }) if err != nil { t.Fatalf("pack artifact: %v", err) } if _, err := Verify(out); err == nil || !strings.Contains(err.Error(), "duplicate load-once key") { t.Fatalf("Verify() error = %v, want duplicate key rejection", err) } }