diff --git a/internal/serviceconfig/observability/prometheus/prometheus_test.go b/internal/serviceconfig/observability/prometheus/prometheus_test.go index 1a02690b..2069d090 100644 --- a/internal/serviceconfig/observability/prometheus/prometheus_test.go +++ b/internal/serviceconfig/observability/prometheus/prometheus_test.go @@ -4,23 +4,46 @@ import ( "context" "fmt" "io" + "net" "net/http" "strings" "testing" "time" ) +func GetFreePortForTesting() (int, error) { + // Create a TCP listener on port 0 (lets OS choose a free port) + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + return 0, fmt.Errorf("failed to resolve TCP address: %v", err) + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return 0, fmt.Errorf("failed to create TCP listener: %v", err) + } + defer l.Close() + + // Get the port that was assigned by the OS + return l.Addr().(*net.TCPAddr).Port, nil +} + func TestMetricsIntegration(t *testing.T) { // Create a context with cancellation for the test ctx, cancel := context.WithCancel(context.Background()) defer cancel() + testingPort, errorGettingPort := GetFreePortForTesting() + if errorGettingPort != nil { + t.Fatalf("Failed to get a free port for testing: %v", errorGettingPort) + } + // Step 1: Define our test metrics configuration config := MetricsConfig{ Namespace: "test", Subsystem: "metrics", - Port: 9090, // Using 9090 for tests - ServeHttp: true, // Enable the built-in HTTP server + Port: testingPort, // Using 9090 for tests + ServeHttp: true, // Enable the built-in HTTP server Definitions: []MetricDefinition{ { // Counter example: counting total events @@ -114,7 +137,8 @@ func TestMetricsIntegration(t *testing.T) { time.Sleep(time.Second) // Step 5: Fetch metrics from the HTTP endpoint - resp, err := http.Get("http://localhost:9090/metrics") + URLForMetrics := fmt.Sprintf("http://localhost:%d/metrics", testingPort) + resp, err := http.Get(URLForMetrics) if err != nil { t.Fatalf("Failed to fetch metrics: %v", err) } @@ -155,10 +179,15 @@ func TestMetricsIntegration(t *testing.T) { // Test cancellation t.Run("Context cancellation", func(t *testing.T) { // Create a new metrics instance with a separate context + testingPort, errorGettingPort := GetFreePortForTesting() + if errorGettingPort != nil { + t.Fatalf("Failed to get a free port for testing: %v", errorGettingPort) + } + cancelCtx, cancelFunc := context.WithCancel(context.Background()) _, err := New(cancelCtx, MetricsConfig{ Namespace: "test_cancel", - Port: 9091, + Port: testingPort, ServeHttp: true, }) if err != nil { @@ -173,7 +202,8 @@ func TestMetricsIntegration(t *testing.T) { // Try to connect to the server - it should fail after a short delay time.Sleep(time.Second) - _, err = http.Get("http://localhost:9091/metrics") + testingUrl := fmt.Sprintf("http://localhost:%d/metrics", testingPort) + _, err = http.Get(testingUrl) if err == nil { t.Error("Expected server to be shutdown after context cancellation") }