Skip to content
quarry Artifact [95e4240e2d]
Login

Artifact [95e4240e2d]

Artifact 95e4240e2d6fd3a2ac311e4f40e3c815f804bc7b1c6b9681c0bd2354148ce383:


package ci

import (
	"encoding/json"
	"strings"
	"testing"
)

// The bug: a pipeline was registered under its file's stem alone, so
// two repositories with the same file name shared one definition on the
// engine — and quarry re-registers immediately before every run, so the
// last writer won and a run could execute the other's pipeline.
func TestTwoRepositoriesDoNotShareAPipelineName(t *testing.T) {
	alpha := ScopedName("alpha", "build")
	beta := ScopedName("beta", "build")
	if alpha == beta {
		t.Fatalf("FAIL: %q == %q — the collision this exists to remove", alpha, beta)
	}
	t.Logf("ok: alpha/build and beta/build register apart (%s, %s)", alpha, beta)
}

// The ambiguity a plain dotted join leaves behind, which is the same one
// dagnats documents for its own version keys. Repository names may
// contain dots and so may file stems, so the join alone is not enough.
func TestADottedNameCannotBeConfusedWithAnother(t *testing.T) {
	a := ScopedName("a.b", "c")
	b := ScopedName("a", "b.c")
	if a == b {
		t.Fatalf("FAIL: %q == %q — a fixed-length digest is what separates these", a, b)
	}
	if !strings.HasPrefix(a, "a.b.c.") || !strings.HasPrefix(b, "a.b.c.") {
		t.Fatalf("both should stay readable as a.b.c.<digest>, got %q and %q", a, b)
	}
	t.Logf("ok: %s and %s differ only where they must", a, b)
}

// Stable across calls: the name is recomputed before every run, and a
// name that moved would register a second definition each time.
func TestTheNameIsStable(t *testing.T) {
	if ScopedName("quarry", "quarry") != ScopedName("quarry", "quarry") {
		t.Fatal("FAIL: the name is not stable")
	}
	t.Log("ok: the same pair always names the same workflow")
}

// The readable half is kept, because this is what shows in the engine's
// console and a name nobody can read is a name nobody can debug.
func TestTheNameStaysReadable(t *testing.T) {
	got := ScopedName("quarry", "build")
	if !strings.HasPrefix(got, "quarry.build.") {
		t.Fatalf("FAIL: %q does not lead with the repository and the pipeline", got)
	}
	t.Logf("ok: %s", got)
}

// A JSON pipeline carries its own name, so registering one under
// quarry's name must replace that field and keep everything else — the
// struct knows only what quarry reads, and most of a pipeline is not it.
func TestRenamingAJSONPipelineKeepsTheRest(t *testing.T) {
	def := []byte(`{"name":"build","steps":[{"task":"shell"}],"unknown_field":{"kept":true}}`)
	var raw map[string]any
	if err := json.Unmarshal(def, &raw); err != nil {
		t.Fatal(err)
	}
	raw["name"] = ScopedName("alpha", "build")
	out, err := json.Marshal(raw)
	if err != nil {
		t.Fatal(err)
	}
	var back map[string]any
	if err := json.Unmarshal(out, &back); err != nil {
		t.Fatal(err)
	}
	if back["unknown_field"] == nil {
		t.Fatal("FAIL: a field quarry does not read was dropped by the rename")
	}
	if back["name"] == "build" {
		t.Fatal("FAIL: the name was not replaced")
	}
	t.Log("ok: the rename keeps fields quarry never reads")
}