Skip to content
quarry Artifact [aa85a0e921]
Login

Artifact [aa85a0e921]

Artifact aa85a0e92196351b278332b4855f8f37839c6072302625c91af7d33d923e761d:


package ingest

import (
	"os/exec"
	"path/filepath"
	"testing"

	"github.com/nats-io/nats.go"

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

// Repository names may contain dots, so a.b's store events sit under
// a's subject prefix: zit.evt.a.b.artifact. a's index folds a's events
// only — a.b may be private where a is public — and a.b folds its own.
// A node upgraded with a's consumer still reading zit.evt.a.> has it
// narrowed before the next fold, keeping its position.
func TestADottedNeighbourNeverFoldsIntoTheRepositoryItContinues(t *testing.T) {
	for _, upgraded := range []bool{false, true} {
		t.Run(map[bool]string{false: "fresh", true: "upgraded"}[upgraded], func(t *testing.T) {
			if _, err := exec.LookPath("zit"); err != nil {
				t.Skip("zit not on PATH")
			}
			ev, err := events.Start(filepath.Join(t.TempDir(), "nats"))
			if err != nil {
				t.Fatal(err)
			}
			t.Cleanup(ev.Close)
			a, aRepo, aIx := storeOnStream(t, ev, "a")
			ab, abRepo, abIx := storeOnStream(t, ev, "a.b")
			if upgraded {
				if _, err := ev.JS().AddConsumer(events.StreamName, &nats.ConsumerConfig{
					Durable: a.durable(), FilterSubject: "zit.evt.a.>", AckPolicy: nats.AckExplicitPolicy,
				}); err != nil {
					t.Fatal(err)
				}
			}
			// The first round reads each store whole, the second checks
			// its tip; only what is committed after travels the stream.
			for range 2 {
				for _, p := range []*Pipeline{a, ab} {
					if _, err := p.Sync(); err != nil {
						t.Fatal(err)
					}
				}
			}
			commitFile(t, abRepo, "b.txt", "beta\n", "pushed to a.b")
			if _, err := ab.Sync(); err != nil {
				t.Fatal(err)
			}
			commitFile(t, aRepo, "c.txt", "gamma\n", "pushed to a")
			if _, err := a.Sync(); err != nil {
				t.Fatal(err)
			}
			if !hasComment(t, aIx, "pushed to a") {
				t.Fatal("a never folded its own push")
			}
			if hasComment(t, aIx, "pushed to a.b") {
				t.Error("a's index holds a check-in pushed to a.b")
			}
			if !hasComment(t, abIx, "pushed to a.b") {
				t.Error("a.b never folded its own push")
			}
			info, err := ev.JS().ConsumerInfo(events.StreamName, a.durable())
			if err != nil {
				t.Fatal(err)
			}
			if info.Config.FilterSubject != "zit.evt.a.*" {
				t.Errorf("a's consumer reads %q", info.Config.FilterSubject)
			}
		})
	}
}