The delivery repository's contracts and SDK live under modules/ as mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths renamed to match the folders (the TypeScript names already did), and every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools and mesh-sdk follows in the same group: a design as it should be, one path per module, checked by the group's check building every importer. Builds: design 47 G §427, §88 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
74 lines
2.6 KiB
Go
74 lines
2.6 KiB
Go
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/modules/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))
|
|
}
|
|
}
|