package inventory import ( "encoding/json" "testing" "time" "github.com/novox/mesh-controller/internal/catalogue" ) // TestWhatRunsIsTheRegisteredBuildNotANewerOnePutBack is novox/hq issue 721's review: the newest build of a module // failed its gate and the mesh put the build before it back. Held names the newest; what runs, and what a merge's build // is compared with, is the build put back — so a merge whose bytes equal the failed build is never said unchanged. func TestWhatRunsIsTheRegisteredBuildNotANewerOnePutBack(t *testing.T) { inv := fresh(t) ctx := t.Context() manifestOf := func(image string) catalogue.Manifest { return catalogue.Manifest{Module: "one", Version: "1", Resources: []map[string]any{ {"id": "app", "type": "container", "name": "one", "image": image}}} } record := func(id, image string, asked time.Time) Build { t.Helper() raw, _ := json.Marshal(manifestOf(image)) b := Build{ID: id, Module: "one", Commit: id + "aaaaaaaa", Repository: "novox/one", Manifest: raw, Asked: asked, At: asked, Made: []Artifact{{Name: "one", Kind: "image", Reference: image}}} if err := inv.RecordBuild(ctx, b); err != nil { t.Fatal(err) } if err := inv.RegisterModule(ctx, manifestOf(image), Source{Repository: "novox/one", BuiltFrom: b.Commit, Asked: asked}); err != nil { t.Fatal(err) } return b } x := "store/one@sha256:" + "1111111111111111111111111111111111111111111111111111111111111111" y := "store/one@sha256:" + "2222222222222222222222222222222222222222222222222222222222222222" before := record("x", x, time.Now().Add(-2*time.Hour)) failed := record("y", y, time.Now().Add(-time.Minute)) if err := inv.RecordGate(ctx, GateVerdict{Build: failed.ID, Module: "one", Commit: failed.Commit, Machines: []string{"anchor"}, Verdict: GateFailed}); err != nil { t.Fatal(err) } if err := inv.RestoreModule(ctx, before); err != nil { t.Fatal(err) } held, err := inv.Held(ctx) if err != nil { t.Fatal(err) } running, err := inv.RegisteredHeld(ctx) if err != nil { t.Fatal(err) } if running["one/one"] == y { t.Fatalf("what runs is read as the build whose gate failed (%s); Held says %s", y, held["one/one"]) } if got := running["one/one"]; got != "" && got != x { t.Fatalf("what runs is read as %s, want the build put back %s or nothing", got, x) } } // TestOnlyArtifactsTheRegisteredManifestNamesAreRunning: registeredOnly keeps a held artifact only when its digest is // in its module's registered manifest. func TestOnlyArtifactsTheRegisteredManifestNamesAreRunning(t *testing.T) { held := map[string]string{"one/app": "store/one@sha256:aaaa", "two/app": "store/two@sha256:bbbb", "three/app": "nodigest"} registered := map[string]string{"one": `{"resources":[{"image":"store/one@sha256:aaaa"}]}`, "two": `{"resources":[{"image":"store/two@sha256:cccc"}]}`, "three": "nodigest"} got := registeredOnly(held, registered) if len(got) != 1 || got["one/app"] == "" { t.Fatalf("running reads %v, want one/app alone", got) } }