builder_build reads the builds and asked states, and the tools bundle follows the catalog half itself (registrations for the watched branches, revision per branch) for `newest`; the manifest names the tool and the two seat verbs. Builds: design 47 G §589, A-87 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
84 lines
4.0 KiB
Go
84 lines
4.0 KiB
Go
package build
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
|
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
|
)
|
|
|
|
const fp2 = "src2:2222222222222222222222222222222222222222222222222222222222222222"
|
|
|
|
func stateOf(vals map[string][]byte) StateRead {
|
|
return StateRead{
|
|
Keys: func() ([]string, error) {
|
|
var ks []string
|
|
for k := range vals {
|
|
ks = append(ks, k)
|
|
}
|
|
sort.Strings(ks)
|
|
return ks, nil
|
|
},
|
|
Get: func(k string) (json.RawMessage, time.Time, error) { return vals[k], time.Time{}, nil }}
|
|
}
|
|
|
|
// Design 47 G §589: builder_build by module answers its keys newest first with whole fingerprints, event-builds and the open
|
|
// ask, and names the watched branches whose newest entry names a key's fingerprint; a module none of whose keys the newest
|
|
// entry names says so; with a fingerprint, that key alone.
|
|
func TestBuilderBuildAnswersAModulesKeysWhole(t *testing.T) {
|
|
failed, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildFailed, EventBuilds: 3, Manifest: mdigest('a'),
|
|
Error: "transport fault: connection, node-build-go ace, dial tcp: connection refused"})
|
|
done, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildDone, Manifest: mdigest('a'), Artifacts: []builds.BuiltArtifact{{Name: "x", Kind: "file", Digest: "sha256:" + strings.Repeat("a", 64)}}})
|
|
k1, _ := builds.BuilderBuildKey("m", fp1)
|
|
k2, _ := builds.BuilderBuildKey("m", fp2)
|
|
other, _ := builds.BuilderBuildKey("other", fp1)
|
|
vals := map[string][]byte{k1: failed, k2: done, other: done}
|
|
ask := occ.Kept{Ask: oc.Ask{ID: "retake-1", About: k1, Expires: occ.FormatTime(time.Now().Add(time.Hour))}, Asked: time.Now()}
|
|
askRaw, _ := json.Marshal(ask)
|
|
r := &BuildReader{Builds: stateOf(vals), Asked: stateOf(map[string][]byte{"ask.retake-1": askRaw}),
|
|
Newest: func(string) (map[string]string, error) { return map[string]string{"main": fp1, "feature": fp2}, nil }}
|
|
a, err := r.Build("m", "")
|
|
if err != nil || len(a.Builds) != 2 {
|
|
t.Fatalf("builds = %+v, %v, want the module's two keys", a, err)
|
|
}
|
|
var row BuildRow
|
|
for _, b := range a.Builds {
|
|
if b.Fingerprint == fp1 {
|
|
row = b
|
|
}
|
|
}
|
|
if row.Fingerprint != fp1 || len(row.Fingerprint) != len("src2:")+64 || row.State != builds.BuildFailed || row.EventBuilds != 3 || row.Node != "ace" ||
|
|
!strings.HasPrefix(row.Error, "transport fault: connection, node-build-go ace, dial tcp") || row.Ask == nil || row.Ask.ID != "retake-1" || len(row.Newest) != 1 || row.Newest[0] != "main" {
|
|
t.Errorf("the failed key = %+v, want its fingerprint whole, its error whole, event-builds 3, the open ask and newest main", row)
|
|
}
|
|
if one, err := r.Build("m", fp2); err != nil || len(one.Builds) != 1 || one.Builds[0].Fingerprint != fp2 || one.Builds[0].Newest[0] != "feature" {
|
|
t.Errorf("one key = %+v, %v", one, err)
|
|
}
|
|
r.Newest = func(string) (map[string]string, error) {
|
|
return map[string]string{"main": "src2:" + strings.Repeat("c", 64)}, nil
|
|
}
|
|
if n, err := r.Build("m", ""); err != nil || !strings.Contains(n.Note, "no build key of m is the newest entry's") || !strings.Contains(n.Note, "main names src2:"+strings.Repeat("c", 64)) {
|
|
t.Errorf("a module none of whose keys the newest entry names: %+v, %v", n, err)
|
|
}
|
|
}
|
|
|
|
// Design 47 G §589: builder_stuck answers each key's fingerprint whole, as the build-input fingerprint the catalog graph entry carries it.
|
|
func TestBuilderStuckAnswersTheFingerprintWhole(t *testing.T) {
|
|
building, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildBuilding, Step: "asked", Manifest: mdigest('a')})
|
|
k, _ := builds.BuilderBuildKey("m", fp1)
|
|
out, err := StuckReader{Builds: stateOf(map[string][]byte{k: building})}.Stuck("m")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rows := out["stuck"].([]Stuck)
|
|
if len(rows) != 1 || rows[0].FP != fp1 {
|
|
t.Fatalf("stuck = %+v, want the fingerprint %s whole", rows, fp1)
|
|
}
|
|
}
|