package main import ( "encoding/json" "strings" "testing" "time" "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun" "git.novox.be/novox/mesh-delivery/sdk/buildstep" stdio "git.novox.be/novox/mesh-sdk/go" ) type fakeHeard struct{ m map[string]json.RawMessage } func (f *fakeHeard) Keys() ([]string, error) { var out []string for k := range f.m { out = append(out, k) } return out, nil } func (f *fakeHeard) Get(k string) (*stdio.StateEntry, error) { v, ok := f.m[k] if !ok { return nil, nil } return &stdio.StateEntry{Key: k, Value: v}, nil } func (f *fakeHeard) Delete(k string) error { delete(f.m, k); return nil } // Design 47 G §604, §546: builder_toolchains lists the keys; builder_toolchains_drop deletes one with its why, after the // hand act is recorded, and nothing is deleted when it is not. func TestToolchainsToolsListAndDropAKeyAfterTheHandAct(t *testing.T) { data, err := buildstep.EncodeToolchain(buildstep.Toolchain{Language: "go", Version: "1.26.0", Recipe: "1", Digest: "sha256:a", At: time.Now()}) if err != nil { t.Fatal(err) } st := &fakeHeard{m: map[string]json.RawMessage{"ace.go": data}} asked := 0 var failAct error acts := meshhandactsclient.Recorder{Ask: func(string, any) (json.RawMessage, error) { asked++ return json.RawMessage(`{"id":"h1"}`), failAct }} tools := toolchainsTools(st, acts, time.Now) run := func(name string, args map[string]any) (any, error) { for _, tl := range tools { if tl.Name == name { return tl.Run(args) } } t.Fatalf("no tool %s", name) return nil, nil } got, err := run(buildrun.ToolchainsTool, nil) rows := got.(map[string]any)["toolchains"].([]map[string]any) if err != nil || len(rows) != 1 || rows[0]["key"] != "ace.go" || rows[0]["digest"] != "sha256:a" { t.Fatalf("listed %v, %v", got, err) } if _, err := run(buildrun.ToolchainsDropTool, map[string]any{"key": "ace.go", "why": ""}); err == nil { t.Fatal("a drop with no why was taken") } failAct = json.Unmarshal([]byte("x"), new(int)) if _, err := run(buildrun.ToolchainsDropTool, map[string]any{"key": "ace.go", "why": "ace left"}); err == nil || !strings.Contains(err.Error(), "nothing was dropped") || len(st.m) != 1 { t.Fatalf("a hand act not recorded still dropped: %v", err) } failAct = nil if _, err := run(buildrun.ToolchainsDropTool, map[string]any{"key": "ace.go", "why": "ace left"}); err != nil || len(st.m) != 0 || asked < 2 { t.Fatalf("the drop: %v, keys left %d", err, len(st.m)) } }