- Wire all goroutines in main.go: watcher, quota monitor, account switcher, dispatcher, janitor, and 10s state flush loop - Add missing sections to config.example.yaml: notifications, dispatcher, watcher, janitor - Add scripts/claude-failover.service systemd unit Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
96 lines
2.7 KiB
Go
96 lines
2.7 KiB
Go
package janitor
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"forge.secuaas.ovh/olivier/claude-failover/internal/state"
|
|
)
|
|
|
|
func TestNew(t *testing.T) {
|
|
s := state.New("/tmp/test-state.json")
|
|
j := New(s, "/tmp/projects")
|
|
|
|
if j == nil {
|
|
t.Fatal("New() returned nil")
|
|
}
|
|
if j.interval != defaultInterval {
|
|
t.Errorf("expected interval %v, got %v", defaultInterval, j.interval)
|
|
}
|
|
if j.state != s {
|
|
t.Error("state not assigned correctly")
|
|
}
|
|
if j.projectsDir != "/tmp/projects" {
|
|
t.Errorf("projectsDir not assigned correctly: %s", j.projectsDir)
|
|
}
|
|
if j.logger == nil {
|
|
t.Error("logger should not be nil")
|
|
}
|
|
}
|
|
|
|
func TestCleanupStaleAgentDoneFiles(t *testing.T) {
|
|
// Create a stale file (older than 1h).
|
|
staleFile := fmt.Sprintf("/tmp/agent-done-test-%d", time.Now().UnixNano())
|
|
if err := os.WriteFile(staleFile, []byte("done"), 0644); err != nil {
|
|
t.Fatalf("create stale file: %v", err)
|
|
}
|
|
// Age the file to 2 hours ago.
|
|
old := time.Now().Add(-2 * time.Hour)
|
|
if err := os.Chtimes(staleFile, old, old); err != nil {
|
|
t.Fatalf("chtimes: %v", err)
|
|
}
|
|
|
|
// Create a recent file (should NOT be deleted).
|
|
recentFile := fmt.Sprintf("/tmp/agent-done-test-recent-%d", time.Now().UnixNano())
|
|
if err := os.WriteFile(recentFile, []byte("recent"), 0644); err != nil {
|
|
t.Fatalf("create recent file: %v", err)
|
|
}
|
|
defer os.Remove(recentFile)
|
|
|
|
s := state.New("/tmp/test-state.json")
|
|
j := New(s, "/tmp/projects")
|
|
j.cleanupStaleAgentDoneFiles()
|
|
|
|
// Stale file should be gone.
|
|
if _, err := os.Stat(staleFile); !os.IsNotExist(err) {
|
|
os.Remove(staleFile)
|
|
t.Errorf("stale file %s should have been deleted", staleFile)
|
|
}
|
|
|
|
// Recent file should still exist.
|
|
if _, err := os.Stat(recentFile); os.IsNotExist(err) {
|
|
t.Errorf("recent file %s should NOT have been deleted", recentFile)
|
|
}
|
|
}
|
|
|
|
func TestCleanupOrphanDispatchMeta(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
inboxDir := filepath.Join(tmpDir, ".agent-queue", "inbox")
|
|
if err := os.MkdirAll(inboxDir, 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Create a task file and its dispatch-meta.
|
|
taskFile := filepath.Join(inboxDir, "my-task.md")
|
|
metaFile := taskFile + ".dispatch-meta"
|
|
os.WriteFile(taskFile, []byte("task"), 0644)
|
|
os.WriteFile(metaFile, []byte("meta"), 0644)
|
|
|
|
s := state.New("/tmp/test-state.json")
|
|
j := New(s, tmpDir)
|
|
|
|
// No working sessions → dispatch-meta should be removed.
|
|
workingByTask := make(map[string]struct{})
|
|
j.cleanupOrphanDispatchMeta(inboxDir, workingByTask)
|
|
|
|
if _, err := os.Stat(metaFile); !os.IsNotExist(err) {
|
|
t.Errorf("orphan dispatch-meta %s should have been deleted", metaFile)
|
|
}
|
|
// Task file itself should still exist.
|
|
if _, err := os.Stat(taskFile); os.IsNotExist(err) {
|
|
t.Errorf("task file %s should NOT have been deleted", taskFile)
|
|
}
|
|
}
|