105 lines
3.6 KiB
Go
105 lines
3.6 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// A6, A7 whole against the store and a real bus (ADR 0503 §6, ADR 0498 check §7; issue 1851): a walk whose modules the
|
|
// builder built goes from asked to built with no build asked, its keys taken in off the plans' hold, then sends its tier
|
|
// to the first machine as before; a key still building holds the tier, said, and moves on when the builder's key is done.
|
|
func TestAWalkTakesItsTierFromTheBuildersKeysAndSendsIt(t *testing.T) {
|
|
withTheGate(t)
|
|
judgeLeavesAsTheCore(t)
|
|
tm := aTierMesh(t, "app1", "app2")
|
|
ctx := t.Context()
|
|
inv := tm.open.inventory
|
|
noBuildAsked(t)
|
|
b := aBuilderOnTheBus(t)
|
|
|
|
// The walk carries c3 of the catalogue; its tier is unasked.
|
|
p := tm.plan(t)
|
|
p.Commit = "c3c3c3c3c3c3c3c3"
|
|
for _, m := range []string{"app1", "app2"} {
|
|
p.Modules[m] = &inventory.PlanModule{}
|
|
}
|
|
if err := inv.SavePlan(ctx, &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fp1, fp2 := fpOf('1'), fpOf('2')
|
|
m1 := b.indexed(t, "app1", "c3", "novox/mesh-catalog", "modules/app1", p.Commit, fp1)
|
|
m2 := b.indexed(t, "app2", "c3", "novox/mesh-catalog", "modules/app2", p.Commit, fp2)
|
|
b.built(t, "app1", "c3", fp1, m1, sdkdelivery.BuildDone)
|
|
b.built(t, "app2", "c3", fp2, m2, sdkdelivery.BuildBuilding)
|
|
|
|
advancePlans(ctx, tm.open)
|
|
becomes(t, 10*time.Second, "app1 taken from its key", func() bool {
|
|
advancePlans(ctx, tm.open)
|
|
return tm.plan(t).Modules["app1"].State == "built"
|
|
})
|
|
p = tm.plan(t)
|
|
if s := p.Modules["app2"]; s.State != "asked" || !s.Key || !strings.Contains(s.Why, "building on ace") {
|
|
t.Fatalf("A7: app2, whose key is building, is %+v", s)
|
|
}
|
|
if len(tm.sent) != 0 {
|
|
t.Fatalf("A7: the tier was sent while app2 waits on its key: %v", tm.sent)
|
|
}
|
|
if s := p.Modules["app1"]; !strings.Contains(s.Made, "taken from the builder's key") || s.Fingerprint != fp1 {
|
|
t.Fatalf("A6: plans does not say app1 was taken from the builder's key: %+v", s)
|
|
}
|
|
|
|
b.built(t, "app2", "c3", fp2, m2, sdkdelivery.BuildDone)
|
|
becomes(t, 10*time.Second, "the tier sent to the first machine", func() bool {
|
|
advancePlans(ctx, tm.open)
|
|
return len(tm.sent) > 0
|
|
})
|
|
p = tm.plan(t)
|
|
if !reflect.DeepEqual(tm.sent[0], []string{"anchor"}) {
|
|
t.Fatalf("A6: the tier taken from keys was sent %v, not to the first machine", tm.sent)
|
|
}
|
|
current, err := inv.CurrentBuilds(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, m := range []string{"app1", "app2"} {
|
|
if current[m].Commit != p.Commit || !strings.HasPrefix(p.Modules[m].Build, "key-") {
|
|
t.Fatalf("A6: %s stands on %+v (%s), not the key's build at %s", m, current[m], p.Modules[m].Build, p.Commit)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A7: a failed key fails the walk with the builder's words, and nothing is sent.
|
|
func TestAFailedKeyFailsTheWalkInTheBuildersWords(t *testing.T) {
|
|
tm := aTierMesh(t, "app1")
|
|
ctx := t.Context()
|
|
inv := tm.open.inventory
|
|
noBuildAsked(t)
|
|
b := aBuilderOnTheBus(t)
|
|
p := tm.plan(t)
|
|
p.Commit = "c4c4c4c4c4c4c4c4"
|
|
p.Modules["app1"] = &inventory.PlanModule{}
|
|
if err := inv.SavePlan(ctx, &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fp := fpOf('4')
|
|
manifest := b.indexed(t, "app1", "c4", "novox/mesh-catalog", "modules/app1", p.Commit, fp)
|
|
b.built(t, "app1", "c4", fp, manifest, sdkdelivery.BuildFailed)
|
|
for i := 0; i < 3; i++ {
|
|
advancePlans(ctx, tm.open)
|
|
}
|
|
p = tm.plan(t)
|
|
if p.State != inventory.PlanFailed || !strings.Contains(p.Note, "digests differ: ace sha256:1, g14 sha256:2") {
|
|
t.Fatalf("A7: the walk is %s: %q", p.State, p.Note)
|
|
}
|
|
if len(tm.sent) != 0 {
|
|
t.Fatalf("A7: a failed walk sent %v", tm.sent)
|
|
}
|
|
}
|