ai-code-battle/metrics/metrics_test.go
jedarden 80334c6e34 feat(evolver): expand MAP-Elites from 2-D to 4-D grid per §10.2
- Add Exploration and Formation axis definitions with feature extraction
  from source code pattern matching (exploration/formation indicators)
- Extend Grid key from (x,y) to (x,y,z,w) with 3⁴=81-cell behavior grid
- Update bin assignment, promotion gate, and persistence (JSON snapshot)
- Add Slice() for 2-D dashboard visualization across any axis pair
- Migration: old 2-D archives project at z=middle, w=middle
- Update cross-pollination to pad 2-element behavior vectors to 4
- Add Prometheus metrics to matchmaker (bot crashes, stale job count)
- Add rivalry detection to index builder (data/meta/rivalries.json)
- Web: batched bot list loading, leaderboard keyboard accessibility,
  improved ARIA attributes on match/playlist cards

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 15:44:39 -04:00

104 lines
2.8 KiB
Go

package metrics
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestHandlerReturnsOK(t *testing.T) {
h := Handler()
req := httptest.NewRequest(http.MethodGet, "/health", nil)
w := httptest.NewRecorder()
h.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected 200, got %d", w.Code)
}
body := w.Body.String()
if !strings.Contains(body, `"status":"ok"`) {
t.Fatalf("unexpected body: %s", body)
}
}
func TestMetricsEndpoint(t *testing.T) {
// Increment some metrics to ensure they appear
MatchThroughput.Inc()
JobQueueDepth.Set(42)
HTTPRequestsTotal.WithLabelValues("GET", "/test", "200").Inc()
h := Handler()
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
w := httptest.NewRecorder()
h.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected 200, got %d", w.Code)
}
body := w.Body.String()
// Verify §9.9 metrics are present
expectedMetrics := []string{
"acb_match_throughput_total",
"acb_job_queue_depth",
"acb_bot_crashed_total",
"acb_job_stale_count",
"acb_r2_bytes_used",
"acb_replay_upload_latency_seconds",
"acb_evolver_generations_total",
"acb_index_build_duration_seconds",
"acb_http_requests_total",
}
for _, name := range expectedMetrics {
if !strings.Contains(body, name) {
t.Errorf("metrics output missing %q", name)
}
}
// Verify the incremented counter is present
if !strings.Contains(body, "acb_match_throughput_total ") {
t.Error("match throughput counter not found in output")
}
// Verify the gauge value
if !strings.Contains(body, "acb_job_queue_depth 42") {
t.Error("job queue depth gauge not found with expected value")
}
}
func TestHTTPRequestsCounter(t *testing.T) {
HTTPRequestsTotal.WithLabelValues("GET", "/api/status", "200").Inc()
HTTPRequestsTotal.WithLabelValues("POST", "/api/register", "201").Inc()
h := Handler()
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
w := httptest.NewRecorder()
h.ServeHTTP(w, req)
body := w.Body.String()
if !strings.Contains(body, `method="GET",path="/api/status",status="200"`) {
t.Error("labelled HTTP request counter not found")
}
if !strings.Contains(body, `method="POST",path="/api/register",status="201"`) {
t.Error("labelled HTTP request counter not found")
}
}
func TestHistogramObserved(t *testing.T) {
ReplayUploadLatency.Observe(1.5)
IndexBuildDuration.Observe(30.2)
h := Handler()
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
w := httptest.NewRecorder()
h.ServeHTTP(w, req)
body := w.Body.String()
if !strings.Contains(body, "acb_replay_upload_latency_seconds_bucket") {
t.Error("replay upload latency histogram not found")
}
if !strings.Contains(body, "acb_index_build_duration_seconds_bucket") {
t.Error("index build duration histogram not found")
}
}