Files
mesh-catalog/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/timers_test.go
T
jschoubben 5ff337e0dc Gate keeps the merge's six states and asks the controller nothing (issue 1946, R6-C1, C2, C4)
Release 6 deletes the plans: the walk half of the holder, the controller port, the carry-over of the former module and the verbs times, what-if, release, stop and retire-history go; the table holds proposed, ready, rejected, merged, held and closed; the delivery's status and view name the source revision the merge moved.
2026-10-24 16:26:36 +02:00

91 lines
3.3 KiB
Go

package main
import (
"errors"
"strings"
"testing"
"time"
)
// **A step that waits on the clock says when it is looked at again** (novox/hq ADR 0406 §1, issue 975): there is no
// tick to find it, so each grace, bound and retry is registered (lookAt) when a look meets it, and the one timer fires
// a look for the earliest. A look that meets nothing waiting registers nothing.
func (w *world) wantedAt() (time.Time, string) {
w.h.wanted.mu.Lock()
defer w.h.wanted.mu.Unlock()
return w.h.wanted.at, w.h.wanted.step
}
func TestALookThatMeetsNothingWaitingOnTheClockWantsNoOtherLook(t *testing.T) {
w := newWorld(t)
w.h.PullUpdated(pr("novox/app", 7, readyHead, "feat/x", "src/a.go"))
w.h.Checked(judgedAt("novox/app", 7, readyHead, "pass", "t1t1t1t1t1t1"))
w.h.React()
if at, step := w.wantedAt(); !at.IsZero() {
t.Fatalf("a look with nothing waiting on the clock wants another at %s for %q", at, step)
}
}
func TestAProposedDeliveryWhoseHeadHoldsAPassingMeshCheckAtTheForgeAdoptsItAndAsksNoCheck(t *testing.T) {
w := newWorld(t)
w.h.PullUpdated(pr("novox/app", 7, readyHead, "feat/x", "src/a.go"))
id := IDOf("novox/app", readyHead)
op := openPull("novox/app", 7, readyHead)
op.Required = []string{ctxCheck}
op.Checks = map[string]HeadCheck{ctxCheck: {State: "success", Description: "pass " + readyHead[:12] + " | the checker's"}}
w.forge.open = []OpenPull{op}
w.h.React()
w.settleAll()
if d := w.delivery(id); d.Check == nil || !d.Check.Passes() || d.State != Ready {
t.Fatalf("the standing verdict was not adopted: %+v (%s)", d.Check, d.State)
}
}
// 1144/AC3: no timer asks a refused merge again; only an event does (here, mergeAgainNow called directly).
func TestAMergeTheForgeRefusedIsAskedAgainOnlyOnAnEventWithNoTimer(t *testing.T) {
w := newWorld(t)
w.h.PullUpdated(pr("novox/app", 7, readyHead, "feat/x", "src/a.go"))
w.h.Checked(judgedAt("novox/app", 7, readyHead, "pass", "t1t1t1t1t1t1"))
w.forge.refuse = errors.New("the forge refused gitea_merge_pull_request: not mergeable yet")
w.forge.open = []OpenPull{openPull("novox/app", 7, readyHead)}
w.h.wantForge()
w.settleAll()
if len(w.forge.merges) != 1 {
t.Fatalf("merges %v", w.forge.merges)
}
if at, step := w.wantedAt(); !at.IsZero() {
t.Fatalf("the refused merge wants a timer at %s for %q; it waits for the next event", at, step)
}
w.forge.refuse = nil
w.settleAll()
if len(w.forge.merges) != 1 {
t.Fatalf("asked again at a look with no event: %v", w.forge.merges)
}
again := w.delivery(IDOf("novox/app", readyHead))
w.h.mu.Lock()
w.h.mergeAgainNow(again)
w.h.mu.Unlock()
w.settleAll()
if len(w.forge.merges) != 2 || w.delivery(IDOf("novox/app", readyHead)).Ready.Merged == nil {
t.Fatalf("the refused merge was not asked again at the timer: %v", w.forge.merges)
}
}
func TestAnEffectTheBusCouldNotTakeIsTriedAgainAtItsTimeByTheTimerAlone(t *testing.T) {
w := newWorld(t)
w.owed.down = true
w.h.PullUpdated(pr("novox/app", 7, readyHead, "feat/x", "src/a.go"))
w.h.React()
at, step := w.wantedAt()
if at.IsZero() || !strings.Contains(step, "owed") || at.After(w.now.Add(retryFirst)) {
t.Fatalf("the look wanted at %s for %q; wanted within %s for the owed effect", at, step, retryFirst)
}
w.owed.down = false
w.later(retryFirst + time.Second)
w.h.React()
if len(w.forge.notes) == 0 {
t.Fatal("the owed effect was not tried again at its time")
}
}