package events
import (
"testing"
"github.com/nats-io/nats.go"
"craftdesign.group/quarry/internal/evt"
)
// ForgetRepo takes a deleted repository's attention events, its event
// log and its traffic tallies, so a repository created later under the
// name inherits none of them — and a neighbour whose name merely starts
// with the deleted one's keeps all of its own (quarry#294).
func TestForgetRepoTakesOnlyThatRepository(t *testing.T) {
s := testServer(t)
const gone, dotted, kept = "gone", "gone.x", "kept"
for _, repo := range []string{gone, dotted, kept} {
for _, who := range []string{"ann", "bob"} {
if _, err := s.Attend(who, AttentionEvent{Kind: "mention", Repo: repo, Link: "/r/" + repo}); err != nil {
t.Fatal(err)
}
}
if err := s.Raise(evt.TicketClosed, repo, map[string]any{"repo": repo}); err != nil {
t.Fatal(err)
}
for _, name := range []string{"clone", "clone.auth.ann", "clone.client.zit.v1", "fetch.anon"} {
if err := s.Count(repo, name, 1); err != nil {
t.Fatal(err)
}
}
}
if err := s.ForgetRepo(gone); err != nil {
t.Fatal(err)
}
for _, who := range []string{"ann", "bob"} {
evs, err := s.RecentAttention(who, 50)
if err != nil {
t.Fatal(err)
}
held := map[string]int{}
for _, e := range evs {
held[e.Repo]++
}
if held[gone] != 0 {
t.Errorf("%s still holds %d attention events for the deleted repository", who, held[gone])
}
if held[dotted] != 1 || held[kept] != 1 {
t.Errorf("%s lost a neighbour's attention events: %v", who, held)
}
}
logged, err := s.Recent(gone, 50)
if err != nil {
t.Fatal(err)
}
for _, l := range logged {
if l.Repo == gone {
t.Errorf("the deleted repository's event log survived: %+v", l)
}
}
for _, repo := range []string{dotted, kept} {
if l, err := s.Recent(repo, 50); err != nil || len(l) == 0 {
t.Errorf("%s's event log went with %s's: %d, %v", repo, gone, len(l), err)
}
}
for _, fam := range []string{"clone", "fetch"} {
if tot, err := s.Totals(gone, fam); err != nil || len(tot) != 0 {
t.Errorf("%s's %s tallies survived: %v, %v", gone, fam, tot, err)
}
}
if n, _ := s.Total(gone, "clone"); n != 0 {
t.Errorf("%s's clone total survived: %d", gone, n)
}
for _, repo := range []string{dotted, kept} {
if n, _ := s.Total(repo, "clone"); n != 1 {
t.Errorf("%s's clone total = %d, want 1", repo, n)
}
if tot, _ := s.Totals(repo, "clone"); tot["auth.ann"] != 1 {
t.Errorf("%s's clone tallies went too: %v", repo, tot)
}
}
}
// A scan that gets short batches off a large stream still finds every
// message: it ends when the consumer has nothing pending, not on the
// first batch under the size asked for. Here every fetch delivers one
// message whatever it asked for.
func TestForgetRepoSurvivesShortBatches(t *testing.T) {
s := testServer(t)
old := forgetFetch
forgetFetch = func(sub *nats.Subscription, _ int) ([]*nats.Msg, error) { return old(sub, 1) }
t.Cleanup(func() { forgetFetch = old })
for i := 0; i < 20; i++ {
if _, err := s.Attend("ann", AttentionEvent{Kind: "mention", Repo: "gone", Link: "/r/gone"}); err != nil {
t.Fatal(err)
}
}
if err := s.ForgetRepo("gone"); err != nil {
t.Fatal(err)
}
evs, err := s.RecentAttention("ann", 50)
if err != nil {
t.Fatal(err)
}
if len(evs) != 0 {
t.Errorf("%d events survived", len(evs))
}
}