Files
mesh-delivery/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/stepsread_test.go
T
jschoubben 39db267630 D1 (builder): the builder names its own module and buckets from its credential's module
Its states' buckets, its finding observer, its build log entries and its step asks' asker take the credential's module (tools: the module the runtime serves them as) instead of constants of its name; builds.StateBucket/BuildsBucket replace the Bucket constants. The readers of the builds bucket (checker, view, grants) still name the builder: the next D1 subtask finds it by the seat mesh-builds.

Builds: design 47 G A-296, §428

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 22:34:08 +01:00

45 lines
2.2 KiB
Go

package main
import (
"context"
"errors"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
"strings"
"testing"
"time"
"github.com/nats-io/nats.go/jetstream"
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
"mesh-delivery-builder/internal/versions"
)
// Design 47 G §568, A-77: the first fault of the read of an ask's steps arms a bound key with its own time to live; its end
// while the read is unanswered raises call-unanswered about the ask; the answer deletes the bound and clears the finding.
func TestTheStepsReadIsCallUnansweredAfterItsBound(t *testing.T) {
st := &memFindings{vals: map[string][]byte{}}
f := &findings{module: builds.BuilderModule, w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }}
marks := &memBounds{keys: map[string]bool{}}
s := &stepsRead{bounds: func() jetstream.KeyValue { return marks }, findings: f, bound: meshconditionsclient.CallUnansweredAfter,
now: func() time.Time { return time.Unix(600, 0) }, logf: t.Logf}
ask := "mvl0frv18d1958"
callKey := meshconditionsclient.Key(meshconditionsclient.ScopeCall, ask, meshconditionsclient.KindCallUnanswered)
s.unanswered("mesh-build-go", ask, errors.New("nats: no responders available for request"))
if !marks.keys[versions.StepsBoundKey("mesh-build-go", ask)] || st.vals[callKey] != nil {
t.Fatalf("a first fault: bound %v, finding %v; want the bound armed, no finding yet", marks.keys, st.vals[callKey] != nil)
}
s.expired(context.Background(), purged{key: versions.StepsBoundKey("mesh-build-go", ask)})
if got, err := decodeFinding(st.vals[callKey]); err != nil || got.Kind != meshconditionsclient.KindCallUnanswered || !strings.Contains(got.Summary, "the steps of mesh-build-go") || !strings.Contains(got.Summary, ask) {
t.Fatalf("the bound's end: the finding = %+v, %v", got, err)
}
s.answered("mesh-build-go", ask)
if marks.keys[versions.StepsBoundKey("mesh-build-go", ask)] || st.vals[callKey] != nil {
t.Errorf("the read answered: bound %v, finding left %v", marks.keys, st.vals[callKey] != nil)
}
s.expired(context.Background(), purged{key: versions.StepsBoundKey("mesh-build-go", ask)})
if st.vals[callKey] != nil {
t.Error("a bound's end after the answer raised call-unanswered")
}
}