347 lines
7.9 KiB
Go
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)
|
|
})
|
|
}
|