Skip to content
quarry Artifact [9f8a0361bd]
Login

Artifact [9f8a0361bd]

Artifact 9f8a0361bdf2b8adcc1f7b47d5c77461e35092f2a7c2b76bcb76da2e84b5cbca:


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")
}