Files
mesh-delivery/modules/mesh-delivery-builder/internal/build/waits_test.go
T
jschoubben b584af3f61 BL14: the builder holds an entry whose fingerprint names another toolchain, in its state waits, with wait-held and wait-ended
An entry whose fingerprint names a toolchain version of its language other than
the agreed one is held in the state waits (one key <module>.<fingerprint>), says
wait-held and wait-ended (ran when the agreed toolchain names the version,
released by builder_release) on its stream waits, says wait-held again for every
key at its start; builder_waits and builder_release; its setting
toolchain-wait-minutes. Not built: the bound's finding toolchain-waits (its
scope is not in the design).

Builds: design 47 G §672, §267, §276, §633
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 20:53:19 +01:00

85 lines
2.8 KiB
Go

package build
import (
"context"
"sync"
"testing"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
)
// memWaits records the waits held and ended.
type memWaits struct {
mu sync.Mutex
held map[string]ToolchainWait
ended []string
}
func (w *memWaits) Hold(_ context.Context, t ToolchainWait) {
w.mu.Lock()
defer w.mu.Unlock()
if w.held == nil {
w.held = map[string]ToolchainWait{}
}
w.held[t.Module+"."+t.Fingerprint] = t
}
func (w *memWaits) End(_ context.Context, module, fp, how string) bool {
w.mu.Lock()
defer w.mu.Unlock()
k := module + "." + fp
if _, ok := w.held[k]; !ok {
return false
}
delete(w.held, k)
w.ended = append(w.ended, how)
return true
}
// Design 47 G §672, §267, §276: an entry whose fingerprint names a toolchain version other than the agreed one is held,
// built and ended `ran` when the agreed toolchain moves to that version; and one held is built with the running build
// module by Release and ended `released`.
func TestAnEntryWhoseFingerprintNamesAnotherToolchainWaitsAndIsBuiltWhenItIsAgreedOrReleased(t *testing.T) {
old := map[string]builds.ToolchainUsed{"go": {Version: "go1.26.0", Recipe: "1"}}
t.Run("ran", func(t *testing.T) {
r := newRig(t, goBundle)
w := &memWaits{}
r.b.Waits = w
r.b.Module(context.Background(), "m", moduleValueWith(t, "modules/m", old))
r.b.Wait()
if len(w.held) != 1 || len(r.st.vals) != 0 {
t.Fatalf("held %v, keys %v: want one wait and nothing written", w.held, r.st.vals)
}
for _, h := range w.held {
if h.On() != "toolchain:go@go1.26.0" {
t.Errorf("the wait is on %s", h.On())
}
}
r.tools.Set("ace", tcOf("go", "go1.26.0"))
r.tools.Set("novox", tcOf("go", "go1.26.0"))
r.b.Reconsider(context.Background())
r.b.Wait()
if v := valueOf(t, r.st, r.key); v.State != builds.BuildDone || len(w.held) != 0 || len(w.ended) != 1 || w.ended[0] != WaitRan {
t.Errorf("build %+v, held %v, ended %v: want done and one wait ended ran", v, w.held, w.ended)
}
})
t.Run("released", func(t *testing.T) {
r := newRig(t, goBundle)
w := &memWaits{}
r.b.Waits = w
v := moduleValueWith(t, "modules/m", old)
r.b.Module(context.Background(), "m", v)
r.b.Wait()
if why := r.b.Release(context.Background(), "m", fp1, "the build module runs", "operator"); why != "" {
t.Fatalf("release refused: %s", why)
}
r.b.Wait()
if got := valueOf(t, r.st, r.key); got.State != builds.BuildDone || got.Toolchains["go"].Version != "go1.27.1" || len(w.ended) != 1 || w.ended[0] != WaitReleased {
t.Errorf("build %+v, ended %v: want done with the running toolchain and a wait ended released", got, w.ended)
}
if why := r.b.Release(context.Background(), "m", fp1, "again", "operator"); why == "" {
t.Error("a second release of an entry that is not held was taken")
}
})
}