package metrics_test import ( "net/http" "net/http/httptest" "strings" "testing" "github.com/uopi/uopi/internal/metrics" ) func TestCounters(t *testing.T) { // Counters are package-level atomics; exercise each Inc function. metrics.IncWsConns() metrics.IncWsConns() metrics.DecWsConns() metrics.IncMsgIn() metrics.IncMsgOut() metrics.IncWrites() metrics.IncHistoryReqs() // No panic = pass; values are additive across tests but that's fine. } func TestHandlerFormat(t *testing.T) { handler := metrics.Handler(func() int { return 42 }) req := httptest.NewRequest(http.MethodGet, "/metrics", nil) rec := httptest.NewRecorder() handler(rec, req) body := rec.Body.String() // Must contain all metric names. required := []string{ "uopi_uptime_seconds", "uopi_ws_connections", "uopi_signal_subscriptions", "uopi_ws_messages_in_total", "uopi_ws_messages_out_total", "uopi_write_ops_total", "uopi_history_requests_total", } for _, name := range required { if !strings.Contains(body, name) { t.Errorf("metric %q not found in response body", name) } } // Content-Type must be set for Prometheus scrapers. ct := rec.Header().Get("Content-Type") if !strings.Contains(ct, "text/plain") { t.Errorf("Content-Type = %q, want text/plain", ct) } // activeSubs value 42 must appear. if !strings.Contains(body, "42") { t.Error("activeSubs value 42 not found in body") } } func TestHandlerNilActiveSubs(t *testing.T) { handler := metrics.Handler(nil) req := httptest.NewRequest(http.MethodGet, "/metrics", nil) rec := httptest.NewRecorder() handler(rec, req) // must not panic if rec.Code != http.StatusOK { t.Errorf("status = %d, want 200", rec.Code) } }