66 lines
2.0 KiB
Go
66 lines
2.0 KiB
Go
package busymark
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// D65 = A: the agent refuses an operator reboot while the controller's busy file is fresh.
|
|
|
|
func newW(t *testing.T) (*Writer, *bool, *time.Time) {
|
|
t.Helper()
|
|
busy := false
|
|
now := time.Date(2026, 10, 29, 16, 0, 0, 0, time.UTC)
|
|
w := &Writer{Path: filepath.Join(t.TempDir(), "ctl", FileName), Now: func() time.Time { return now }}
|
|
w.AddProbe("a backup or a restore is running", func() bool { return busy })
|
|
return w, &busy, &now
|
|
}
|
|
|
|
// Busy → the file holds the time and the sentence; idle → gone. RED-PROOF: skip the write → no file → FAILS;
|
|
// skip the remove → the file stays → FAILS.
|
|
func TestBusyFileFollowsTheWork(t *testing.T) {
|
|
w, busy, now := newW(t)
|
|
w.Tick()
|
|
if _, err := os.Stat(w.Path); !os.IsNotExist(err) {
|
|
t.Fatalf("idle: a busy file exists (%v)", err)
|
|
}
|
|
*busy = true
|
|
w.Tick()
|
|
raw, err := os.ReadFile(w.Path)
|
|
if err != nil {
|
|
t.Fatalf("busy: no file: %v", err)
|
|
}
|
|
lines := strings.Split(strings.TrimSpace(string(raw)), "\n")
|
|
if len(lines) != 2 || lines[0] != now.Format(time.RFC3339) || lines[1] != "a backup or a restore is running" {
|
|
t.Fatalf("file %q", raw)
|
|
}
|
|
if fi, _ := os.Stat(w.Path); fi.Mode().Perm() != 0o600 {
|
|
t.Fatalf("mode %v, want 0600", fi.Mode().Perm())
|
|
}
|
|
// it is REWRITTEN while busy: freshness is the agent's signal
|
|
*now = now.Add(15 * time.Second)
|
|
w.Tick()
|
|
raw, _ = os.ReadFile(w.Path)
|
|
if !strings.HasPrefix(string(raw), now.Format(time.RFC3339)) {
|
|
t.Fatalf("not rewritten: %q", raw)
|
|
}
|
|
*busy = false
|
|
w.Tick()
|
|
if _, err := os.Stat(w.Path); !os.IsNotExist(err) {
|
|
t.Fatalf("idle again: the busy file is still there (%v) — the agent would refuse a reboot for 90 s more", err)
|
|
}
|
|
}
|
|
|
|
// The first probe that runs names the work; a nil probe is ignored.
|
|
func TestBusyNamesTheRunningWork(t *testing.T) {
|
|
w, _, _ := newW(t)
|
|
w.AddProbe("an app update is running", func() bool { return true })
|
|
w.AddProbe("ignored", nil)
|
|
if got := w.Busy(); got != "an app update is running" {
|
|
t.Fatalf("Busy() = %q", got)
|
|
}
|
|
}
|