Pulse/internal/infradiscovery/service_additional_test.go
2026-01-25 21:08:44 +00:00

153 lines
3.8 KiB
Go

package infradiscovery
import (
"context"
"strings"
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/ai/knowledge"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
)
func waitFor(t *testing.T, timeout time.Duration, check func() bool) {
t.Helper()
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
if check() {
return
}
time.Sleep(10 * time.Millisecond)
}
t.Fatal("condition not met before timeout")
}
func TestStartStopUpdatesStatus(t *testing.T) {
provider := &mockStateProvider{state: models.StateSnapshot{}}
service := NewService(provider, nil, Config{
Interval: 10 * time.Millisecond,
CacheExpiry: time.Millisecond,
})
service.SetAIAnalyzer(&mockAIAnalyzer{})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
service.Start(ctx)
status := service.GetStatus()
if running, ok := status["running"].(bool); !ok || !running {
t.Fatalf("expected running status true, got %v", status["running"])
}
waitFor(t, 500*time.Millisecond, func() bool {
return !service.GetLastRun().IsZero()
})
service.Stop()
status = service.GetStatus()
if running, ok := status["running"].(bool); !ok || running {
t.Fatalf("expected running status false, got %v", status["running"])
}
}
func TestForceRefreshUpdatesLastRun(t *testing.T) {
provider := &mockStateProvider{state: models.StateSnapshot{}}
service := NewService(provider, nil, DefaultConfig())
service.SetAIAnalyzer(&mockAIAnalyzer{})
service.ForceRefresh(context.Background())
waitFor(t, 500*time.Millisecond, func() bool {
return !service.GetLastRun().IsZero()
})
}
func TestSaveDiscoveriesWritesKnowledge(t *testing.T) {
store, err := knowledge.NewStore(t.TempDir())
if err != nil {
t.Fatalf("create knowledge store: %v", err)
}
service := NewService(&mockStateProvider{}, store, DefaultConfig())
apps := []DiscoveredApp{
{
ID: "docker:host1:pg",
Name: "PostgreSQL",
RunsIn: "docker",
HostID: "host-1",
Hostname: "host1",
CLIAccess: "docker exec pg psql",
},
{
ID: "docker:host1:redis",
Name: "Redis",
RunsIn: "docker",
HostID: "host-1",
Hostname: "host1",
CLIAccess: "",
},
}
service.saveDiscoveries(apps)
knowledgeData, err := store.GetKnowledge("host-1")
if err != nil {
t.Fatalf("load knowledge: %v", err)
}
if knowledgeData == nil || len(knowledgeData.Notes) != 2 {
t.Fatalf("expected 2 notes, got %+v", knowledgeData)
}
var sawCLI, sawNoCLI bool
for _, note := range knowledgeData.Notes {
if strings.Contains(note.Content, "CLI access:") {
sawCLI = true
}
if strings.Contains(note.Content, "No CLI access available.") {
sawNoCLI = true
}
}
if !sawCLI || !sawNoCLI {
t.Fatalf("expected notes with and without CLI access, got %+v", knowledgeData.Notes)
}
}
func TestGetDiscoveriesReturnsCopy(t *testing.T) {
provider := &mockStateProvider{
state: models.StateSnapshot{
DockerHosts: []models.DockerHost{
{
AgentID: "agent-1",
Hostname: "host1",
Containers: []models.DockerContainer{
{ID: "1", Name: "web", Image: "nginx:latest"},
},
},
},
},
}
analyzer := &mockAIAnalyzer{
responses: map[string]string{
"nginx:latest": `{"service_type": "nginx", "service_name": "Nginx", "category": "web", "cli_command": "", "confidence": 0.9, "reasoning": "Web server"}`,
},
}
service := NewService(provider, nil, DefaultConfig())
service.SetAIAnalyzer(analyzer)
service.RunDiscovery(context.Background())
first := service.GetDiscoveries()
if len(first) != 1 {
t.Fatalf("expected 1 discovery, got %d", len(first))
}
first[0].Name = "changed"
second := service.GetDiscoveries()
if len(second) != 1 {
t.Fatalf("expected 1 discovery, got %d", len(second))
}
if second[0].Name == "changed" {
t.Fatalf("expected discoveries to be immutable copy, got %v", second[0].Name)
}
}