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") } }