go/pkg/lab/store_test.go
Snider 3587d0ce27 test: add coverage for lab, session, sigil, repos, plugin packages
Brings 5 packages from low/zero coverage to solid test suites:
- pkg/lab: 0% → 100% (Store pub/sub, Config env loading)
- pkg/session: 0% → 89.9% (transcript parser, HTML renderer, search, video)
- pkg/io/sigil: 43.8% → 98.5% (XOR/ShuffleMask obfuscators, ChaCha20-Poly1305)
- pkg/repos: 18.9% → 81.9% (registry, topo sort, directory scan, org detection)
- pkg/plugin: 54.8% → 67.1% (installer error paths, Remove, registry Load/Save)

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-24 13:29:15 +00:00

391 lines
10 KiB
Go

package lab
import (
"errors"
"testing"
"time"
)
// ── NewStore ────────────────────────────────────────────────────────
func TestNewStore_Good(t *testing.T) {
s := NewStore()
if s == nil {
t.Fatal("NewStore returned nil")
}
if s.subs == nil {
t.Fatal("subs map not initialised")
}
if s.errors == nil {
t.Fatal("errors map not initialised")
}
}
// ── Subscribe / Unsubscribe ────────────────────────────────────────
func TestSubscribe_Good(t *testing.T) {
s := NewStore()
ch := s.Subscribe()
if ch == nil {
t.Fatal("Subscribe returned nil channel")
}
s.subMu.Lock()
_, ok := s.subs[ch]
s.subMu.Unlock()
if !ok {
t.Fatal("subscriber not registered")
}
}
func TestUnsubscribe_Good(t *testing.T) {
s := NewStore()
ch := s.Subscribe()
s.Unsubscribe(ch)
s.subMu.Lock()
_, ok := s.subs[ch]
s.subMu.Unlock()
if ok {
t.Fatal("subscriber not removed after Unsubscribe")
}
}
func TestUnsubscribe_Bad_NeverSubscribed(t *testing.T) {
s := NewStore()
ch := make(chan struct{}, 1)
// Should not panic.
s.Unsubscribe(ch)
}
// ── Notify ─────────────────────────────────────────────────────────
func TestNotify_Good_SubscriberReceivesSignal(t *testing.T) {
s := NewStore()
ch := s.Subscribe()
defer s.Unsubscribe(ch)
s.SetMachines([]Machine{{Name: "test"}})
select {
case <-ch:
// good
case <-time.After(100 * time.Millisecond):
t.Fatal("subscriber did not receive notification")
}
}
func TestNotify_Good_NonBlockingWhenFull(t *testing.T) {
s := NewStore()
ch := s.Subscribe()
defer s.Unsubscribe(ch)
// Fill the buffer.
ch <- struct{}{}
// Should not block.
s.SetMachines([]Machine{{Name: "a"}})
s.SetMachines([]Machine{{Name: "b"}})
}
func TestNotify_Good_MultipleSubscribers(t *testing.T) {
s := NewStore()
ch1 := s.Subscribe()
ch2 := s.Subscribe()
defer s.Unsubscribe(ch1)
defer s.Unsubscribe(ch2)
s.SetAgents(AgentSummary{Available: true})
for _, ch := range []chan struct{}{ch1, ch2} {
select {
case <-ch:
case <-time.After(100 * time.Millisecond):
t.Fatal("subscriber missed notification")
}
}
}
// ── SetMachines / Overview ─────────────────────────────────────────
func TestSetMachines_Good(t *testing.T) {
s := NewStore()
machines := []Machine{{Name: "noc", Host: "77.42.42.205"}, {Name: "de1", Host: "116.202.82.115"}}
s.SetMachines(machines)
ov := s.Overview()
if len(ov.Machines) != 2 {
t.Fatalf("expected 2 machines, got %d", len(ov.Machines))
}
if ov.Machines[0].Name != "noc" {
t.Fatalf("expected noc, got %s", ov.Machines[0].Name)
}
}
func TestOverview_Good_ContainersMergedIntoFirstMachine(t *testing.T) {
s := NewStore()
s.SetMachines([]Machine{{Name: "primary"}, {Name: "secondary"}})
s.SetContainers([]Container{{Name: "forgejo", Status: "running"}})
ov := s.Overview()
if len(ov.Machines[0].Containers) != 1 {
t.Fatal("containers not merged into first machine")
}
if ov.Machines[0].Containers[0].Name != "forgejo" {
t.Fatalf("unexpected container name: %s", ov.Machines[0].Containers[0].Name)
}
if len(ov.Machines[1].Containers) != 0 {
t.Fatal("containers leaked into second machine")
}
}
func TestOverview_Good_EmptyMachinesNoContainerPanic(t *testing.T) {
s := NewStore()
s.SetContainers([]Container{{Name: "c1"}})
// No machines set — should not panic.
ov := s.Overview()
if len(ov.Machines) != 0 {
t.Fatal("expected zero machines")
}
}
func TestOverview_Good_ErrorsCopied(t *testing.T) {
s := NewStore()
s.SetError("prometheus", errors.New("connection refused"))
ov := s.Overview()
if ov.Errors["prometheus"] != "connection refused" {
t.Fatal("error not in overview")
}
// Mutating the copy should not affect the store.
ov.Errors["prometheus"] = "hacked"
ov2 := s.Overview()
if ov2.Errors["prometheus"] != "connection refused" {
t.Fatal("overview errors map is not a copy")
}
}
// ── SetAgents / GetAgents ──────────────────────────────────────────
func TestAgents_Good(t *testing.T) {
s := NewStore()
s.SetAgents(AgentSummary{Available: true, RegisteredTotal: 3, QueuePending: 1})
got := s.GetAgents()
if !got.Available {
t.Fatal("expected Available=true")
}
if got.RegisteredTotal != 3 {
t.Fatalf("expected 3, got %d", got.RegisteredTotal)
}
}
// ── SetTraining / GetTraining ──────────────────────────────────────
func TestTraining_Good(t *testing.T) {
s := NewStore()
s.SetTraining(TrainingSummary{GoldGenerated: 404, GoldTarget: 15000, GoldPercent: 2.69})
got := s.GetTraining()
if got.GoldGenerated != 404 {
t.Fatalf("expected 404, got %d", got.GoldGenerated)
}
}
// ── SetModels / GetModels ──────────────────────────────────────────
func TestModels_Good(t *testing.T) {
s := NewStore()
s.SetModels([]HFModel{{ModelID: "lthn/lem-gemma3-1b", Downloads: 42}})
got := s.GetModels()
if len(got) != 1 {
t.Fatal("expected 1 model")
}
if got[0].Downloads != 42 {
t.Fatalf("expected 42 downloads, got %d", got[0].Downloads)
}
}
// ── SetCommits ─────────────────────────────────────────────────────
func TestCommits_Good(t *testing.T) {
s := NewStore()
s.SetCommits([]Commit{{SHA: "abc123", Message: "feat: test coverage", Author: "virgil"}})
ov := s.Overview()
if len(ov.Commits) != 1 {
t.Fatal("expected 1 commit")
}
if ov.Commits[0].Author != "virgil" {
t.Fatalf("expected virgil, got %s", ov.Commits[0].Author)
}
}
// ── SetContainers / GetContainers ──────────────────────────────────
func TestContainers_Good(t *testing.T) {
s := NewStore()
s.SetContainers([]Container{{Name: "traefik", Status: "running"}, {Name: "forgejo", Status: "running"}})
got := s.GetContainers()
if len(got) != 2 {
t.Fatal("expected 2 containers")
}
}
// ── SetError / GetErrors ───────────────────────────────────────────
func TestSetError_Good_SetAndClear(t *testing.T) {
s := NewStore()
s.SetError("hf", errors.New("rate limited"))
errs := s.GetErrors()
if errs["hf"] != "rate limited" {
t.Fatal("error not stored")
}
// Clear by passing nil.
s.SetError("hf", nil)
errs = s.GetErrors()
if _, ok := errs["hf"]; ok {
t.Fatal("error not cleared")
}
}
func TestGetErrors_Good_ReturnsCopy(t *testing.T) {
s := NewStore()
s.SetError("forge", errors.New("timeout"))
errs := s.GetErrors()
errs["forge"] = "tampered"
fresh := s.GetErrors()
if fresh["forge"] != "timeout" {
t.Fatal("GetErrors did not return a copy")
}
}
// ── SetServices / GetServices ──────────────────────────────────────
func TestServices_Good(t *testing.T) {
s := NewStore()
s.SetServices([]Service{{Name: "Forgejo", URL: "https://forge.lthn.ai", Status: "ok"}})
got := s.GetServices()
if len(got) != 1 {
t.Fatal("expected 1 service")
}
if got[0].Name != "Forgejo" {
t.Fatalf("expected Forgejo, got %s", got[0].Name)
}
}
// ── SetBenchmarks / GetBenchmarks ──────────────────────────────────
func TestBenchmarks_Good(t *testing.T) {
s := NewStore()
s.SetBenchmarks(BenchmarkData{
Runs: []BenchmarkRun{{RunID: "run-1", Model: "gemma3-4b", Type: "training"}},
})
got := s.GetBenchmarks()
if len(got.Runs) != 1 {
t.Fatal("expected 1 benchmark run")
}
}
// ── SetGoldenSet / GetGoldenSet ────────────────────────────────────
func TestGoldenSet_Good(t *testing.T) {
s := NewStore()
s.SetGoldenSet(GoldenSetSummary{Available: true, TotalExamples: 15000, TargetTotal: 15000, CompletionPct: 100})
got := s.GetGoldenSet()
if !got.Available {
t.Fatal("expected Available=true")
}
if got.TotalExamples != 15000 {
t.Fatalf("expected 15000, got %d", got.TotalExamples)
}
}
// ── SetTrainingRuns / GetTrainingRuns ───────────────────────────────
func TestTrainingRuns_Good(t *testing.T) {
s := NewStore()
s.SetTrainingRuns([]TrainingRunStatus{
{Model: "gemma3-4b", RunID: "r1", Status: "training", Iteration: 100, TotalIters: 300},
})
got := s.GetTrainingRuns()
if len(got) != 1 {
t.Fatal("expected 1 training run")
}
if got[0].Iteration != 100 {
t.Fatalf("expected iter 100, got %d", got[0].Iteration)
}
}
// ── SetDataset / GetDataset ────────────────────────────────────────
func TestDataset_Good(t *testing.T) {
s := NewStore()
s.SetDataset(DatasetSummary{
Available: true,
Tables: []DatasetTable{{Name: "golden_set", Rows: 15000}},
})
got := s.GetDataset()
if !got.Available {
t.Fatal("expected Available=true")
}
if len(got.Tables) != 1 {
t.Fatal("expected 1 table")
}
}
// ── Concurrent access (race detector) ──────────────────────────────
func TestConcurrentAccess_Good(t *testing.T) {
s := NewStore()
done := make(chan struct{})
// Writer goroutine.
go func() {
for i := range 100 {
s.SetMachines([]Machine{{Name: "noc"}})
s.SetAgents(AgentSummary{Available: true})
s.SetTraining(TrainingSummary{GoldGenerated: i})
s.SetModels([]HFModel{{ModelID: "m1"}})
s.SetCommits([]Commit{{SHA: "abc"}})
s.SetContainers([]Container{{Name: "c1"}})
s.SetError("test", errors.New("e"))
s.SetServices([]Service{{Name: "s1"}})
s.SetBenchmarks(BenchmarkData{})
s.SetGoldenSet(GoldenSetSummary{})
s.SetTrainingRuns([]TrainingRunStatus{})
s.SetDataset(DatasetSummary{})
}
close(done)
}()
// Reader goroutine.
for range 100 {
_ = s.Overview()
_ = s.GetModels()
_ = s.GetTraining()
_ = s.GetAgents()
_ = s.GetContainers()
_ = s.GetServices()
_ = s.GetBenchmarks()
_ = s.GetGoldenSet()
_ = s.GetTrainingRuns()
_ = s.GetDataset()
_ = s.GetErrors()
}
<-done
}