package events
import (
"testing"
"time"
"craftdesign.group/quarry/internal/evt"
)
func nextVocab(t *testing.T, ch <-chan VocabEvent) VocabEvent {
t.Helper()
select {
case e, open := <-ch:
if !open {
t.Fatal("FAIL: tail closed early")
}
return e
case <-time.After(5 * time.Second):
t.Fatal("FAIL: tail delivered nothing")
}
return VocabEvent{}
}
// A listener that resumes after an event gets every later event, with
// its kind, repository, payload and position; one that asks for one
// repository gets only that one's, even when another's name extends it.
func TestTailVocabResumesAndFiltersByRepository(t *testing.T) {
s := testServer(t)
raise := func(kind evt.Kind, repo string) {
t.Helper()
if err := s.Raise(kind, repo, map[string]any{"status": "pass"}); err != nil {
t.Fatal(err)
}
}
raise(evt.LandingOpened, "alpha")
// Everything after the first event, across repositories.
raise(evt.CICompleted, "alpha")
raise(evt.CICompleted, "alpha.b")
all, stop := s.TailVocab("", 1)
defer stop()
a := nextVocab(t, all)
b := nextVocab(t, all)
if a.Kind != string(evt.CICompleted) || a.Repo != "alpha" || a.Seq != 2 || a.Payload["status"] != "pass" {
t.Fatalf("FAIL: first resumed event = %+v", a)
}
if b.Repo != "alpha.b" || b.Seq != 3 || b.At.IsZero() {
t.Fatalf("FAIL: second resumed event = %+v", b)
}
// One repository's: alpha.b is not alpha's.
one, stop1 := s.TailVocab("alpha", 1)
defer stop1()
if e := nextVocab(t, one); e.Repo != "alpha" || e.Seq != 2 {
t.Fatalf("FAIL: alpha's tail delivered %+v", e)
}
raise(evt.MirrorFailed, "alpha")
if e := nextVocab(t, one); e.Repo != "alpha" || e.Kind != string(evt.MirrorFailed) {
t.Fatalf("FAIL: alpha's tail delivered %+v, want its mirror.failed and not alpha.b's", e)
}
t.Log("ok")
}
// A resume point older than the repository's first retained event is
// said out loud before the replay.
func TestTailVocabSignalsGap(t *testing.T) {
s := testServer(t)
for i := 0; i < 3; i++ {
if err := s.Raise(evt.CICompleted, "other", nil); err != nil {
t.Fatal(err)
}
}
if err := s.Raise(evt.LandingAccepted, "alpha", nil); err != nil {
t.Fatal(err)
}
ch, cancel := s.TailVocab("alpha", 1)
defer cancel()
g := nextVocab(t, ch)
if !g.Gap || g.From != 1 || g.Seq != 4 {
t.Fatalf("FAIL: first delivery = %+v, want a gap from 1 to 4", g)
}
if e := nextVocab(t, ch); e.Gap || e.Seq != 4 || e.Kind != string(evt.LandingAccepted) {
t.Fatalf("FAIL: replay after the gap = %+v", e)
}
t.Log("ok")
}