Ctrl K
ComunidadGuías…

internal/store/runs_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package store

import (
	"context"
	"path/filepath"
	"testing"
	"time"
)

func runStore(t *testing.T) *Store {
	t.Helper()
	held, err := Open(t.Context(), filepath.Join(t.TempDir(), "runs.db"))
	if err != nil {
		t.Fatalf("open: %v", err)
	}
	t.Cleanup(func() { _ = held.Close() })
	return held
}

func aRun(at time.Time, findings int) Run {
	return Run{At: at, Findings: findings, Fresh: 1, Cleared: 2, Scanned: 42}
}

func TestARunReadsBackTheWayItWasRecorded(t *testing.T) {
	held := runStore(t)
	at := time.Date(2026, 9, 9, 12, 0, 0, 0, time.UTC)

	if err := held.RecordRun(t.Context(), "kind-spinoza", aRun(at, 4)); err != nil {
		t.Fatalf("record: %v", err)
	}

	back, err := held.Runs(t.Context(), "kind-spinoza", 0)
	if err != nil {
		t.Fatalf("runs: %v", err)
	}
	if len(back) != 1 {
		t.Fatalf("runs = %d, want 1", len(back))
	}
	one := back[0]
	if one.Findings != 4 || one.Fresh != 1 || one.Cleared != 2 || one.Scanned != 42 {
		t.Fatalf("run = %+v", one)
	}
	if !one.At.Equal(at) {
		t.Fatalf("at = %s, want %s", one.At, at)
	}
	if one.ID == 0 {
		t.Fatal("the run came back with no id")
	}
}

func TestRunsComeBackNewestFirstAndOnlyForTheClusterAsked(t *testing.T) {
	held := runStore(t)
	for at, one := range []struct {
		cluster string
		run     Run
	}{
		{cluster: "one", run: aRun(noon.Add(-2*time.Hour), 1)},
		{cluster: "one", run: aRun(noon, 3)},
		{cluster: "two", run: aRun(noon.Add(-time.Hour), 2)},
	} {
		if err := held.RecordRun(t.Context(), one.cluster, one.run); err != nil {
			t.Fatalf("record %d: %v", at, err)
		}
	}

	onlyOne, err := held.Runs(t.Context(), "one", 0)
	if err != nil {
		t.Fatalf("runs: %v", err)
	}
	if len(onlyOne) != 2 {
		t.Fatalf("runs for one = %d, want 2", len(onlyOne))
	}
	if onlyOne[0].Findings != 3 {
		t.Fatalf("first run = %+v, want the newest", onlyOne[0])
	}

	everything, allErr := held.Runs(t.Context(), "", 0)
	if allErr != nil {
		t.Fatalf("runs: %v", allErr)
	}
	if len(everything) != 3 {
		t.Fatalf("runs across every cluster = %d, want 3", len(everything))
	}
}

func TestAskingForMoreRunsThanAreKeptGivesWhatIsKept(t *testing.T) {
	held := runStore(t)
	for at := range 5 {
		if err := held.RecordRun(t.Context(), "one", aRun(noon.Add(time.Duration(at)*time.Minute), at)); err != nil {
			t.Fatalf("record: %v", err)
		}
	}

	for _, asked := range []int{-1, 0, runsKept + 1} {
		back, err := held.Runs(t.Context(), "one", asked)
		if err != nil {
			t.Fatalf("runs(%d): %v", asked, err)
		}
		if len(back) != 5 {
			t.Fatalf("runs(%d) = %d, want every one of 5", asked, len(back))
		}
	}

	two, err := held.Runs(t.Context(), "one", 2)
	if err != nil {
		t.Fatalf("runs: %v", err)
	}
	if len(two) != 2 {
		t.Fatalf("runs(2) = %d", len(two))
	}
}

func TestRunsArePrunedByAgeAndByCount(t *testing.T) {
	held := runStore(t)
	if err := held.RecordRun(t.Context(), "one", aRun(noon.AddDate(0, 0, -30), 1)); err != nil {
		t.Fatalf("record: %v", err)
	}
	if err := held.RecordRun(t.Context(), "one", aRun(noon, 2)); err != nil {
		t.Fatalf("record: %v", err)
	}

	if err := held.PruneRuns(t.Context(), Retention{Days: 7}, noon); err != nil {
		t.Fatalf("prune: %v", err)
	}

	back, err := held.Runs(t.Context(), "one", 0)
	if err != nil {
		t.Fatalf("runs: %v", err)
	}
	if len(back) != 1 || back[0].Findings != 2 {
		t.Fatalf("runs after pruning = %+v, want only the recent one", back)
	}

	if err := held.PruneRuns(t.Context(), Retention{Rows: 0}, noon); err != nil {
		t.Fatalf("prune with no cap: %v", err)
	}
	kept, keptErr := held.Runs(t.Context(), "one", 0)
	if keptErr != nil {
		t.Fatalf("runs: %v", keptErr)
	}
	if len(kept) != 1 {
		t.Fatalf("a prune with no window removed something: %d left", len(kept))
	}
}

func TestAStoreWithNowhereToWriteKeepsNoRunsAndSaysSo(t *testing.T) {
	held := &Store{}

	if err := held.RecordRun(t.Context(), "one", aRun(time.Now(), 1)); err != nil {
		t.Fatalf("record: %v", err)
	}
	back, err := held.Runs(t.Context(), "one", 0)
	if err != nil {
		t.Fatalf("runs: %v", err)
	}
	if len(back) != 0 {
		t.Fatalf("runs = %d, want none", len(back))
	}
	if pruneErr := held.PruneRuns(t.Context(), Retention{Days: 1}, time.Now()); pruneErr != nil {
		t.Fatalf("prune: %v", pruneErr)
	}
}

func TestAClosedStoreKeepsNoRunsRatherThanBreaking(t *testing.T) {
	held := runStore(t)
	if err := held.Close(); err != nil {
		t.Fatalf("close: %v", err)
	}

	if err := held.RecordRun(context.Background(), "one", aRun(time.Now(), 1)); err != nil {
		t.Fatalf("a closed store returned an error rather than keeping nothing: %v", err)
	}
	back, readErr := held.Runs(context.Background(), "one", 0)
	if readErr != nil {
		t.Fatalf("a closed store returned an error rather than nothing: %v", readErr)
	}
	if len(back) != 0 {
		t.Fatalf("a closed store answered with %d runs", len(back))
	}
}

func TestARunThatCannotBeWrittenIsReported(t *testing.T) {
	held := runStore(t)
	canceled, stop := context.WithCancel(t.Context())
	stop()

	err := held.RecordRun(canceled, "one", aRun(time.Now(), 1))

	if err == nil {
		t.Fatal("a write against a canceled request came back clean")
	}
	if _, readErr := held.Runs(canceled, "one", 0); readErr == nil {
		t.Fatal("a read against a canceled request came back clean")
	}
}