package db import ( "fmt" "testing" "time" "crypto-miner-server/internal/models" ) func TestListAgentsFilteredLargeFleet(t *testing.T) { d, err := New(t.TempDir()) if err != nil { t.Fatal(err) } defer d.Close() const total = 200 for i := 0; i < total; i++ { subnet := i % 3 agent := &models.Agent{ ID: fmt.Sprintf("agent-%04d", i), Name: fmt.Sprintf("node-%d", i), IP: fmt.Sprintf("10.0.%d.%d", subnet, (i%250)+1), Status: "online", LastSeen: time.Now().Add(-time.Duration(i) * time.Second), } if err := d.UpsertAgent(agent); err != nil { t.Fatalf("upsert %d: %v", i, err) } } all, err := d.ListAgents() if err != nil { t.Fatal(err) } if len(all) != total { t.Fatalf("ListAgents: want %d got %d", total, len(all)) } page, err := d.ListAgentsFiltered(AgentListFilter{Limit: 50, Offset: 0}) if err != nil { t.Fatal(err) } if len(page) != 50 { t.Fatalf("page 0: want 50 got %d", len(page)) } subnetAgents, err := d.ListAgentsFiltered(AgentListFilter{Subnet: "10.0.1.x"}) if err != nil { t.Fatal(err) } wantSubnet := total / 3 if len(subnetAgents) < wantSubnet-1 || len(subnetAgents) > wantSubnet+1 { t.Fatalf("subnet filter: want ~%d got %d", wantSubnet, len(subnetAgents)) } count, err := d.CountAgentsFiltered(AgentListFilter{Status: "online"}) if err != nil { t.Fatal(err) } if count != total { t.Fatalf("count online: want %d got %d", total, count) } } func TestListAgentsFilteredAt500(t *testing.T) { d, err := New(t.TempDir()) if err != nil { t.Fatal(err) } defer d.Close() const total = 500 const subnets = 25 for i := 0; i < total; i++ { subnet := i % subnets agent := &models.Agent{ ID: fmt.Sprintf("agent-%04d", i), Name: fmt.Sprintf("node-%d", i), IP: fmt.Sprintf("10.0.%d.%d", subnet, (i%250)+1), Status: "online", LastSeen: time.Now().Add(-time.Duration(i) * time.Second), } if err := d.UpsertAgent(agent); err != nil { t.Fatalf("upsert %d: %v", i, err) } } const pageLimit = 80 var seen int for offset := 0; offset < total; offset += pageLimit { page, err := d.ListAgentsFiltered(AgentListFilter{Limit: pageLimit, Offset: offset}) if err != nil { t.Fatal(err) } want := pageLimit if remain := total - offset; remain < pageLimit { want = remain } if len(page) != want { t.Fatalf("offset %d: want %d got %d", offset, want, len(page)) } seen += len(page) } if seen != total { t.Fatalf("paginated scan: want %d rows got %d", total, seen) } const targetSubnet = "10.0.1.x" subnetAgents, err := d.ListAgentsFiltered(AgentListFilter{Subnet: targetSubnet, Limit: pageLimit}) if err != nil { t.Fatal(err) } wantSubnet := total / subnets if len(subnetAgents) != wantSubnet { t.Fatalf("subnet filter: want %d got %d", wantSubnet, len(subnetAgents)) } start := time.Now() count, err := d.CountAgentsFiltered(AgentListFilter{Subnet: targetSubnet}) elapsed := time.Since(start) if err != nil { t.Fatal(err) } if count != wantSubnet { t.Fatalf("subnet count: want %d got %d", wantSubnet, count) } if elapsed > 2*time.Second { t.Fatalf("CountAgentsFiltered at %d agents too slow: %v", total, elapsed) } t.Logf("CountAgentsFiltered subnet=%s: %d in %v", targetSubnet, count, elapsed) } func TestSubnetToIPPrefix(t *testing.T) { if got := subnetToIPPrefix("192.168.1.x"); got != "192.168.1.%" { t.Fatalf("got %q", got) } if got := subnetToIPPrefix(""); got != "" { t.Fatalf("empty: got %q", got) } }