diff --git a/modules/mesh-delivery/cmd/mesh-delivery/bus_test.go b/modules/mesh-delivery/cmd/mesh-delivery/bus_test.go index 34c5b329..87d37458 100644 --- a/modules/mesh-delivery/cmd/mesh-delivery/bus_test.go +++ b/modules/mesh-delivery/cmd/mesh-delivery/bus_test.go @@ -107,7 +107,9 @@ type runtime struct { // the asks the operator was asked, and the controller's walks and the forge's open pull requests as the test plays // them. operatorAsks []asks.Ask - openPulls []OpenPull + // operatorCancels are the ids of the asks taken back from the router, in order (issue 1079). + operatorCancels []string + openPulls []OpenPull } type askedOfMesh struct { @@ -268,6 +270,17 @@ func (r *runtime) answer(m rpcMessage) { r.operatorAsks = append(r.operatorAsks, a) r.mu.Unlock() } + if strings.Contains(p.Subject, ".accept.cancel.") { + var c struct { + ID string `json:"id"` + } + if err := json.Unmarshal(p.Body, &c); err != nil { + return nil, err + } + r.mu.Lock() + r.operatorCancels = append(r.operatorCancels, c.ID) + r.mu.Unlock() + } return map[string]any{}, nil case "mesh/seat.record": return nil, nil @@ -416,7 +429,7 @@ func TestAPassingVerdictAsksTheApproveAndItsApproveMergesWithinSecondsOverARealB announced := pr("novox/app", 7, head, "fix/x", "src/a.go") announced.BaseSHA = "t1t1t1t1t1t1" announced.Title = "Fix the apostrophe (issue 975)" - announced.Body = "Reviewed-by: lead@shanks at " + head + announced.Body = "The description, with no review line yet." b.publish(t, "mesh.mod.gitea.event.pull.updated", announced) passed := b.publish(t, "mesh.seat."+ControllerSeat+".event.checked", judgedAt("novox/app", 7, head, "pass", "t1t1t1t1t1t1")) @@ -430,10 +443,29 @@ func TestAPassingVerdictAsksTheApproveAndItsApproveMergesWithinSecondsOverARealB ask := rt.operatorAsks[0] asked := time.Now() rt.mu.Unlock() - if !strings.Contains(ask.Explanation, "reviewed by lead") { - t.Fatalf("the ask does not name the reviewer: %s", ask.Explanation) + if !strings.Contains(ask.Explanation, "not reviewed at this head") { + t.Fatalf("the first ask does not say the record is missing: %s", ask.Explanation) } t.Logf("the operator was asked %s after the verdict's event", asked.Sub(passed)) + // The description is edited to add the review record (issue 1079): the forge module's edit event carries it. The unanswered + // ask is withdrawn from the router and asked again, once, with the record read; nothing else is asked of the mesh. + first := ask + b.publish(t, "mesh.mod.gitea.event.forge.pull-request.edited", map[string]any{"owner": "novox", "repo": "app", "number": 7, + "title": announced.Title, "head_sha": head, "base": "main", "body": "Reviewed-by: lead@shanks at " + head}) + rt.until("the first ask to be withdrawn and the operator asked again", 5*time.Second, func() bool { + rt.mu.Lock() + defer rt.mu.Unlock() + return len(rt.operatorCancels) >= 1 && len(rt.operatorAsks) >= 2 + }) + rt.mu.Lock() + if len(rt.operatorCancels) != 1 || rt.operatorCancels[0] != first.ID || len(rt.operatorAsks) != 2 { + t.Fatalf("withdrawn %v, asked %d; wanted the first ask %s withdrawn once and exactly one new ask", rt.operatorCancels, len(rt.operatorAsks), first.ID) + } + ask = rt.operatorAsks[1] + rt.mu.Unlock() + if ask.ID == first.ID || !strings.Contains(ask.Explanation, "reviewed by lead on shanks") || strings.Contains(ask.Explanation, "not reviewed") { + t.Fatalf("the new ask is not a fresh one naming the reviewer: %s %s", ask.ID, ask.Explanation) + } if len(rt.asksOf("gitea.gitea_merge_pull_request")) != 0 { t.Fatalf("merged before the Approve") }