diff --git a/caddy/caddy_test.go b/caddy/caddy_test.go index a55654d4a2..09bd59eeb6 100644 --- a/caddy/caddy_test.go +++ b/caddy/caddy_test.go @@ -20,24 +20,25 @@ import ( "github.com/stretchr/testify/require" ) -// waitForServerReady polls the server with retries until it responds to HTTP requests. -// This handles a race condition during Caddy config reload on macOS where SO_REUSEPORT -// can briefly route connections to the old listener being shut down, +// initServer initializes a Caddy test server and waits for it to be ready. +// After InitServer, it polls the server to handle a race condition on macOS where +// SO_REUSEPORT can briefly route connections to the old listener being shut down, // resulting in "connection reset by peer". -func waitForServerReady(t *testing.T, url string) { +func initServer(t *testing.T, tester *caddytest.Tester, config string, format string) { t.Helper() + tester.InitServer(config, format) client := &http.Client{Timeout: 1 * time.Second} - for range 10 { - resp, err := client.Get(url) - if err == nil { - require.NoError(t, resp.Body.Close()) - - return + require.Eventually(t, func() bool { + resp, err := client.Get("http://localhost:" + testPort) + if err != nil { + return false } - time.Sleep(100 * time.Millisecond) - } + require.NoError(t, resp.Body.Close()) + + return true + }, 5*time.Second, 100*time.Millisecond, "server failed to become ready") } var testPort = "9080" @@ -74,7 +75,7 @@ func TestMain(m *testing.M) { func TestPHP(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -104,7 +105,7 @@ func TestPHP(t *testing.T) { func TestLargeRequest(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -133,7 +134,7 @@ func TestLargeRequest(t *testing.T) { func TestWorker(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -170,7 +171,7 @@ func TestGlobalAndModuleWorker(t *testing.T) { testPortNum, _ := strconv.Atoi(testPort) testPortTwo := strconv.Itoa(testPortNum + 1) tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -220,7 +221,7 @@ func TestGlobalAndModuleWorker(t *testing.T) { func TestModuleWorkerInheritsEnv(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -245,7 +246,7 @@ func TestNamedModuleWorkers(t *testing.T) { testPortNum, _ := strconv.Atoi(testPort) testPortTwo := strconv.Itoa(testPortNum + 1) tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -294,7 +295,7 @@ func TestNamedModuleWorkers(t *testing.T) { func TestEnv(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -325,7 +326,7 @@ func TestEnv(t *testing.T) { func TestJsonEnv(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { "admin": { "listen": "localhost:2999" @@ -408,7 +409,7 @@ func TestJsonEnv(t *testing.T) { func TestCustomCaddyVariablesInEnv(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -442,7 +443,7 @@ func TestCustomCaddyVariablesInEnv(t *testing.T) { func TestPHPServerDirective(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -456,7 +457,6 @@ func TestPHPServerDirective(t *testing.T) { } `, "caddyfile") - waitForServerReady(t, "http://localhost:"+testPort) tester.AssertGetResponse("http://localhost:"+testPort, http.StatusOK, "I am by birth a Genevese (i not set)") tester.AssertGetResponse("http://localhost:"+testPort+"/hello.txt", http.StatusOK, "Hello\n") tester.AssertGetResponse("http://localhost:"+testPort+"/not-found.txt", http.StatusOK, "I am by birth a Genevese (i not set)") @@ -464,7 +464,7 @@ func TestPHPServerDirective(t *testing.T) { func TestPHPServerDirectiveDisableFileServer(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -482,7 +482,6 @@ func TestPHPServerDirectiveDisableFileServer(t *testing.T) { } `, "caddyfile") - waitForServerReady(t, "http://localhost:"+testPort) tester.AssertGetResponse("http://localhost:"+testPort, http.StatusOK, "I am by birth a Genevese (i not set)") tester.AssertGetResponse("http://localhost:"+testPort+"/not-found.txt", http.StatusOK, "I am by birth a Genevese (i not set)") } @@ -490,7 +489,7 @@ func TestPHPServerDirectiveDisableFileServer(t *testing.T) { func TestMetrics(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -571,7 +570,7 @@ func TestMetrics(t *testing.T) { func TestWorkerMetrics(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -672,7 +671,7 @@ func TestWorkerMetrics(t *testing.T) { func TestNamedWorkerMetrics(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -767,7 +766,7 @@ func TestNamedWorkerMetrics(t *testing.T) { func TestAutoWorkerConfig(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -868,7 +867,7 @@ func TestAllDefinedServerVars(t *testing.T) { expectedBody = strings.ReplaceAll(expectedBody, "{testPort}", testPort) expectedBody = strings.ReplaceAll(expectedBody, documentRoot+"/", documentRoot+string(filepath.Separator)) tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -900,7 +899,7 @@ func TestAllDefinedServerVars(t *testing.T) { func TestPHPIniConfiguration(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -928,7 +927,7 @@ func TestPHPIniConfiguration(t *testing.T) { func TestPHPIniBlockConfiguration(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -968,7 +967,7 @@ func testSingleIniConfiguration(tester *caddytest.Tester, key string, value stri func TestOsEnv(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -998,7 +997,7 @@ func TestOsEnv(t *testing.T) { func TestMaxWaitTime(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1039,7 +1038,7 @@ func TestMaxWaitTime(t *testing.T) { func TestMaxWaitTimeWorker(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1122,7 +1121,7 @@ func getStatusCode(url string, t *testing.T) int { func TestMultiWorkersMetrics(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1231,7 +1230,7 @@ func TestMultiWorkersMetrics(t *testing.T) { func TestDisabledMetrics(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1311,7 +1310,7 @@ func TestDisabledMetrics(t *testing.T) { func TestWorkerRestart(t *testing.T) { var wg sync.WaitGroup tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1413,7 +1412,7 @@ func TestWorkerRestart(t *testing.T) { func TestWorkerMatchDirective(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1446,7 +1445,7 @@ func TestWorkerMatchDirective(t *testing.T) { func TestWorkerMatchDirectiveWithMultipleWorkers(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1487,7 +1486,7 @@ func TestWorkerMatchDirectiveWithMultipleWorkers(t *testing.T) { func TestWorkerMatchDirectiveWithoutFileServer(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1520,7 +1519,7 @@ func TestWorkerMatchDirectiveWithoutFileServer(t *testing.T) { func TestDd(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1544,7 +1543,7 @@ func TestDd(t *testing.T) { func TestLog(t *testing.T) { tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1582,7 +1581,7 @@ func TestSymlinkWorkerPaths(t *testing.T) { // When I execute `frankenphp php-server --listen localhost:8080 -w index.php` from `public` // Then I expect to see the worker script executed successfully tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1612,7 +1611,7 @@ func TestSymlinkWorkerPaths(t *testing.T) { // When I execute `frankenphp --listen localhost:8080 -w nested/index.php` from `public` // Then I expect to see the worker script executed successfully tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1642,7 +1641,7 @@ func TestSymlinkWorkerPaths(t *testing.T) { // When I execute `frankenphp --listen localhost:8080 -w public/index.php` from the root folder // Then I expect to see the worker script executed successfully tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1676,7 +1675,7 @@ func TestSymlinkWorkerPaths(t *testing.T) { // When I execute `frankenphp --listen localhost:8080 -w public/index.php -r public` from the root folder // Then I expect to see the worker script executed successfully tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1715,7 +1714,7 @@ func TestSymlinkResolveRoot(t *testing.T) { t.Run("ResolveRootSymlink", func(t *testing.T) { // Tests that resolve_root_symlink directive works correctly tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1743,7 +1742,7 @@ func TestSymlinkResolveRoot(t *testing.T) { t.Run("NoResolveRootSymlink", func(t *testing.T) { // Tests that symlinks are preserved when resolve_root_symlink is false (non-worker mode) tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1774,7 +1773,7 @@ func TestSymlinkWorkerBehavior(t *testing.T) { t.Run("WorkerScriptFailsWithoutWorkerMode", func(t *testing.T) { // Tests that accessing a worker-only script without configuring it as a worker actually results in an error tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999 @@ -1798,7 +1797,7 @@ func TestSymlinkWorkerBehavior(t *testing.T) { t.Run("MultipleRequests", func(t *testing.T) { // Tests that symlinked workers handle multiple requests correctly tester := caddytest.NewTester(t) - tester.InitServer(` + initServer(t, tester, ` { skip_install_trust admin localhost:2999