forgejo-runner-optimiser/internal/collector/collector_test.go
Martin McCaffery d713c25fa5
All checks were successful
ci / build (push) Successful in 26s
ci / goreleaser (push) Successful in 23s
Rename repo from forgejo-runner-resource-collector
2026-02-12 09:55:04 +01:00

98 lines
2.5 KiB
Go

// ABOUTME: Tests for the collector's summary integration.
// ABOUTME: Validates that run summaries are emitted on shutdown and handles missing writer gracefully.
package collector
import (
"bytes"
"context"
"log/slog"
"strings"
"testing"
"time"
"edp.buildth.ing/DevFW-CICD/forgejo-runner-optimiser/internal/output"
"edp.buildth.ing/DevFW-CICD/forgejo-runner-optimiser/internal/summary"
)
func TestCollector_EmitsSummaryOnShutdown(t *testing.T) {
// Use testdata/proc as the proc filesystem
procPath := "testdata/proc"
// Metrics output (regular collection output)
var metricsOut bytes.Buffer
metricsWriter := output.NewLoggerWriter(output.LoggerConfig{
Output: &metricsOut,
Format: output.LogFormatJSON,
Level: slog.LevelInfo,
})
// Summary output
var summaryOut bytes.Buffer
sw := summary.NewSummaryWriter(&summaryOut, "json")
// Silence app logs
appLogger := slog.New(slog.NewTextHandler(&bytes.Buffer{}, nil))
c := New(Config{
ProcPath: procPath,
Interval: 50 * time.Millisecond,
TopN: 5,
}, metricsWriter, appLogger)
c.SetSummaryWriter(sw)
// Run collector briefly then cancel
ctx, cancel := context.WithCancel(context.Background())
go func() {
// Let at least 2 collection cycles run
time.Sleep(150 * time.Millisecond)
cancel()
}()
_ = c.Run(ctx)
// Verify summary was emitted
summaryOutput := summaryOut.String()
if !strings.Contains(summaryOutput, "run_summary") {
t.Errorf("expected 'run_summary' in output, got: %s", summaryOutput)
}
if !strings.Contains(summaryOutput, "duration_seconds") {
t.Errorf("expected 'duration_seconds' in output, got: %s", summaryOutput)
}
if !strings.Contains(summaryOutput, "sample_count") {
t.Errorf("expected 'sample_count' in output, got: %s", summaryOutput)
}
}
func TestCollector_NoSummaryWithoutWriter(t *testing.T) {
procPath := "testdata/proc"
var metricsOut bytes.Buffer
metricsWriter := output.NewLoggerWriter(output.LoggerConfig{
Output: &metricsOut,
Format: output.LogFormatJSON,
Level: slog.LevelInfo,
})
appLogger := slog.New(slog.NewTextHandler(&bytes.Buffer{}, nil))
c := New(Config{
ProcPath: procPath,
Interval: 50 * time.Millisecond,
TopN: 5,
}, metricsWriter, appLogger)
// Deliberately do NOT set a summary writer
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(100 * time.Millisecond)
cancel()
}()
// Should not panic
err := c.Run(ctx)
if err != context.Canceled {
t.Errorf("expected context.Canceled, got: %v", err)
}
}