package main
import (
"errors"
"os"
"path/filepath"
"testing"
"time"
"craftdesign.group/quarry/internal/ops"
)
// A forge agent's rebuild starts only on a quiet forge and a store a
// rebuild of which is routine; past either, it is refused and starts
// nothing, and the refusal says which.
func TestAnAgentsRebuildWaitsForAQuietForgeAndASmallStore(t *testing.T) {
if err := upkeepRefusal("tcl", 0, 400<<20); err != nil {
t.Errorf("FAIL: a quiet forge and a 400 MiB store were refused: %v", err)
}
if err := upkeepRefusal("tcl", 1, 1<<20); !errors.Is(err, ops.ErrUnavailable) {
t.Errorf("FAIL: a rebuild under way did not hold the agent back: %v", err)
}
if err := upkeepRefusal("netbsd-src", 0, 3<<30); !errors.Is(err, ops.ErrForbidden) {
t.Errorf("FAIL: a 3 GiB store was rebuilt by an agent: %v", err)
}
}
// storeBytes reads a store file, or the .zit inside a directory.
func TestStoreBytesReadsTheStore(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, ".zit"), make([]byte, 1234), 0o644); err != nil {
t.Fatal(err)
}
if n := storeBytes(dir); n != 1234 {
t.Errorf("FAIL: a directory's store reads as %d bytes", n)
}
if n := storeBytes(filepath.Join(dir, ".zit")); n != 1234 {
t.Errorf("FAIL: a store file reads as %d bytes", n)
}
}
// An agent's rebuilds are spaced: one repository at most once a day,
// and the forge's next a while after the last ended, so no agent walks
// the fleet emptying timelines as it goes. A store whose size cannot be
// read is not rebuilt unasked.
func TestAnAgentsRebuildsAreSpaced(t *testing.T) {
upkeepLast.Lock()
upkeepLast.repo, upkeepLast.any = map[string]time.Time{}, time.Time{}
upkeepLast.Unlock()
t0 := time.Date(2026, 10, 19, 12, 0, 0, 0, time.UTC)
if err := upkeepSpaced("tcl", t0); err != nil {
t.Fatalf("FAIL: the first rebuild was refused: %v", err)
}
upkeepDone("tcl", func() time.Time { return t0 })
for _, c := range []struct {
name string
at time.Duration
ok bool
}{
{"tcl", time.Hour, false},
{"tk", 5 * time.Minute, false},
{"tk", 11 * time.Minute, true},
{"tcl", 25 * time.Hour, true},
} {
if err := upkeepSpaced(c.name, t0.Add(c.at)); (err == nil) != c.ok {
t.Errorf("FAIL: %s at +%s: %v, want allowed=%v", c.name, c.at, err, c.ok)
}
}
if err := upkeepRefusal("tcl", 0, 0); !errors.Is(err, ops.ErrUnavailable) {
t.Errorf("FAIL: a store of unknown size was rebuilt: %v", err)
}
}