Skip to content
quarry Artifact [fc3fec86e8]
Login

Artifact [fc3fec86e8]

Artifact fc3fec86e8210d076093203992e8182a3b5d752c4ea40d6339321cc6afeeca97:


package events

import (
	"testing"
	"time"

	"craftdesign.group/quarry/internal/evt"
)

// Repository names may contain dots, so a.b's subjects begin with a's.
// Nothing read or watched for a may carry a.b's: a.b may be private
// where a is public, and its actors, summaries, readers and even the
// timing of its pushes are its own.

func TestTheEventLogShowsOnlyThatRepository(t *testing.T) {
	s := testServer(t)
	for _, repo := range []string{"a", "a.b"} {
		if err := s.Raise(evt.TicketClosed, repo, map[string]any{"actor": "in-" + repo}); err != nil {
			t.Fatal(err)
		}
	}
	got, err := s.Recent("a", 10)
	if err != nil {
		t.Fatal(err)
	}
	if len(got) != 1 || got[0].Repo != "a" || got[0].Actor != "in-a" {
		t.Errorf("a's event log is %+v, want only a's one event", got)
	}
}

func TestATallyFamilyCountsOnlyThatRepository(t *testing.T) {
	s := testServer(t)
	for _, c := range [][2]string{
		{"a", "clone.auth.ann"},
		{"a", "clone.client.zit.v1"},
		// a.clone.auth's clone total, and a.clone.client's reader bob:
		// each continues one of a's families by a token or two.
		{"a.clone.auth", "clone"},
		{"a.clone.client", "clone.auth.bob"},
		{"a.x", "clone.auth.eve"},
	} {
		if err := s.Count(c[0], c[1], 1); err != nil {
			t.Fatal(err)
		}
	}
	auth, err := s.Totals("a", "clone.auth")
	if err != nil {
		t.Fatal(err)
	}
	if len(auth) != 1 || auth["ann"] != 1 {
		t.Errorf("a's readers are %v, want only ann", auth)
	}
	clients, err := s.Totals("a", "clone.client")
	if err != nil {
		t.Fatal(err)
	}
	if len(clients) != 1 || clients["zit.v1"] != 1 {
		t.Errorf("a's clients are %v, want only zit.v1", clients)
	}
}

// ticked reports whether ch ticks within a short wait.
func ticked(ch <-chan struct{}) bool {
	select {
	case <-ch:
		return true
	case <-time.After(300 * time.Millisecond):
		return false
	}
}

func TestALiveWatchWakesOnlyForThatRepository(t *testing.T) {
	s := testServer(t)
	ticks, cancel := s.Watch("a")
	defer cancel()
	if err := s.nc.Publish("zit.evt.a.b.artifact", nil); err != nil {
		t.Fatal(err)
	}
	if ticked(ticks) {
		t.Error("a's watch ticked for a push to a.b")
	}
	if err := s.nc.Publish("zit.evt.a.artifact", nil); err != nil {
		t.Fatal(err)
	}
	if !ticked(ticks) {
		t.Error("a's watch never ticked for a's own push")
	}
	every, stop := s.Watch("*")
	defer stop()
	if err := s.nc.Publish("zit.evt.a.b.artifact", nil); err != nil {
		t.Fatal(err)
	}
	if !ticked(every) {
		t.Error("the watch on every repository missed a dotted one")
	}
}

func TestANounWatchWakesOnlyForThatRepository(t *testing.T) {
	s := testServer(t)
	ticks, cancel := s.WatchNoun("a", "ci")
	defer cancel()
	// a.ci's ci.started is quarry.evt.a.ci.ci.started.
	if err := s.Raise(evt.CIStarted, "a.ci", nil); err != nil {
		t.Fatal(err)
	}
	if ticked(ticks) {
		t.Error("a's ci watch ticked for a.ci's run")
	}
}