package index
import (
"path/filepath"
"testing"
"time"
)
func warmIndex(t *testing.T) *Index {
t.Helper()
ix, err := Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
if _, err := ix.db.Exec(`INSERT INTO checkin (hash, date, user, comment, branch)
VALUES ('a1', '2026-01-01T00:00:00.000', 'dan', '', 'main')`); err != nil {
t.Fatal(err)
}
return ix
}
func warmKeys(ix *Index) []string {
ix.countMu.Lock()
defer ix.countMu.Unlock()
out := make([]string, 0, len(ix.activityDays))
for b := range ix.activityDays {
out = append(out, b)
}
return out
}
// The day-fold is 1.03s cold and 1ms warm on the tcl mirror, and a
// mirror folds on every pull — so a reader kept paying the scan. After
// a fold it is recomputed off the request path, and what was warm
// before is warm again.
func TestAFoldRewarmsTheDayFoldItDropped(t *testing.T) {
ix := warmIndex(t)
if _, err := ix.ActivityDays("main"); err != nil {
t.Fatal(err)
}
if len(warmKeys(ix)) != 1 {
t.Fatal("precondition: the day-fold was not memoised")
}
ix.invalidateCounts()
deadline := time.Now().Add(2 * time.Second)
for time.Now().Before(deadline) {
if len(warmKeys(ix)) == 1 {
return
}
time.Sleep(5 * time.Millisecond)
}
t.Error("the day-fold was dropped and not rebuilt: the next reader pays the scan")
}
// A repository nobody has opened must cost nothing. This is what makes
// re-warming safe on a fleet: a bulk import folds in a tight loop before
// anyone has looked, and warming what was never warm would turn every
// one of those folds into a full scan.
func TestAnUnviewedRepositoryIsNotWarmed(t *testing.T) {
ix := warmIndex(t)
ix.invalidateCounts()
time.Sleep(50 * time.Millisecond)
if got := warmKeys(ix); len(got) != 0 {
t.Errorf("warmed %v for a repository nobody has opened", got)
}
}
// Only the branches that were warm come back — not every branch that
// exists — so the work stays proportional to what people actually read.
func TestOnlyTheBranchesThatWereWarmComeBack(t *testing.T) {
ix := warmIndex(t)
if _, err := ix.ActivityDays("main"); err != nil {
t.Fatal(err)
}
ix.invalidateCounts()
deadline := time.Now().Add(2 * time.Second)
for time.Now().Before(deadline) && len(warmKeys(ix)) == 0 {
time.Sleep(5 * time.Millisecond)
}
got := warmKeys(ix)
if len(got) != 1 || got[0] != "main" {
t.Errorf("warm keys = %v, want only the branch that was being read", got)
}
}