Files
onix/pkg/metrics/requests_test.go
2025-11-13 13:16:16 +05:30

347 lines
7.9 KiB
Go

package metrics
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestInitRequestMetrics(t *testing.T) {
tests := []struct {
name string
enabled bool
wantError bool
}{
{
name: "metrics enabled",
enabled: true,
wantError: false,
},
{
name: "metrics disabled",
enabled: false,
wantError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Setup: Initialize metrics with enabled state
cfg := Config{
Enabled: tt.enabled,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
// Test InitRequestMetrics
err = InitRequestMetrics()
if tt.wantError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
// Cleanup
Shutdown(context.Background())
})
}
}
func TestRecordInboundRequest(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
err = InitRequestMetrics()
require.NoError(t, err)
ctx := context.Background()
host := "example.com"
// Test: Record inbound request
RecordInboundRequest(ctx, host)
// Verify: No error should occur
// Note: We can't easily verify the metric value without exporting,
// but we can verify the function doesn't panic
assert.NotPanics(t, func() {
RecordInboundRequest(ctx, host)
})
}
func TestRecordInboundSignValidation(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
err = InitRequestMetrics()
require.NoError(t, err)
ctx := context.Background()
host := "example.com"
// Test: Record sign validation
RecordInboundSignValidation(ctx, host)
// Verify: No error should occur
assert.NotPanics(t, func() {
RecordInboundSignValidation(ctx, host)
})
}
func TestRecordInboundSchemaValidation(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
err = InitRequestMetrics()
require.NoError(t, err)
ctx := context.Background()
host := "example.com"
// Test: Record schema validation
RecordInboundSchemaValidation(ctx, host)
// Verify: No error should occur
assert.NotPanics(t, func() {
RecordInboundSchemaValidation(ctx, host)
})
}
func TestRecordOutboundRequest(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
err = InitRequestMetrics()
require.NoError(t, err)
ctx := context.Background()
host := "example.com"
tests := []struct {
name string
statusCode int
duration time.Duration
}{
{
name: "2XX status code",
statusCode: 200,
duration: 100 * time.Millisecond,
},
{
name: "4XX status code",
statusCode: 404,
duration: 50 * time.Millisecond,
},
{
name: "5XX status code",
statusCode: 500,
duration: 200 * time.Millisecond,
},
{
name: "3XX status code",
statusCode: 301,
duration: 75 * time.Millisecond,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test: Record outbound request
RecordOutboundRequest(ctx, host, tt.statusCode, tt.duration)
// Verify: No error should occur
assert.NotPanics(t, func() {
RecordOutboundRequest(ctx, host, tt.statusCode, tt.duration)
})
})
}
}
func TestHTTPTransport_RoundTrip(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
err = InitRequestMetrics()
require.NoError(t, err)
// Create a test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}))
defer server.Close()
// Create transport wrapper
transport := &HTTPTransport{
Transport: http.DefaultTransport,
}
// Create request
req, err := http.NewRequest("GET", server.URL, nil)
require.NoError(t, err)
req = req.WithContext(context.Background())
// Test: RoundTrip should track metrics
resp, err := transport.RoundTrip(req)
require.NoError(t, err)
require.NotNil(t, resp)
assert.Equal(t, http.StatusOK, resp.StatusCode)
// Verify: Metrics should be recorded
assert.NotPanics(t, func() {
resp, err = transport.RoundTrip(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
})
}
func TestHTTPTransport_RoundTrip_Error(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
err = InitRequestMetrics()
require.NoError(t, err)
// Create transport with invalid URL to cause error
transport := &HTTPTransport{
Transport: http.DefaultTransport,
}
// Create request with invalid URL
req, err := http.NewRequest("GET", "http://invalid-host-that-does-not-exist:9999", nil)
require.NoError(t, err)
req = req.WithContext(context.Background())
// Test: RoundTrip should handle error and still record metrics
resp, err := transport.RoundTrip(req)
assert.Error(t, err)
assert.Nil(t, resp)
// Verify: Metrics should still be recorded (with 500 status)
assert.NotPanics(t, func() {
_, _ = transport.RoundTrip(req)
})
}
func TestWrapHTTPTransport_Enabled(t *testing.T) {
// Setup
cfg := Config{
Enabled: true,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
// Create a new transport
transport := http.DefaultTransport.(*http.Transport).Clone()
// Test: Wrap transport
wrapped := WrapHTTPTransport(transport)
// Verify: Should be wrapped
assert.NotEqual(t, transport, wrapped)
_, ok := wrapped.(*HTTPTransport)
assert.True(t, ok, "Should be wrapped with HTTPTransport")
}
func TestWrapHTTPTransport_Disabled(t *testing.T) {
// Setup: Initialize metrics with disabled state
cfg := Config{
Enabled: false,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
// Create a new transport
transport := http.DefaultTransport.(*http.Transport).Clone()
// Test: Wrap transport when metrics disabled
wrapped := WrapHTTPTransport(transport)
// Verify: When metrics are disabled, IsEnabled() returns false
// So WrapHTTPTransport should return the original transport
// Note: This test verifies the behavior when IsEnabled() returns false
if !IsEnabled() {
assert.Equal(t, transport, wrapped, "Should return original transport when metrics disabled")
} else {
// If metrics are still enabled from previous test, just verify it doesn't panic
assert.NotNil(t, wrapped)
}
}
func TestRecordInboundRequest_WhenDisabled(t *testing.T) {
// Setup: Metrics disabled
cfg := Config{
Enabled: false,
ExporterType: ExporterPrometheus,
ServiceName: "test-service",
}
err := InitMetrics(cfg)
require.NoError(t, err)
defer Shutdown(context.Background())
ctx := context.Background()
host := "example.com"
// Test: Should not panic when metrics are disabled
assert.NotPanics(t, func() {
RecordInboundRequest(ctx, host)
RecordInboundSignValidation(ctx, host)
RecordInboundSchemaValidation(ctx, host)
RecordOutboundRequest(ctx, host, 200, time.Second)
})
}