chore: Refactor test setup for Gin framework

- Removed redundant `gin.SetMode(gin.TestMode)` calls from individual test files.
- Introduced a centralized `TestMain` function in `testmain_test.go` to set the Gin mode for all tests.
- Ensured consistent test environment setup across various handler test files.
This commit is contained in:
GitHub Actions
2026-03-25 22:00:07 +00:00
parent f40fca844f
commit e6c4e46dd8
93 changed files with 58 additions and 1203 deletions

View File

@@ -68,6 +68,11 @@ type CrowdsecHandler struct {
LAPIPollInterval time.Duration // For testing; 0 means 500ms default
dashCache *dashboardCache
// validateLAPIURL validates and parses a LAPI base URL.
// This field allows tests to inject a permissive validator for mock servers
// without mutating package-level state (which causes data races).
validateLAPIURL func(string) (*url.URL, error)
// registrationMutex protects concurrent bouncer registration attempts
registrationMutex sync.Mutex
@@ -85,6 +90,14 @@ const (
bouncerName = "caddy-bouncer"
)
// resolveLAPIURLValidator returns the handler's validator or the default.
func (h *CrowdsecHandler) resolveLAPIURLValidator(raw string) (*url.URL, error) {
if h.validateLAPIURL != nil {
return h.validateLAPIURL(raw)
}
return validateCrowdsecLAPIBaseURLDefault(raw)
}
func (h *CrowdsecHandler) bouncerKeyPath() string {
if h != nil && strings.TrimSpace(h.DataDir) != "" {
return filepath.Join(h.DataDir, "bouncer_key")
@@ -371,15 +384,16 @@ func NewCrowdsecHandler(db *gorm.DB, executor CrowdsecExecutor, binPath, dataDir
consoleSvc = crowdsec.NewConsoleEnrollmentService(db, &crowdsec.SecureCommandExecutor{}, dataDir, consoleSecret)
}
return &CrowdsecHandler{
DB: db,
Executor: executor,
CmdExec: &RealCommandExecutor{},
BinPath: binPath,
DataDir: dataDir,
Hub: hubSvc,
Console: consoleSvc,
Security: securitySvc,
dashCache: newDashboardCache(),
DB: db,
Executor: executor,
CmdExec: &RealCommandExecutor{},
BinPath: binPath,
DataDir: dataDir,
Hub: hubSvc,
Console: consoleSvc,
Security: securitySvc,
dashCache: newDashboardCache(),
validateLAPIURL: validateCrowdsecLAPIBaseURLDefault,
}
}
@@ -1444,18 +1458,10 @@ const (
defaultCrowdsecLAPIPort = 8085
)
// validateCrowdsecLAPIBaseURLFunc is a variable holding the LAPI URL validation function.
// This indirection allows tests to inject a permissive validator for mock servers.
var validateCrowdsecLAPIBaseURLFunc = validateCrowdsecLAPIBaseURLDefault
func validateCrowdsecLAPIBaseURLDefault(raw string) (*url.URL, error) {
return security.ValidateInternalServiceBaseURL(raw, defaultCrowdsecLAPIPort, security.InternalServiceHostAllowlist())
}
func validateCrowdsecLAPIBaseURL(raw string) (*url.URL, error) {
return validateCrowdsecLAPIBaseURLFunc(raw)
}
// GetLAPIDecisions queries CrowdSec LAPI directly for current decisions.
// This is an alternative to ListDecisions which uses cscli.
// Query params:
@@ -1473,7 +1479,7 @@ func (h *CrowdsecHandler) GetLAPIDecisions(c *gin.Context) {
}
}
baseURL, err := validateCrowdsecLAPIBaseURL(lapiURL)
baseURL, err := h.resolveLAPIURLValidator(lapiURL)
if err != nil {
logger.Log().WithError(err).WithField("lapi_url", lapiURL).Warn("Blocked CrowdSec LAPI URL by internal allowlist policy")
// Fallback to cscli-based method.
@@ -2144,7 +2150,7 @@ func (h *CrowdsecHandler) CheckLAPIHealth(c *gin.Context) {
ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second)
defer cancel()
baseURL, err := validateCrowdsecLAPIBaseURL(lapiURL)
baseURL, err := h.resolveLAPIURLValidator(lapiURL)
if err != nil {
c.JSON(http.StatusOK, gin.H{"healthy": false, "error": "invalid LAPI URL (blocked by SSRF policy)", "lapi_url": lapiURL})
return