Luigit
repositories / bugabinga.net

bugabinga.net

personal infrastructure for bugabinga!

owned by admin

services/luci/internal/runstate/runstate_test.go

Raw
package runstate

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

func TestActiveLifecycleUsesCanonicalJSON(t *testing.T) {
	store := Store{DataDir: t.TempDir()}
	active := Active{RunID: "42", ChildID: "001", Repo: "smith", Job: "smoke", Rev: "abc", Ref: "refs/heads/trunk", Trigger: "push", StartedAt: time.Date(2026, 8, 5, 0, 0, 0, 0, time.UTC)}
	if err := store.Write(active); err != nil {
		t.Fatal(err)
	}
	path := filepath.Join(store.DataDir, "active", "42.json")
	data, err := os.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}
	text := string(data)
	for _, want := range []string{`"run_id":"42"`, `"child_id":"001"`, `"started_at":"2026-08-05T00:00:00Z"`} {
		if !strings.Contains(text, want) {
			t.Fatalf("JSON missing %s: %s", want, text)
		}
	}
	if matches, _ := filepath.Glob(filepath.Join(store.DataDir, "active", "*.tmp")); len(matches) != 0 {
		t.Fatalf("tmp=%v", matches)
	}
	got, warnings, err := store.List()
	if err != nil || len(warnings) != 0 || len(got) != 1 || got[0].ChildID != "001" {
		t.Fatalf("got=%#v warnings=%v err=%v", got, warnings, err)
	}
	if err := store.Remove("42"); err != nil {
		t.Fatal(err)
	}
	if _, err := os.Stat(path); !os.IsNotExist(err) {
		t.Fatalf("active remains: %v", err)
	}
}

func TestStoreAcceptsScheduledActiveRecord(t *testing.T) {
	store := Store{DataDir: t.TempDir()}
	active := Active{RunID: "scheduled", ChildID: "001", Repo: "repo", Job: "nightly", Rev: "abc", Ref: "refs/heads/main", Trigger: "schedule", StartedAt: time.Now().UTC()}
	if err := store.Write(active); err != nil {
		t.Fatal(err)
	}
}

func TestListIsolatesMalformedRecords(t *testing.T) {
	store := Store{DataDir: t.TempDir()}
	if err := store.Write(Active{RunID: "good", ChildID: "001", Repo: "repo", Job: "check", Rev: "abc", Trigger: "push", StartedAt: time.Now().UTC()}); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(filepath.Join(store.DataDir, "active", "bad.json"), []byte("{"), 0o644); err != nil {
		t.Fatal(err)
	}
	got, warnings, err := store.List()
	if err != nil || len(got) != 1 || len(warnings) != 1 {
		t.Fatalf("got=%#v warnings=%v err=%v", got, warnings, err)
	}
}

func TestListMissingDirectoryFailsAndUnsafeIDsAreRejected(t *testing.T) {
	store := Store{DataDir: t.TempDir()}
	if _, _, err := store.List(); err == nil {
		t.Fatal("missing active dir accepted")
	}
	if err := store.Write(Active{RunID: "../bad"}); err == nil {
		t.Fatal("unsafe id accepted")
	}
	if err := store.Remove("../bad"); err == nil {
		t.Fatal("unsafe remove accepted")
	}
}

func TestListRejectsMismatchedAndIncompleteRecords(t *testing.T) {
	store := Store{DataDir: t.TempDir()}
	if err := os.MkdirAll(filepath.Join(store.DataDir, "active"), 0o755); err != nil {
		t.Fatal(err)
	}
	validTime := "2026-08-05T00:00:00Z"
	for name, data := range map[string]string{
		"victim.json": `{"run_id":"other","child_id":"001","repo":"repo","job":"check","rev":"abc","trigger":"push","started_at":"` + validTime + `"}`,
		"empty.json":  `{"run_id":"empty","child_id":"","repo":"","job":"","rev":"","trigger":"","started_at":"0001-01-01T00:00:00Z"}`,
	} {
		if err := os.WriteFile(filepath.Join(store.DataDir, "active", name), []byte(data), 0o644); err != nil {
			t.Fatal(err)
		}
	}
	got, warnings, err := store.List()
	if err != nil || len(got) != 0 || len(warnings) != 2 {
		t.Fatalf("got=%#v warnings=%v err=%v", got, warnings, err)
	}
}

func TestChildIDAcceptsEveryPositiveOrdinal(t *testing.T) {
	for _, childID := range []string{"001", "999", "1000"} {
		store := Store{DataDir: t.TempDir()}
		active := Active{RunID: childID, ChildID: childID, Repo: "repo", Job: "check", Rev: "abc", Trigger: "push", StartedAt: time.Now().UTC()}
		if err := store.Write(active); err != nil {
			t.Fatalf("child %s: %v", childID, err)
		}
	}
	store := Store{DataDir: t.TempDir()}
	if err := store.Write(Active{RunID: "zero", ChildID: "000", Repo: "repo", Job: "check", Rev: "abc", Trigger: "push", StartedAt: time.Now().UTC()}); err == nil {
		t.Fatal("zero child accepted")
	}
}