diff --git a/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go b/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go index 9e96ad9..8268215 100644 --- a/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go +++ b/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go @@ -305,7 +305,8 @@ func startBed(t *testing.T) *bed { for name, history := range map[string]int{delivery.CheckerVerdictsBucket: delivery.CheckerVerdictsHistory, delivery.CheckerKeptBucket: delivery.CheckerKeptHistory, delivery.CheckerOwedBucket: delivery.CheckerOwedHistory, delivery.PreviewsBucket: delivery.PreviewsHistory, delivery.CandidatesBucket: delivery.CandidatesHistory, delivery.ModulesBucket: delivery.ModulesHistory, delivery.ManifestsBucket: delivery.ManifestsHistory, delivery.SourceBucket: delivery.SourceHistory, - delivery.PresenceBucket: delivery.PresenceHistory, delivery.HaveBucket: delivery.HaveHistory, check.TriesBucket: 1} { + delivery.PresenceBucket: delivery.PresenceHistory, delivery.HaveBucket: delivery.HaveHistory, check.TriesBucket: 1, + delivery.TurnsBucket: delivery.TurnsHistory} { kv, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: name, History: uint8(history)}) if err != nil { t.Fatal(err) @@ -507,9 +508,12 @@ func TestCheckerJudgesACandidateAndOwesItsStatus(t *testing.T) { // N6/AC5, 1300 } } -// TestACheckOfEqualInputsRunsNothing: a second candidate (another head, the same digests) is checked with every package -// taken from the first's kept verdicts: no test step runs and no second kept key appears. -func TestACheckOfEqualInputsRunsNothing(t *testing.T) { // 1287/AC5, 1288/AC6, 1929/AC2 +// TestACheckOrACarryOfEqualInputsRunsNothing: a second candidate (another head, the same digests) is checked with every +// package taken from the first's kept verdicts: no test step runs and no second kept key appears. Then, through the real bus +// (novox/hq ADR 0548 §3, §5): a third candidate is not claimed while the gate's merge turn on its repository stands, and is +// claimed when the turn's key is deleted; and a move of the trunk carries the first verdict on the recheck stream by its +// unchanged digests, running no test, the verdict naming the trunk it was carried from. +func TestACheckOrACarryOfEqualInputsRunsNothing(t *testing.T) { // 1287/AC5, 1288/AC6, 1929/AC2, ADR 0548 §3, §5 b := startBed(t) first := b.candidate(t, "feat/x", pull(repo, 7, head1)) b.start(t, nil) @@ -526,6 +530,42 @@ func TestACheckOfEqualInputsRunsNothing(t *testing.T) { // 1287/AC5, 1288/AC6, 1 if got := keptCount(t, b); got != kept { t.Errorf("%d kept keys, was %d", got, kept) } + + // §3: the gate's turn on the repository holds a new check off; its delete claims it. + at := time.Now().UTC() + turn, err := delivery.EncodeTurn(delivery.Turn{Repository: repo, Waiting: []delivery.TurnWait{{Group: "fix/other", Heads: "0123456789ab", Approved: at, Since: at}}}) + if err != nil { + t.Fatal(err) + } + tk, _ := delivery.TurnsKey(repo) + if _, err := b.buckets[delivery.TurnsBucket].Put(b.ctx, tk, turn); err != nil { + t.Fatal(err) + } + time.Sleep(300 * time.Millisecond) // the checker hears the turn + third := b.candidate(t, "feat/z", pull(repo, 9, "3333333333333333333333333333333333333333")) + time.Sleep(time.Second) + if _, err := b.buckets[delivery.CheckerVerdictsBucket].Get(b.ctx, third); !errors.Is(err, jetstream.ErrKeyNotFound) { + t.Fatalf("verdicts.%s exists (%v) while a merge turn holds its repository", third, err) + } + if err := b.buckets[delivery.TurnsBucket].Delete(b.ctx, tk); err != nil { + t.Fatal(err) + } + b.verdict(t, third, ended) + + // §5: the trunk moves; the first verdict is carried by its digests, nothing runs. + tests = b.fake.count("mesh-build-go.build_go_test") + const moved = "abababababababababababababababababababab" + b.setTrunk(t, map[string]string{repo: moved}) + c := b.verdict(t, first, func(v delivery.Verdict) bool { return ended(v) && v.Trunk[repo] == moved }) + if c.State != delivery.VerdictPass || c.CarriedFrom[repo] != trunk || c.Levels[delivery.LevelUnit].Run != 0 || c.Levels[delivery.LevelIntegration].Run != 0 { + t.Fatalf("the carried verdict = %+v, want a pass carried from %s with no test run", c, trunk[:12]) + } + if got := b.fake.count("mesh-build-go.build_go_test"); got != tests { + t.Errorf("build_go_test called %d times on the carry, was %d: a carry of unchanged digests runs nothing", got, tests) + } + if o := b.owed(t, 7, head1, "success"); !strings.HasPrefix(o.Text, "pass 111111111111 on abababababab | carried from aaaaaaaaaaaa") { + t.Errorf("the carried status says %q", o.Text) + } } func keptCount(t *testing.T, b *bed) int {