mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 11:30:15 +00:00
test: expand backend coverage
This commit is contained in:
parent
3ea5f54d93
commit
7f7edfceb4
118 changed files with 21980 additions and 74 deletions
188
internal/api/ai_intelligence_handlers_data_additional_test.go
Normal file
188
internal/api/ai_intelligence_handlers_data_additional_test.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/ai"
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
||||
)
|
||||
|
||||
func setupAIHandlerWithIntelligence(t *testing.T) (*AISettingsHandler, *ai.PatrolService) {
|
||||
t.Helper()
|
||||
|
||||
tmp := t.TempDir()
|
||||
cfg := &config.Config{DataPath: tmp}
|
||||
persistence := config.NewConfigPersistence(tmp)
|
||||
handler := newTestAISettingsHandler(cfg, persistence, nil)
|
||||
handler.legacyAIService.SetStateProvider(&stubStateProvider{})
|
||||
|
||||
patrol := handler.legacyAIService.GetPatrolService()
|
||||
if patrol == nil {
|
||||
t.Fatalf("expected patrol service to be initialized")
|
||||
}
|
||||
|
||||
return handler, patrol
|
||||
}
|
||||
|
||||
func seedPatternDetector(now time.Time) *ai.PatternDetector {
|
||||
detector := ai.NewPatternDetector(ai.PatternDetectorConfig{
|
||||
MinOccurrences: 2,
|
||||
PatternWindow: 24 * time.Hour,
|
||||
PredictionLimit: 48 * time.Hour,
|
||||
})
|
||||
|
||||
detector.RecordEvent(ai.HistoricalEvent{
|
||||
ResourceID: "vm-1",
|
||||
EventType: ai.EventHighCPU,
|
||||
Timestamp: now.Add(-1 * time.Hour),
|
||||
Duration: 10 * time.Minute,
|
||||
})
|
||||
detector.RecordEvent(ai.HistoricalEvent{
|
||||
ResourceID: "vm-1",
|
||||
EventType: ai.EventHighCPU,
|
||||
Timestamp: now,
|
||||
Duration: 5 * time.Minute,
|
||||
})
|
||||
|
||||
return detector
|
||||
}
|
||||
|
||||
func seedCorrelationDetector(now time.Time) *ai.CorrelationDetector {
|
||||
detector := ai.NewCorrelationDetector(ai.CorrelationConfig{
|
||||
MinOccurrences: 1,
|
||||
CorrelationWindow: 10 * time.Minute,
|
||||
RetentionWindow: 24 * time.Hour,
|
||||
MaxEvents: 100,
|
||||
})
|
||||
|
||||
detector.RecordEvent(ai.CorrelationEvent{
|
||||
ResourceID: "node-1",
|
||||
ResourceName: "node-1",
|
||||
ResourceType: "node",
|
||||
EventType: ai.CorrelationEventHighCPU,
|
||||
Timestamp: now.Add(-2 * time.Minute),
|
||||
})
|
||||
detector.RecordEvent(ai.CorrelationEvent{
|
||||
ResourceID: "vm-1",
|
||||
ResourceName: "vm-1",
|
||||
ResourceType: "vm",
|
||||
EventType: ai.CorrelationEventRestart,
|
||||
Timestamp: now.Add(-1 * time.Minute),
|
||||
})
|
||||
|
||||
return detector
|
||||
}
|
||||
|
||||
func TestHandleGetPatterns_LockedWithData(t *testing.T) {
|
||||
t.Setenv("PULSE_MOCK_MODE", "true")
|
||||
handler, _ := setupAIHandlerWithIntelligence(t)
|
||||
|
||||
handler.legacyAIService.SetPatternDetector(seedPatternDetector(time.Now()))
|
||||
handler.legacyAIService.SetLicenseChecker(stubLicenseChecker{allow: false})
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/ai/intelligence/patterns", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.HandleGetPatterns(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", rec.Code)
|
||||
}
|
||||
if rec.Header().Get("X-License-Required") != "true" {
|
||||
t.Fatalf("expected license header to be set")
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
Patterns []map[string]interface{} `json:"patterns"`
|
||||
Count int `json:"count"`
|
||||
LicenseRequired bool `json:"license_required"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if resp.Count != 1 {
|
||||
t.Fatalf("count = %d, want 1", resp.Count)
|
||||
}
|
||||
if len(resp.Patterns) != 0 {
|
||||
t.Fatalf("expected patterns to be redacted")
|
||||
}
|
||||
if !resp.LicenseRequired {
|
||||
t.Fatalf("expected license_required=true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleGetPredictions_WithData(t *testing.T) {
|
||||
t.Setenv("PULSE_MOCK_MODE", "true")
|
||||
handler, _ := setupAIHandlerWithIntelligence(t)
|
||||
|
||||
handler.legacyAIService.SetPatternDetector(seedPatternDetector(time.Now()))
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/ai/intelligence/predictions?resource_id=vm-1", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.HandleGetPredictions(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", rec.Code)
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
Predictions []struct {
|
||||
ResourceID string `json:"resource_id"`
|
||||
IsOverdue bool `json:"is_overdue"`
|
||||
} `json:"predictions"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if resp.Count != 1 || len(resp.Predictions) != 1 {
|
||||
t.Fatalf("predictions count = %d, want 1", resp.Count)
|
||||
}
|
||||
if resp.Predictions[0].ResourceID != "vm-1" {
|
||||
t.Fatalf("resource_id = %s, want vm-1", resp.Predictions[0].ResourceID)
|
||||
}
|
||||
if resp.Predictions[0].IsOverdue {
|
||||
t.Fatalf("expected prediction to not be overdue")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleGetCorrelations_WithData(t *testing.T) {
|
||||
t.Setenv("PULSE_MOCK_MODE", "true")
|
||||
handler, _ := setupAIHandlerWithIntelligence(t)
|
||||
|
||||
handler.legacyAIService.SetCorrelationDetector(seedCorrelationDetector(time.Now()))
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/ai/intelligence/correlations?resource_id=vm-1", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.HandleGetCorrelations(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", rec.Code)
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
Correlations []struct {
|
||||
TargetID string `json:"target_id"`
|
||||
EventPattern string `json:"event_pattern"`
|
||||
} `json:"correlations"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if resp.Count != 1 || len(resp.Correlations) != 1 {
|
||||
t.Fatalf("correlations count = %d, want 1", resp.Count)
|
||||
}
|
||||
if resp.Correlations[0].TargetID != "vm-1" {
|
||||
t.Fatalf("target_id = %s, want vm-1", resp.Correlations[0].TargetID)
|
||||
}
|
||||
if resp.Correlations[0].EventPattern == "" {
|
||||
t.Fatalf("expected event_pattern to be set")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue