package runner
import (
"encoding/json"
"os"
"path/filepath"
"regexp"
"slices"
"testing"
)
// quarry's own CI: every step in its pipeline names a task the runner
// manifest can run (a step no manifest entry serves sits queued until
// it times out), and one of those steps is the race detector, run as
// the same make target a local `make check` runs.
func TestQuarrysPipelineRunsTheRaceTargetAsItsOwnStep(t *testing.T) {
root := filepath.Join("..", "..")
b, err := os.ReadFile(filepath.Join(root, ManifestPath))
if err != nil {
t.Fatal(err)
}
m, err := ParseManifest(b)
if err != nil {
t.Fatal(err)
}
b, err = os.ReadFile(filepath.Join(root, "ci", "quarry.json"))
if err != nil {
t.Fatal(err)
}
var pipeline struct {
Steps []struct {
ID string `json:"id"`
Task string `json:"task"`
} `json:"steps"`
}
if err := json.Unmarshal(b, &pipeline); err != nil {
t.Fatal(err)
}
raceStep := ""
for _, s := range pipeline.Steps {
task, ok := m.Tasks[s.Task]
if !ok {
t.Errorf("FAIL: step %q runs task %q, which %s does not name", s.ID, s.Task, ManifestPath)
continue
}
if slices.Equal(task.Argv, []string{"make", "race"}) {
raceStep = s.ID
}
}
if raceStep == "" {
t.Fatal("FAIL: no pipeline step runs `make race`")
}
mk, err := os.ReadFile(filepath.Join(root, "Makefile"))
if err != nil {
t.Fatal(err)
}
if !regexp.MustCompile(`(?m)^check:.*\brace\b`).Match(mk) {
t.Error("FAIL: make check does not run the race target CI runs")
}
if !regexp.MustCompile(`(?m)^race:\n(\t.*\n)*\tgo test -race `).Match(mk) {
t.Error("FAIL: the Makefile has no race target running go test -race")
}
t.Logf("ok: step %q runs make race, and make check runs it too", raceStep)
}