144 lines
5.1 KiB
Go
144 lines
5.1 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// **A reviewer's word marks the pull request ready in the order the forge counts** (novox/hq issue 913): the label,
|
|
// then the comment "ready at <full sha>". Written the other way round the mark's head is empty (issue 873).
|
|
|
|
const fullHead = "3333333333333333333333333333333333333333"
|
|
|
|
// readyDelivery is a delivery of a pull request whose head is fullHead, its check passed, and the forge's open pull.
|
|
func readyDelivery(t *testing.T, w *world) string {
|
|
t.Helper()
|
|
w.h.PullUpdated(pr("novox/app", 7, fullHead, "feat/x", "src/a.go"))
|
|
w.h.Checked(verdict("novox/app", 7, fullHead, "pass"))
|
|
w.settleAll()
|
|
w.forge.open = []OpenPull{{Owner: "novox", Repo: "app", Number: 7, Base: "main", HeadSHA: fullHead}}
|
|
return IDOf("novox/app", fullHead)
|
|
}
|
|
|
|
func TestMarkReadyLabelsThenCommentsTheFullHead(t *testing.T) {
|
|
w := newWorld(t)
|
|
id := readyDelivery(t, w)
|
|
answer, err := w.h.MarkReady(id, "fix-913@shanks", "the change is right")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(w.forge.calls) != 2 || w.forge.calls[0] != "label novox/app#7 mesh/ready" {
|
|
t.Fatalf("the forge was asked %q; wanted the label first", w.forge.calls)
|
|
}
|
|
c := strings.TrimPrefix(w.forge.calls[1], "comment ")
|
|
if first, _, _ := strings.Cut(c, "\n"); first != "ready at "+fullHead || !strings.Contains(c, "\n\nReviewed by fix-913@shanks: the change is right.") ||
|
|
!strings.Contains(c, "mark-ready") {
|
|
t.Fatalf("the comment is %q", c)
|
|
}
|
|
d := w.delivery(id)
|
|
if d.Ready == nil || d.Ready.Head != fullHead || d.Ready.By != "fix-913@shanks" || d.Ready.Seen.IsZero() {
|
|
t.Fatalf("the mark is not kept: %+v", d.Ready)
|
|
}
|
|
if !strings.Contains(answer, "marked") {
|
|
t.Fatalf("answer %q", answer)
|
|
}
|
|
}
|
|
|
|
func TestMarkReadyRefusesAMovedHeadAndAsksTheForgeNothing(t *testing.T) {
|
|
w := newWorld(t)
|
|
id := readyDelivery(t, w)
|
|
w.forge.open[0].HeadSHA = pushed
|
|
_, err := w.h.MarkReady(id, "fix-913@shanks", "ok")
|
|
if err == nil || !strings.Contains(err.Error(), "the head is now "+pushed) {
|
|
t.Fatalf("a moved head: %v", err)
|
|
}
|
|
if len(w.forge.calls) != 0 {
|
|
t.Fatalf("the forge was asked %q", w.forge.calls)
|
|
}
|
|
}
|
|
|
|
func TestMarkReadyRefusesAnUnknownAndAFinalDelivery(t *testing.T) {
|
|
w := newWorld(t)
|
|
id := readyDelivery(t, w)
|
|
if _, err := w.h.MarkReady("novox/app@nothing", "a@b", "ok"); err == nil || !strings.Contains(err.Error(), "deliveries") {
|
|
t.Fatalf("unknown id: %v", err)
|
|
}
|
|
w.h.mu.Lock()
|
|
w.h.deliveries[id].State = Stopped
|
|
w.h.mu.Unlock()
|
|
if _, err := w.h.MarkReady(id, "a@b", "ok"); err == nil {
|
|
t.Fatal("a final delivery was marked")
|
|
}
|
|
if len(w.forge.calls) != 0 {
|
|
t.Fatalf("the forge was asked %q", w.forge.calls)
|
|
}
|
|
}
|
|
|
|
func TestMarkReadyWritesNoCommentWhenTheLabelFails(t *testing.T) {
|
|
w := newWorld(t)
|
|
id := readyDelivery(t, w)
|
|
w.forge.labelErr = errors.New("the forge refused gitea_api: no such label")
|
|
_, err := w.h.MarkReady(id, "a@b", "ok")
|
|
if err == nil || !strings.Contains(err.Error(), "no such label") {
|
|
t.Fatalf("label failure: %v", err)
|
|
}
|
|
if len(w.forge.comments) != 0 {
|
|
t.Fatalf("commented: %v", w.forge.comments)
|
|
}
|
|
if w.delivery(id).Ready != nil {
|
|
t.Fatal("marked though the label failed")
|
|
}
|
|
}
|
|
|
|
func TestClearMarkWithAnEmptyHeadSaysWhatWasWrongOnceItStayedEmpty(t *testing.T) {
|
|
w := newWorld(t)
|
|
w.h.PullUpdated(pr("novox/app", 7, readyHead, "feat/x", "src/a.go"))
|
|
w.forge.open = []OpenPull{markedPull("novox/app", 7, readyHead, "")}
|
|
w.h.SeeOpenPulls()
|
|
w.settleAll()
|
|
if len(w.forge.comments) != 0 || len(w.forge.unlabels) != 0 {
|
|
t.Fatalf("an empty-head mark seen once was cleared: %v", w.forge.comments)
|
|
}
|
|
w.later(markGrace + time.Second)
|
|
w.h.SeeOpenPulls()
|
|
w.settleAll()
|
|
if len(w.forge.comments) != 1 || !strings.Contains(w.forge.comments[0], "no \"ready at\" comment by a listed account") ||
|
|
!strings.Contains(w.forge.comments[0], "the head is now "+readyHead) ||
|
|
!strings.Contains(w.forge.comments[0], "mesh-delivery.mark-ready") || strings.Contains(w.forge.comments[0], "pushed after it") {
|
|
t.Fatalf("comments: %v", w.forge.comments)
|
|
}
|
|
}
|
|
|
|
func TestAMarkReadyJustMadeIsNotClearedByAReadThatPredatesItsComment(t *testing.T) {
|
|
w := newWorld(t)
|
|
id := readyDelivery(t, w)
|
|
if _, err := w.h.MarkReady(id, "a@b", "ok"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
w.later(markGrace + time.Second) // the label alone was read long enough ago to count as stale...
|
|
w.forge.open = []OpenPull{markedPull("novox/app", 7, fullHead, "")}
|
|
w.h.SeeOpenPulls()
|
|
w.h.mu.Lock()
|
|
w.h.deliveries[id].Ready.Seen = w.now // ...but the mark was made just now
|
|
w.h.marks["novox/app#7"].firstEmpty = w.now.Add(-2 * markGrace)
|
|
w.h.mu.Unlock()
|
|
before := len(w.forge.comments)
|
|
w.settleAll()
|
|
if len(w.forge.unlabels) != 0 || len(w.forge.comments) != before {
|
|
t.Fatalf("a mark just made was cleared: %v %v", w.forge.unlabels, w.forge.comments)
|
|
}
|
|
}
|
|
|
|
func TestClearMarkWithAnOlderHeadKeepsTheOldWording(t *testing.T) {
|
|
w := newWorld(t)
|
|
w.h.PullUpdated(pr("novox/app", 7, pushed, "feat/x", "src/a.go"))
|
|
w.forge.open = []OpenPull{markedPull("novox/app", 7, pushed, readyHead)}
|
|
w.h.SeeOpenPulls()
|
|
w.settleAll()
|
|
if len(w.forge.comments) != 1 || !strings.Contains(w.forge.comments[0], "pushed after it") {
|
|
t.Fatalf("comments: %v", w.forge.comments)
|
|
}
|
|
}
|