87 lines
3.0 KiB
Go
87 lines
3.0 KiB
Go
|
|
package metrics
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
// TestExporterHealthzAndEscaping runs one orchestration or CLI step.
|
||
|
|
// Signature: TestExporterHealthzAndEscaping(t *testing.T).
|
||
|
|
// Why: covers health endpoint and label escaping branches in metrics renderer.
|
||
|
|
func TestExporterHealthzAndEscaping(t *testing.T) {
|
||
|
|
e := New()
|
||
|
|
e.UpdateSample(Sample{
|
||
|
|
Name: `Sta"tera`,
|
||
|
|
Target: `statera\host`,
|
||
|
|
Status: `O"B`,
|
||
|
|
LastError: "x",
|
||
|
|
})
|
||
|
|
|
||
|
|
h := e.Handler("/custom")
|
||
|
|
healthReq := httptest.NewRequest(http.MethodGet, "/healthz", nil)
|
||
|
|
healthRR := httptest.NewRecorder()
|
||
|
|
h.ServeHTTP(healthRR, healthReq)
|
||
|
|
if healthRR.Code != http.StatusOK || strings.TrimSpace(healthRR.Body.String()) != "ok" {
|
||
|
|
t.Fatalf("unexpected health response: code=%d body=%q", healthRR.Code, healthRR.Body.String())
|
||
|
|
}
|
||
|
|
|
||
|
|
metricsReq := httptest.NewRequest(http.MethodGet, "/custom", nil)
|
||
|
|
metricsRR := httptest.NewRecorder()
|
||
|
|
h.ServeHTTP(metricsRR, metricsReq)
|
||
|
|
body := metricsRR.Body.String()
|
||
|
|
if !strings.Contains(body, `source="Sta\\\"tera"`) {
|
||
|
|
t.Fatalf("expected escaped source label, got:\n%s", body)
|
||
|
|
}
|
||
|
|
if !strings.Contains(body, `target="statera\\\\host"`) {
|
||
|
|
t.Fatalf("expected escaped target label, got:\n%s", body)
|
||
|
|
}
|
||
|
|
if !strings.Contains(body, "ananke_ups_error") {
|
||
|
|
t.Fatalf("expected error metric line in output")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// TestBoolNumAndSafeHelpers runs one orchestration or CLI step.
|
||
|
|
// Signature: TestBoolNumAndSafeHelpers(t *testing.T).
|
||
|
|
// Why: directly covers remaining helper branches.
|
||
|
|
func TestBoolNumAndSafeHelpers(t *testing.T) {
|
||
|
|
if boolNum(true) != 1 || boolNum(false) != 0 {
|
||
|
|
t.Fatalf("unexpected boolNum values")
|
||
|
|
}
|
||
|
|
if got := safe(`a"b\c`); got != `a\"b\\c` {
|
||
|
|
t.Fatalf("unexpected escaped string: %q", got)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// TestExporterAppendsQualityGateMetrics runs one orchestration or CLI step.
|
||
|
|
// Signature: TestExporterAppendsQualityGateMetrics(t *testing.T).
|
||
|
|
// Why: verifies quality-gate metrics are surfaced on /metrics for Grafana suite
|
||
|
|
// pass-rate tracking.
|
||
|
|
func TestExporterAppendsQualityGateMetrics(t *testing.T) {
|
||
|
|
tmp := t.TempDir()
|
||
|
|
metricsPath := filepath.Join(tmp, "quality-gate.prom")
|
||
|
|
content := strings.Join([]string{
|
||
|
|
`# HELP ananke_quality_gate_runs_total Total quality gate runs by status.`,
|
||
|
|
`# TYPE ananke_quality_gate_runs_total counter`,
|
||
|
|
`ananke_quality_gate_runs_total{suite="ananke",status="ok"} 10`,
|
||
|
|
`ananke_quality_gate_runs_total{suite="ananke",status="failed"} 2`,
|
||
|
|
"",
|
||
|
|
}, "\n")
|
||
|
|
if err := os.WriteFile(metricsPath, []byte(content), 0o600); err != nil {
|
||
|
|
t.Fatalf("write quality metrics file: %v", err)
|
||
|
|
}
|
||
|
|
t.Setenv("ANANKE_QUALITY_METRICS_FILE", metricsPath)
|
||
|
|
|
||
|
|
e := New()
|
||
|
|
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
|
||
|
|
rr := httptest.NewRecorder()
|
||
|
|
e.Handler("/metrics").ServeHTTP(rr, req)
|
||
|
|
body := rr.Body.String()
|
||
|
|
if !strings.Contains(body, `ananke_quality_gate_runs_total{suite="ananke",status="ok"} 10`) {
|
||
|
|
t.Fatalf("expected quality gate metrics appended to exporter output, got:\n%s", body)
|
||
|
|
}
|
||
|
|
}
|