The Gin framework uses a global mode setting (gin.SetMode()) which is not thread-safe when tests run in parallel. Removing t.Parallel() from metrics tests that use gin.SetMode() prevents data races when running tests with the race detector enabled. All tests now pass with 'make test' which includes -race flag.
119 lines
2.4 KiB
Go
119 lines
2.4 KiB
Go
package metrics
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func TestNewMetrics(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
metrics := NewMetrics()
|
|
if metrics == nil {
|
|
t.Fatal("Expected metrics, got nil")
|
|
}
|
|
|
|
if metrics.registry == nil {
|
|
t.Error("Expected registry, got nil")
|
|
}
|
|
|
|
if metrics.httpRequestDuration == nil {
|
|
t.Error("Expected httpRequestDuration, got nil")
|
|
}
|
|
|
|
if metrics.httpRequestTotal == nil {
|
|
t.Error("Expected httpRequestTotal, got nil")
|
|
}
|
|
|
|
if metrics.httpErrorsTotal == nil {
|
|
t.Error("Expected httpErrorsTotal, got nil")
|
|
}
|
|
}
|
|
|
|
func TestMetrics_HTTPMiddleware(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
metrics := NewMetrics()
|
|
|
|
router := gin.New()
|
|
router.Use(metrics.HTTPMiddleware())
|
|
|
|
router.GET("/test", func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{"message": "test"})
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/test", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status 200, got %d", w.Code)
|
|
}
|
|
|
|
// Verify metrics were recorded
|
|
// We can't easily verify the internal metrics without exposing them,
|
|
// but we can verify the middleware doesn't panic
|
|
}
|
|
|
|
func TestMetrics_HTTPMiddleware_Error(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
metrics := NewMetrics()
|
|
|
|
router := gin.New()
|
|
router.Use(metrics.HTTPMiddleware())
|
|
|
|
router.GET("/error", func(c *gin.Context) {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "test error"})
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/error", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusInternalServerError {
|
|
t.Errorf("Expected status 500, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestMetrics_Handler(t *testing.T) {
|
|
metrics := NewMetrics()
|
|
|
|
handler := metrics.Handler()
|
|
if handler == nil {
|
|
t.Error("Expected handler, got nil")
|
|
}
|
|
|
|
// Test that the handler can be called
|
|
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status 200, got %d", w.Code)
|
|
}
|
|
|
|
// Verify Prometheus format
|
|
body := w.Body.String()
|
|
// Prometheus handler may return empty body if no metrics are registered yet
|
|
// This is acceptable - we just verify the handler works
|
|
_ = body
|
|
}
|
|
|
|
func TestMetrics_Registry(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
metrics := NewMetrics()
|
|
|
|
registry := metrics.Registry()
|
|
if registry == nil {
|
|
t.Error("Expected registry, got nil")
|
|
}
|
|
}
|