package inventory import ( "context" "testing" "time" ) // 1933/AC1: a build recorded while a sweep reads the records is never offered to let go of. The record lands between the // sweep's two reads (what it keeps, and what was ever recorded), whichever it reads first: on 2026-10-24 01:51 a // concurrent take-in's route-proxy build landed between them, read as recorded and not kept, and was let go of seconds // after the take-in read its archive. func TestABuildRecordedWhileTheRecordsAreReadIsNotOffered(t *testing.T) { const old, fresh = "artifact-store://x/app@sha256:01", "artifact-store://y/files/blobs/sha256:02" reads, landed := 0, false // read answers what the records hold at the moment of the read; the take-in's RecordBuild lands just after the // first read, before the second. read := func(before, after func()) { if landed { after() } else { before() } reads++ if reads == 1 { landed = true } } recorded := func(context.Context) (out []string, _ error) { read(func() { out = []string{old} }, func() { out = []string{old, fresh} }) return out, nil } keepSet := func(context.Context) (out map[string][]string, _ error) { // Once recorded, the keep set keeps it as recorded lately. read(func() { out = map[string][]string{} }, func() { out = map[string][]string{fresh: {KeptByRecentRecord}} }) return out, nil } collected := func(context.Context) (map[string]bool, error) { return map[string]bool{}, nil } states, err := artifactStates(t.Context(), recorded, keepSet, collected) if err != nil { t.Fatal(err) } for _, s := range states { if s.Reference == fresh && s.State == ArtifactEligible { t.Fatalf("a build recorded between the sweep's reads is offered to let go of: %+v", states) } } } // 1933/AC1: an artifact a build recorded within the last hour, or a build a plan that has not ended names, is kept // whatever else the records say: a new module's first build is not registered yet, and a definition naming it is not // written yet, while its take-in runs. func TestAFreshBuildOrOneAnOpenPlanNamesIsKept(t *testing.T) { now := time.Date(2026, 10, 24, 1, 52, 0, 0, time.UTC) made := func(id, reference string, at time.Time) Build { return Build{ID: id, Module: "route-proxy", At: at, Made: []Artifact{{Name: "files", Kind: "archive", Reference: reference}}} } const ( fresh = "artifact-store://route-proxy/files/blobs/sha256:58bd41dc" planned = "artifact-store://route-proxy/files/blobs/sha256:0ld91a" stale = "artifact-store://route-proxy/files/blobs/sha256:5ta1e" ) builds := []Build{ made("key-ee3448e0-1", fresh, now.Add(-10*time.Second)), made("key-planned-1", planned, now.Add(-3*time.Hour)), made("key-stale-1", stale, now.Add(-2*time.Hour)), {ID: "failed-1", Module: "route-proxy", At: now, Failed: "no", Made: []Artifact{{Reference: "artifact-store://f@sha256:ff"}}}, } kept := keptLately(builds, map[string]bool{"key-planned-1": true}, now, KeptLately) if !has(kept[fresh], KeptByRecentRecord) { t.Errorf("an archive recorded 10 s ago is not kept as recorded lately: %v", kept) } if !has(kept[planned], KeptByOpenPlan) || has(kept[planned], KeptByRecentRecord) { t.Errorf("an archive an open plan names is not kept by that plan alone: %v", kept) } if len(kept[stale]) > 0 { t.Errorf("an archive recorded two hours ago and named by no open plan is kept: %v", kept[stale]) } if len(kept["artifact-store://f@sha256:ff"]) > 0 { t.Errorf("a failed build keeps what it names: %v", kept) } } func has(whys []string, why string) bool { for _, w := range whys { if w == why { return true } } return false }