Seed from go-template-repo, renamed to simplexcalc
The template's files at a77fd30, without its history or LICENSE, after script/rename simplexcalc. Model: opus-5-5
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
package telemetry_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"sneak.berlin/go/simplexcalc/internal/config"
|
||||
"sneak.berlin/go/simplexcalc/internal/telemetry"
|
||||
)
|
||||
|
||||
func newMetrics(t *testing.T, user, password string) *telemetry.Metrics {
|
||||
t.Helper()
|
||||
|
||||
m, err := telemetry.NewMetrics(telemetry.MetricsParams{
|
||||
Config: &config.Config{MetricsUser: user, MetricsPassword: password},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("building metrics: %v", err)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// TestMetricsRequireCredentialsWhenConfigured: an exposition endpoint
|
||||
// leaks route names, traffic volume and process layout, so credentials
|
||||
// have to actually be enforced.
|
||||
func TestMetricsRequireCredentialsWhenConfigured(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := newMetrics(t, user, pass)
|
||||
|
||||
if !m.AuthRequired() {
|
||||
t.Fatal("credentials are configured but AuthRequired is false")
|
||||
}
|
||||
|
||||
const (
|
||||
unauthorized = http.StatusUnauthorized
|
||||
ok = http.StatusOK
|
||||
)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
user, pass string
|
||||
useAuth bool
|
||||
want int
|
||||
}{
|
||||
{name: "no credentials", want: unauthorized},
|
||||
{name: "wrong password", user: user, pass: "no", useAuth: true, want: unauthorized},
|
||||
{name: "wrong user", user: "nobody", pass: pass, useAuth: true, want: unauthorized},
|
||||
{name: "correct", user: user, pass: pass, useAuth: true, want: ok},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
req := scrapeReq(t)
|
||||
if tc.useAuth {
|
||||
req.SetBasicAuth(tc.user, tc.pass)
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
m.Handler().ServeHTTP(w, req)
|
||||
|
||||
if w.Code != tc.want {
|
||||
t.Errorf("status = %d, want %d", w.Code, tc.want)
|
||||
}
|
||||
|
||||
if tc.want == http.StatusUnauthorized {
|
||||
if w.Header().Get("WWW-Authenticate") == "" {
|
||||
t.Error("a 401 with no WWW-Authenticate gives the client nothing to do")
|
||||
}
|
||||
|
||||
if strings.Contains(w.Body.String(), "http_requests_total") {
|
||||
t.Error("metrics were served in the body of a 401")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestMetricsOpenWhenNoCredentials documents the other half: with
|
||||
// nothing configured the endpoint is open, which config permits only
|
||||
// when BOTH values are absent.
|
||||
func TestMetricsOpenWhenNoCredentials(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := newMetrics(t, "", "")
|
||||
|
||||
if m.AuthRequired() {
|
||||
t.Fatal("no credentials configured but AuthRequired is true")
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
m.Handler().ServeHTTP(w, scrapeReq(t))
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("status = %d, want 200", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// TestObservedRequestsAreExported: the middleware records through
|
||||
// Observe, and what it records has to come back out of the endpoint.
|
||||
func TestObservedRequestsAreExported(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := newMetrics(t, "", "")
|
||||
|
||||
m.Observe(http.MethodGet, "/widgets/{id}", "200", 25*time.Millisecond)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
m.Handler().ServeHTTP(w, scrapeReq(t))
|
||||
|
||||
body := w.Body.String()
|
||||
|
||||
for _, want := range []string{
|
||||
`http_requests_total{code="200",method="GET",route="/widgets/{id}"} 1`,
|
||||
"http_request_duration_seconds_bucket",
|
||||
"go_goroutines", // the Go collector is registered
|
||||
} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("exposition output is missing %q", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestSentryDisabledWithoutDSN: every method must be safe with no DSN,
|
||||
// because that is how the service runs in development and in tests.
|
||||
func TestSentryDisabledWithoutDSN(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s, err := telemetry.NewSentry(nil, telemetry.SentryParams{
|
||||
Config: &config.Config{},
|
||||
Globals: testGlobals(),
|
||||
Logger: testLogger(t),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("building sentry: %v", err)
|
||||
}
|
||||
|
||||
if s.Enabled() {
|
||||
t.Error("sentry reports enabled with no DSN")
|
||||
}
|
||||
|
||||
// Must not panic.
|
||||
s.CaptureError(nil)
|
||||
s.CaptureError(errTest)
|
||||
s.CapturePanic("boom", []byte("stack"))
|
||||
}
|
||||
Reference in New Issue
Block a user