114 lines
4.6 KiB
Go
114 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/asks"
|
|
sdk "git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// 1280 (novox/hq ADR 0556 clause 5): settle writes one ask for several deliveries held for a merge without a passing check and
|
|
// moves none of them; it refuses, asking nothing, a delivery held for another reason and one not held, naming why; the
|
|
// operator's Leave keeps them held, and Settle, asked again under a new asking, moves each to merged with the operator's words.
|
|
func TestSettleAsksTheOperatorOnceAndMovesOnlyOnTheAnswer(t *testing.T) {
|
|
w := newWorld(t)
|
|
w.op.auto = false
|
|
merged := w.now.Add(-time.Hour)
|
|
put := func(id string, state State, why string) *Delivery {
|
|
repo, commit, _ := strings.Cut(id, "@")
|
|
d := &Delivery{ID: id, Repository: repo, Commit: commit, Number: len(id), Title: "a fix", State: state, Since: merged,
|
|
MergedAs: "m" + commit, MergedAt: merged, HeldWhy: why}
|
|
w.h.mu.Lock()
|
|
w.h.keep(d)
|
|
w.h.mu.Unlock()
|
|
return d
|
|
}
|
|
a := put("novox/web@aaaaaaaaaaaa", Held, HeldUnchecked)
|
|
b := put("novox/sdk@bbbbbbbbbbbb", Held, HeldUnchecked)
|
|
put("novox/web@cccccccccccc", Held, "a conflict on the trunk")
|
|
put("novox/web@dddddddddddd", Merged, "")
|
|
for ids, words := range map[string]string{
|
|
"novox/web@aaaaaaaaaaaa novox/web@cccccccccccc": "held for another reason",
|
|
"novox/web@aaaaaaaaaaaa novox/web@dddddddddddd": "not held",
|
|
"novox/web@aaaaaaaaaaaa novox/web@eeeeeeeeeeee": "no such delivery",
|
|
} {
|
|
if _, err := w.h.Settle(strings.Fields(ids), "on every machine since 10-25", aPerson); err == nil || !strings.Contains(err.Error(), words) {
|
|
t.Errorf("settle %s: %v, want refused naming %q", ids, err, words)
|
|
}
|
|
}
|
|
if _, err := w.h.Settle([]string{a.ID}, " ", aPerson); err == nil {
|
|
t.Error("a settle with no why was asked")
|
|
}
|
|
if w.op.count() != 0 {
|
|
t.Fatalf("a refused settle asked the operator: %d asks", w.op.count())
|
|
}
|
|
out, err := w.h.Settle([]string{b.ID, a.ID}, "on every machine since 10-25", aPerson)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
key, _ := out["asked"].(string)
|
|
if open := w.op.open(); len(open) != 1 || open[0] != key || w.op.count() != 1 {
|
|
t.Fatalf("asks open %v (asked %d), want the one key %s", open, w.op.count(), key)
|
|
}
|
|
ask := w.op.ask(key)
|
|
heads := map[string]string{a.ID: a.Commit, b.ID: b.Commit}
|
|
group := sdk.SettleGroup([]string{a.ID, b.ID})
|
|
for _, o := range ask.Options {
|
|
if want, _ := asks.ActDigest(settleAct(group, ask.ID, o.ID, heads)); o.Binds != want {
|
|
t.Errorf("the option %s binds %s, not mesh-delivery.settle of these heads", o.ID, o.Binds)
|
|
}
|
|
}
|
|
w.h.hearAsks()
|
|
if a.State != Held || b.State != Held {
|
|
t.Fatalf("moved before an answer: %s, %s", a.State, b.State)
|
|
}
|
|
w.op.answer(key, OptionLeave)
|
|
w.h.hearAsks()
|
|
if a.State != Held || a.Settle == nil || a.Settle.Answer != OptionLeave {
|
|
t.Fatalf("after Leave: %s %+v", a.State, a.Settle)
|
|
}
|
|
// Asked again: a new asking of the same key, under its own id.
|
|
if _, err := w.h.Settle([]string{a.ID, b.ID}, "asked again", aPerson); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if again := w.op.ask(key); again.ID == ask.ID || a.Settle.Asking != 2 {
|
|
t.Fatalf("asked again under %s (asking %d), want a new id", again.ID, a.Settle.Asking)
|
|
}
|
|
// An answer under a settle key no delivery waits for moves nothing.
|
|
other, _ := sdk.MergeAskKey(sdk.SettleGroup([]string{"novox/web@ffffffffffff"}), []sdk.Head{{Repository: "novox/web", Number: 1, Head: "ffffffffffff"}})
|
|
w.h.mu.Lock()
|
|
w.h.settled(other, sdk.Answer{Option: OptionSettle, Warrant: "x@now", Words: "chose Settle"})
|
|
w.h.mu.Unlock()
|
|
if a.State != Held || b.State != Held || !strings.Contains(w.logbuf.String(), "covers no delivery") {
|
|
t.Fatalf("an answer for other ids moved %s, %s", a.State, b.State)
|
|
}
|
|
w.op.answer(key, OptionSettle)
|
|
w.h.hearAsks()
|
|
w.h.mu.Lock()
|
|
cancels := len(w.h.cancels)
|
|
w.h.mu.Unlock()
|
|
if cancels == 0 {
|
|
t.Error("the answered settle ask is not taken away")
|
|
}
|
|
for _, d := range []*Delivery{a, b} {
|
|
last := d.Transitions[len(d.Transitions)-1]
|
|
if d.State != Merged || last.Event != EvSettled || last.By != "the operator" || !strings.Contains(last.Why, "chose Settle") {
|
|
t.Errorf("%s after Settle: %s, %+v", d.ID, d.State, last)
|
|
}
|
|
}
|
|
// A settle ask nobody answers within its bound is taken away; its delivery stays held.
|
|
c := put("novox/web@999999999999", Held, HeldUnchecked)
|
|
if _, err := w.h.Settle([]string{c.ID}, "once more", aPerson); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
w.later(AskLasts + time.Minute)
|
|
w.h.mu.Lock()
|
|
w.h.endStaleSettles()
|
|
w.h.mu.Unlock()
|
|
if c.State != Held || c.Settle.Answer != "lapsed" {
|
|
t.Errorf("a lapsed settle ask: %s %+v", c.State, c.Settle)
|
|
}
|
|
}
|