Test-quality audit: fix 2 prod bugs, strengthen weak tests, add mutation/fuzz/CI tooling (#5345)

* test(audit): add gremlins/rapid/coverage tooling + AUDIT.md scaffold

* test(audit): hygiene sweep (race-clean except logger global; Finding #2) + smell inventory

* test(audit): cover untested error/edge branches (TLS proxy+pin, migration tag cleanup=Finding #1)

* test(audit): strengthen internal/sub link tests (dedup key, TLS/Reality mapping, clash well-formedness)

* test(audit): property (rapid) + fuzz tests for joinHostPort/userinfo/pin/ParseLink

* test(audit): tighten frontend subSortIndex rejection assertions + wire coverage

* ci(audit): add shuffle gate + non-blocking race job (Finding #2) + fuzz-smoke; document mutation policy

* chore(audit): gitignore frontend coverage output

* test(audit): exhaustive whole-repo pass — strengthen 5 weak/fake tests (netproxy, CSP, modal per-protocol loops, schema coercions)

* docs(contributing): add Testing section (conventions, race/shuffle, fuzz, mutation policy); drop AUDIT.md ledger

* fix(logger,migration): guard logBuffer with mutex; execute legacy tag cleanup (tx.Exec); make CI race gate blocking

* ci(mutation): add nightly scoped gremlins workflow (informational artifacts)

* test(audit): strengthen runtime tests — baseURL scheme/port bounds, isNonEmptySlice, trafficReset

* test(audit): strengthen clash tests — reality field mapping + tcp-header validation

* test(audit): runtime — egress-proxy + content-type tests; drop redundant bp=='' branch

* test(audit): strengthen link parser/helper tests (defaultPort, splitComma, base64, canonicalQuery, tls/reality/transport mapping)

* test(audit): strengthen sub/xray/common/netsafe/mtproto/config/middleware tests (kill surviving mutants)

* test(audit): raise timeout on protocol-iteration modal tests (heavy re-renders, slow on CI)

* fix(logger): GetLogs returns at most c entries (off-by-one fix; addresses PR review)

* perf(logger): snapshot logBuffer under lock so GetLogs doesn't block logging; clarify fuzz-seed docs (addresses PR review)
This commit is contained in:
Sanaei
2026-06-15 15:17:03 +02:00
committed by GitHub
parent b5872af279
commit 7605902324
37 changed files with 2580 additions and 330 deletions
+30
View File
@@ -3,6 +3,7 @@ package middleware
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/mhsanaei/3x-ui/v3/internal/web/session"
@@ -80,7 +81,9 @@ func TestSecurityHeadersMiddleware(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(SecurityHeadersMiddleware(true))
var capturedNonce string
router.GET("/", func(c *gin.Context) {
capturedNonce = c.GetString("csp_nonce")
c.String(http.StatusOK, "ok")
})
@@ -101,6 +104,33 @@ func TestSecurityHeadersMiddleware(t *testing.T) {
if got := headers.Get("Strict-Transport-Security"); got == "" {
t.Fatal("Strict-Transport-Security should be set for direct HTTPS")
}
// CSP is the highest-value header here: assert it stays nonce-bound with its hardening
// directives, so weakening it (unsafe-inline, dropped frame-ancestors, broken nonce) fails.
csp := headers.Get("Content-Security-Policy")
if csp == "" {
t.Fatal("Content-Security-Policy header must be set")
}
if capturedNonce == "" {
t.Fatal("csp_nonce context value must be set (the injected inline script reads it)")
}
if want := "script-src 'self' 'nonce-" + capturedNonce + "'"; !strings.Contains(csp, want) {
t.Fatalf("CSP script-src must be bound to the per-request nonce %q; got %q", want, csp)
}
for _, directive := range []string{"object-src 'none'", "frame-ancestors 'none'", "base-uri 'self'", "form-action 'self'"} {
if !strings.Contains(csp, directive) {
t.Errorf("CSP missing hardening directive %q; got %q", directive, csp)
}
}
// script-src must NOT allow 'unsafe-inline' (it would defeat the nonce). Check the
// script-src directive in isolation, since style-src legitimately uses unsafe-inline.
scriptDir := csp[strings.Index(csp, "script-src"):]
if i := strings.Index(scriptDir, ";"); i >= 0 {
scriptDir = scriptDir[:i]
}
if strings.Contains(scriptDir, "unsafe-inline") {
t.Errorf("CSP script-src must not allow 'unsafe-inline': %q", scriptDir)
}
}
func TestSecurityHeadersMiddlewareSkipsHSTSWithoutDirectHTTPS(t *testing.T) {