Files
Pulse/pkg/reporting/engine_additional_test.go
2026-02-05 11:36:54 +00:00

187 lines
5.3 KiB
Go

package reporting
import (
"path/filepath"
"strings"
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/pkg/metrics"
)
func TestReportEngineGenerateMissingStore(t *testing.T) {
engine := NewReportEngine(EngineConfig{})
_, _, err := engine.Generate(MetricReportRequest{
ResourceType: "node",
ResourceID: "node-1",
Start: time.Now().Add(-1 * time.Hour),
End: time.Now(),
Format: FormatCSV,
})
if err == nil {
t.Fatal("expected error when metrics store is nil")
}
if !strings.Contains(err.Error(), "metrics store not initialized") {
t.Fatalf("unexpected error: %v", err)
}
}
func TestReportEngineGenerateUnsupportedFormat(t *testing.T) {
store := newTestMetricsStore(t)
defer store.Close()
engine := NewReportEngine(EngineConfig{MetricsStore: store})
_, _, err := engine.Generate(MetricReportRequest{
ResourceType: "node",
ResourceID: "node-1",
Start: time.Now().Add(-1 * time.Hour),
End: time.Now(),
Format: ReportFormat("xls"),
})
if err == nil {
t.Fatal("expected unsupported format error")
}
if !strings.Contains(err.Error(), "unsupported format") {
t.Fatalf("unexpected error: %v", err)
}
}
func TestReportEngineQueryMetricsSpecificMetric(t *testing.T) {
store := newTestMetricsStore(t)
defer store.Close()
start := time.Now().Add(-30 * time.Minute)
points := []metrics.WriteMetric{
{ResourceType: "node", ResourceID: "node-1", MetricType: "cpu", Value: 10, Timestamp: start, Tier: metrics.TierRaw},
{ResourceType: "node", ResourceID: "node-1", MetricType: "cpu", Value: 30, Timestamp: start.Add(5 * time.Minute), Tier: metrics.TierRaw},
{ResourceType: "node", ResourceID: "node-1", MetricType: "memory", Value: 50, Timestamp: start, Tier: metrics.TierRaw},
}
store.WriteBatchSync(points)
engine := NewReportEngine(EngineConfig{MetricsStore: store})
data, err := engine.queryMetrics(MetricReportRequest{
ResourceType: "node",
ResourceID: "node-1",
MetricType: "cpu",
Start: start.Add(-1 * time.Minute),
End: start.Add(10 * time.Minute),
})
if err != nil {
t.Fatalf("queryMetrics failed: %v", err)
}
if data.Title != "node Report: node-1" {
t.Fatalf("expected default title, got %q", data.Title)
}
if len(data.Metrics) != 1 {
t.Fatalf("expected 1 metric, got %d", len(data.Metrics))
}
if _, ok := data.Metrics["cpu"]; !ok {
t.Fatal("expected cpu metric data to be present")
}
if _, ok := data.Metrics["memory"]; ok {
t.Fatal("expected memory metric to be filtered out")
}
stats, ok := data.Summary.ByMetric["cpu"]
if !ok {
t.Fatal("expected cpu summary stats")
}
if stats.Count != 2 {
t.Fatalf("expected cpu count 2, got %d", stats.Count)
}
if stats.Min != 10 || stats.Max != 30 {
t.Fatalf("unexpected cpu min/max: %+v", stats)
}
if stats.Avg != 20 {
t.Fatalf("expected cpu avg 20, got %v", stats.Avg)
}
if stats.Current != 30 {
t.Fatalf("expected cpu current 30, got %v", stats.Current)
}
}
func TestReportEngineQueryMetricsNoData(t *testing.T) {
store := newTestMetricsStore(t)
defer store.Close()
engine := NewReportEngine(EngineConfig{MetricsStore: store})
start := time.Now().Add(-1 * time.Hour)
data, err := engine.queryMetrics(MetricReportRequest{
ResourceType: "node",
ResourceID: "missing-node",
Start: start,
End: time.Now(),
})
if err != nil {
t.Fatalf("queryMetrics failed: %v", err)
}
if data.TotalPoints != 0 {
t.Fatalf("expected zero points, got %d", data.TotalPoints)
}
if len(data.Metrics) != 0 {
t.Fatalf("expected no metrics, got %d", len(data.Metrics))
}
if data.Title != "node Report: missing-node" {
t.Fatalf("expected default title, got %q", data.Title)
}
}
func TestReportEngineGenerateMultiAggregatesData(t *testing.T) {
store := newTestMetricsStore(t)
defer store.Close()
base := time.Now().Add(-15 * time.Minute)
store.WriteBatchSync([]metrics.WriteMetric{
{ResourceType: "node", ResourceID: "node-1", MetricType: "cpu", Value: 10, Timestamp: base, Tier: metrics.TierRaw},
{ResourceType: "node", ResourceID: "node-2", MetricType: "cpu", Value: 20, Timestamp: base.Add(2 * time.Minute), Tier: metrics.TierRaw},
})
engine := NewReportEngine(EngineConfig{MetricsStore: store})
data, contentType, err := engine.GenerateMulti(MultiReportRequest{
Resources: []MetricReportRequest{
{ResourceType: "node", ResourceID: "node-1"},
{ResourceType: "node", ResourceID: "node-2"},
},
MetricType: "cpu",
Start: base.Add(-1 * time.Minute),
End: base.Add(5 * time.Minute),
Format: FormatCSV,
})
if err != nil {
t.Fatalf("GenerateMulti failed: %v", err)
}
if contentType != "text/csv" {
t.Fatalf("expected text/csv, got %s", contentType)
}
csv := string(data)
if !strings.Contains(csv, "# Pulse Multi-Resource Metrics Report") {
t.Fatal("missing multi-resource header")
}
if !strings.Contains(csv, "node-1") || !strings.Contains(csv, "node-2") {
t.Fatal("expected both resource IDs in output")
}
}
func newTestMetricsStore(t *testing.T) *metrics.Store {
t.Helper()
dir := t.TempDir()
cfg := metrics.DefaultConfig(dir)
cfg.DBPath = filepath.Join(dir, "metrics.db")
cfg.WriteBufferSize = 1
cfg.FlushInterval = 50 * time.Millisecond
store, err := metrics.NewStore(cfg)
if err != nil {
t.Fatalf("failed to create metrics store: %v", err)
}
return store
}