ananke/internal/state/store_test.go

88 lines
2.3 KiB
Go

package state
import (
"os"
"path/filepath"
"strconv"
"strings"
"testing"
)
func TestAcquireLockLifecycle(t *testing.T) {
lockPath := filepath.Join(t.TempDir(), "hecate.lock")
unlock, err := AcquireLock(lockPath)
if err != nil {
t.Fatalf("acquire lock: %v", err)
}
if _, err := os.Stat(lockPath); err != nil {
t.Fatalf("expected lock file to exist: %v", err)
}
unlock()
if _, err := os.Stat(lockPath); !os.IsNotExist(err) {
t.Fatalf("expected lock file to be removed, got: %v", err)
}
}
func TestAcquireLockReclaimsStaleLock(t *testing.T) {
lockPath := filepath.Join(t.TempDir(), "hecate.lock")
if err := os.WriteFile(lockPath, []byte("pid=999999\n"), 0o600); err != nil {
t.Fatalf("write stale lock: %v", err)
}
unlock, err := AcquireLock(lockPath)
if err != nil {
t.Fatalf("acquire lock with stale predecessor: %v", err)
}
defer unlock()
b, err := os.ReadFile(lockPath)
if err != nil {
t.Fatalf("read lock: %v", err)
}
if !strings.Contains(string(b), "pid=") {
t.Fatalf("expected lock content to contain pid, got %q", string(b))
}
}
func TestAcquireLockRejectsActiveLock(t *testing.T) {
lockPath := filepath.Join(t.TempDir(), "hecate.lock")
active := "pid=" + strconv.Itoa(os.Getpid()) + "\n"
if err := os.WriteFile(lockPath, []byte(active), 0o600); err != nil {
t.Fatalf("write active lock: %v", err)
}
if _, err := AcquireLock(lockPath); err == nil {
t.Fatalf("expected acquire lock to fail when active pid holds lock")
}
}
func TestStoreLoadAutoHealsCorruptJSON(t *testing.T) {
dir := t.TempDir()
p := filepath.Join(dir, "runs.json")
if err := os.WriteFile(p, []byte(`{"bad":`), 0o640); err != nil {
t.Fatalf("write corrupt run history: %v", err)
}
records, err := New(p).Load()
if err != nil {
t.Fatalf("load with auto-heal: %v", err)
}
if len(records) != 0 {
t.Fatalf("expected no records after heal, got %d", len(records))
}
raw, err := os.ReadFile(p)
if err != nil {
t.Fatalf("read healed runs file: %v", err)
}
if string(raw) != "[]\n" {
t.Fatalf("expected healed runs payload '[]', got %q", string(raw))
}
matches, err := filepath.Glob(filepath.Join(dir, "runs.json.corrupt-*"))
if err != nil {
t.Fatalf("glob backup files: %v", err)
}
if len(matches) != 1 {
t.Fatalf("expected 1 backup file, got %d (%v)", len(matches), matches)
}
}