Files
mesh-catalog/modules/messenger/cmd/messenger/replaced_test.go
T
jschoubben b7d9590fdc
mesh/merge-gate head b7d9590fdc95 merged into trunk e1c8965ddbf1 — pass: builds messenger, telegram → novox; no bus step; every machine composes with the c…
mesh/repo-check head b7d9590fdc95 merged into trunk e1c8965ddbf1 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
An answered ask keeps its question whole, its answer below it (issue 714)
Issue 372's fix with issue 639's one line edited an answered ask down to
'You chose X at HH:MM · headline', so the operator could not read back what
they approved. The headline stays the title, the summary, points, link and
Details stay the body, and how it ended and who acts on it become the note.
Telegram cuts the body from its end past 4096 characters, never the title or
the note.
2026-10-14 20:06:24 +02:00

112 lines
4.0 KiB
Go

package main
import (
"strings"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/asks"
)
// openAskRecords are the records still open that show an ask as their own message.
func openAskRecords(h *Holder) []string {
h.mu.Lock()
defer h.mu.Unlock()
var out []string
for k, r := range h.open {
if r.Origin == "ask" && r.Cleared.IsZero() {
out = append(out, k)
}
}
return out
}
// Issue 548: an ask replaced by a newer one about the same thing kept its own message open for good, its
// buttons on the phone answering nothing. Two asks with the same About from one asker leave exactly one open
// record, and the older one's message says it was replaced, its buttons gone, on every channel that showed it.
func TestAReplacedAsksMessageEndsWithIt(t *testing.T) {
h, tg, dt, c, store, _ := newRouter(t)
link(h, store, c, "42", c.now().Add(-2*time.Hour))
a := ackAsk(c, "d-1")
a.About = "delivery.hq"
submit(t, h, "mesh-delivery", a)
settle(h, c)
if len(tg.sends) != 1 || len(dt.sends) != 1 {
t.Fatalf("the first ask was not shown: telegram %d, desktop %d", len(tg.sends), len(dt.sends))
}
b := ackAsk(c, "d-2")
b.About = "delivery.hq"
b.Headline = "Delivery of hq held, asked again"
submit(t, h, "mesh-delivery", b)
settle(h, c)
if got := openAskRecords(h); len(got) != 1 || got[0] != "ask.mesh-delivery.d-2" {
t.Fatalf("open ask records: %v; want only the newer ask's", got)
}
for _, ch := range []*fakeChannel{tg, dt} {
id := map[string]string{"telegram": "1", "desktop": "g14=1"}[ch.name]
m, edited := ch.edits[id]
for _, r := range ch.replaced {
if r.id == id {
m, edited = r.m, true
}
}
if !edited || len(m.Actions) != 0 || !strings.HasPrefix(m.Note, "Replaced by a newer question") {
t.Errorf("%s: the replaced ask's message still stands: edited %v, %q %v", ch.name, edited, m.Text(), labelsOf(m))
}
}
if store.asks["mesh-delivery.d-1"].State != string(asks.OutcomeReplaced) {
t.Errorf("the older ask was not replaced: %s", store.asks["mesh-delivery.d-1"].State)
}
}
// The leftover of issue 548: a record from before the fix whose ask already ended keeps its message open. The
// next tick ends it, as the ask's end would have.
func TestAnAsksMessageLeftOpenAfterItsAskEndedIsEndedOnTheNextTick(t *testing.T) {
h, tg, _, c, store, _ := newRouter(t)
link(h, store, c, "42", c.now().Add(-2*time.Hour))
a := ackAsk(c, "d-1")
a.About = "delivery.hq"
submit(t, h, "mesh-delivery", a)
settle(h, c)
// Ended as replaced the way the router did before the fix: the ask's record only, its message untouched.
key := "mesh-delivery.d-1"
rec := store.asks[key]
rec.State, rec.Closed, rec.Told = string(asks.OutcomeReplaced), c.now(), true
rec.Warrant = &asks.Warrant{Ask: "d-1", Asker: "mesh-delivery", About: a.About, Outcome: asks.OutcomeReplaced,
Words: "a newer ask about the same thing replaced it", At: c.now()}
store.asks[key] = rec
h.keepAsk(key, rec, 99)
if got := openAskRecords(h); len(got) != 1 {
t.Fatalf("the leftover is not set up: %v", got)
}
c.pass(time.Minute)
stand(h, c)
h.Tick()
h.Flush()
if got := openAskRecords(h); len(got) != 0 {
t.Fatalf("the message of an ended ask is still open: %v", got)
}
if m, ok := tg.edits["1"]; !ok || len(m.Actions) != 0 || !strings.HasPrefix(m.Note, "Replaced by a newer question") {
t.Errorf("the leftover's copy was not ended: %v %q %v", ok, m.Text(), labelsOf(m))
}
}
// The review of PR 238: what a walk owed of a record is dropped when the record clears, so a router that
// restarts never says a held message of something that already ended.
func TestAClearedRecordOwesNothing(t *testing.T) {
h, _, _, c, st := newHolder(t)
k := cond("machine.shanks.units", Warning, "2 failed services on shanks")
k.Raised = c.now()
h.Condition(EventRaised, k)
h.mu.Lock()
h.open[k.Key].Owed = "raised"
h.mu.Unlock()
h.cleared(k.Key, false)
if r := h.open[k.Key]; r.Owed != "" {
t.Errorf("a cleared record still owes %q", r.Owed)
}
if r := st.recs[k.Key]; r.Owed != "" {
t.Errorf("a cleared record still owes %q in the state", r.Owed)
}
}