Skip to content

Commit 87556c4

Browse files
authored
tests: fix race condition on macOS (#2242)
1 parent c099d66 commit 87556c4

1 file changed

Lines changed: 50 additions & 51 deletions

File tree

caddy/caddy_test.go

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,25 @@ import (
2020
"github.com/stretchr/testify/require"
2121
)
2222

23-
// waitForServerReady polls the server with retries until it responds to HTTP requests.
24-
// This handles a race condition during Caddy config reload on macOS where SO_REUSEPORT
25-
// can briefly route connections to the old listener being shut down,
23+
// initServer initializes a Caddy test server and waits for it to be ready.
24+
// After InitServer, it polls the server to handle a race condition on macOS where
25+
// SO_REUSEPORT can briefly route connections to the old listener being shut down,
2626
// resulting in "connection reset by peer".
27-
func waitForServerReady(t *testing.T, url string) {
27+
func initServer(t *testing.T, tester *caddytest.Tester, config string, format string) {
2828
t.Helper()
29+
tester.InitServer(config, format)
2930

3031
client := &http.Client{Timeout: 1 * time.Second}
31-
for range 10 {
32-
resp, err := client.Get(url)
33-
if err == nil {
34-
require.NoError(t, resp.Body.Close())
35-
36-
return
32+
require.Eventually(t, func() bool {
33+
resp, err := client.Get("http://localhost:" + testPort)
34+
if err != nil {
35+
return false
3736
}
3837

39-
time.Sleep(100 * time.Millisecond)
40-
}
38+
require.NoError(t, resp.Body.Close())
39+
40+
return true
41+
}, 5*time.Second, 100*time.Millisecond, "server failed to become ready")
4142
}
4243

4344
var testPort = "9080"
@@ -74,7 +75,7 @@ func TestMain(m *testing.M) {
7475
func TestPHP(t *testing.T) {
7576
var wg sync.WaitGroup
7677
tester := caddytest.NewTester(t)
77-
tester.InitServer(`
78+
initServer(t, tester, `
7879
{
7980
skip_install_trust
8081
admin localhost:2999
@@ -104,7 +105,7 @@ func TestPHP(t *testing.T) {
104105

105106
func TestLargeRequest(t *testing.T) {
106107
tester := caddytest.NewTester(t)
107-
tester.InitServer(`
108+
initServer(t, tester, `
108109
{
109110
skip_install_trust
110111
admin localhost:2999
@@ -133,7 +134,7 @@ func TestLargeRequest(t *testing.T) {
133134
func TestWorker(t *testing.T) {
134135
var wg sync.WaitGroup
135136
tester := caddytest.NewTester(t)
136-
tester.InitServer(`
137+
initServer(t, tester, `
137138
{
138139
skip_install_trust
139140
admin localhost:2999
@@ -170,7 +171,7 @@ func TestGlobalAndModuleWorker(t *testing.T) {
170171
testPortNum, _ := strconv.Atoi(testPort)
171172
testPortTwo := strconv.Itoa(testPortNum + 1)
172173
tester := caddytest.NewTester(t)
173-
tester.InitServer(`
174+
initServer(t, tester, `
174175
{
175176
skip_install_trust
176177
admin localhost:2999
@@ -220,7 +221,7 @@ func TestGlobalAndModuleWorker(t *testing.T) {
220221

221222
func TestModuleWorkerInheritsEnv(t *testing.T) {
222223
tester := caddytest.NewTester(t)
223-
tester.InitServer(`
224+
initServer(t, tester, `
224225
{
225226
skip_install_trust
226227
admin localhost:2999
@@ -245,7 +246,7 @@ func TestNamedModuleWorkers(t *testing.T) {
245246
testPortNum, _ := strconv.Atoi(testPort)
246247
testPortTwo := strconv.Itoa(testPortNum + 1)
247248
tester := caddytest.NewTester(t)
248-
tester.InitServer(`
249+
initServer(t, tester, `
249250
{
250251
skip_install_trust
251252
admin localhost:2999
@@ -294,7 +295,7 @@ func TestNamedModuleWorkers(t *testing.T) {
294295

295296
func TestEnv(t *testing.T) {
296297
tester := caddytest.NewTester(t)
297-
tester.InitServer(`
298+
initServer(t, tester, `
298299
{
299300
skip_install_trust
300301
admin localhost:2999
@@ -325,7 +326,7 @@ func TestEnv(t *testing.T) {
325326

326327
func TestJsonEnv(t *testing.T) {
327328
tester := caddytest.NewTester(t)
328-
tester.InitServer(`
329+
initServer(t, tester, `
329330
{
330331
"admin": {
331332
"listen": "localhost:2999"
@@ -408,7 +409,7 @@ func TestJsonEnv(t *testing.T) {
408409

409410
func TestCustomCaddyVariablesInEnv(t *testing.T) {
410411
tester := caddytest.NewTester(t)
411-
tester.InitServer(`
412+
initServer(t, tester, `
412413
{
413414
skip_install_trust
414415
admin localhost:2999
@@ -442,7 +443,7 @@ func TestCustomCaddyVariablesInEnv(t *testing.T) {
442443

443444
func TestPHPServerDirective(t *testing.T) {
444445
tester := caddytest.NewTester(t)
445-
tester.InitServer(`
446+
initServer(t, tester, `
446447
{
447448
skip_install_trust
448449
admin localhost:2999
@@ -456,15 +457,14 @@ func TestPHPServerDirective(t *testing.T) {
456457
}
457458
`, "caddyfile")
458459

459-
waitForServerReady(t, "http://localhost:"+testPort)
460460
tester.AssertGetResponse("http://localhost:"+testPort, http.StatusOK, "I am by birth a Genevese (i not set)")
461461
tester.AssertGetResponse("http://localhost:"+testPort+"/hello.txt", http.StatusOK, "Hello\n")
462462
tester.AssertGetResponse("http://localhost:"+testPort+"/not-found.txt", http.StatusOK, "I am by birth a Genevese (i not set)")
463463
}
464464

465465
func TestPHPServerDirectiveDisableFileServer(t *testing.T) {
466466
tester := caddytest.NewTester(t)
467-
tester.InitServer(`
467+
initServer(t, tester, `
468468
{
469469
skip_install_trust
470470
admin localhost:2999
@@ -482,15 +482,14 @@ func TestPHPServerDirectiveDisableFileServer(t *testing.T) {
482482
}
483483
`, "caddyfile")
484484

485-
waitForServerReady(t, "http://localhost:"+testPort)
486485
tester.AssertGetResponse("http://localhost:"+testPort, http.StatusOK, "I am by birth a Genevese (i not set)")
487486
tester.AssertGetResponse("http://localhost:"+testPort+"/not-found.txt", http.StatusOK, "I am by birth a Genevese (i not set)")
488487
}
489488

490489
func TestMetrics(t *testing.T) {
491490
var wg sync.WaitGroup
492491
tester := caddytest.NewTester(t)
493-
tester.InitServer(`
492+
initServer(t, tester, `
494493
{
495494
skip_install_trust
496495
admin localhost:2999
@@ -571,7 +570,7 @@ func TestMetrics(t *testing.T) {
571570
func TestWorkerMetrics(t *testing.T) {
572571
var wg sync.WaitGroup
573572
tester := caddytest.NewTester(t)
574-
tester.InitServer(`
573+
initServer(t, tester, `
575574
{
576575
skip_install_trust
577576
admin localhost:2999
@@ -672,7 +671,7 @@ func TestWorkerMetrics(t *testing.T) {
672671
func TestNamedWorkerMetrics(t *testing.T) {
673672
var wg sync.WaitGroup
674673
tester := caddytest.NewTester(t)
675-
tester.InitServer(`
674+
initServer(t, tester, `
676675
{
677676
skip_install_trust
678677
admin localhost:2999
@@ -767,7 +766,7 @@ func TestNamedWorkerMetrics(t *testing.T) {
767766
func TestAutoWorkerConfig(t *testing.T) {
768767
var wg sync.WaitGroup
769768
tester := caddytest.NewTester(t)
770-
tester.InitServer(`
769+
initServer(t, tester, `
771770
{
772771
skip_install_trust
773772
admin localhost:2999
@@ -868,7 +867,7 @@ func TestAllDefinedServerVars(t *testing.T) {
868867
expectedBody = strings.ReplaceAll(expectedBody, "{testPort}", testPort)
869868
expectedBody = strings.ReplaceAll(expectedBody, documentRoot+"/", documentRoot+string(filepath.Separator))
870869
tester := caddytest.NewTester(t)
871-
tester.InitServer(`
870+
initServer(t, tester, `
872871
{
873872
skip_install_trust
874873
admin localhost:2999
@@ -900,7 +899,7 @@ func TestAllDefinedServerVars(t *testing.T) {
900899

901900
func TestPHPIniConfiguration(t *testing.T) {
902901
tester := caddytest.NewTester(t)
903-
tester.InitServer(`
902+
initServer(t, tester, `
904903
{
905904
skip_install_trust
906905
admin localhost:2999
@@ -928,7 +927,7 @@ func TestPHPIniConfiguration(t *testing.T) {
928927

929928
func TestPHPIniBlockConfiguration(t *testing.T) {
930929
tester := caddytest.NewTester(t)
931-
tester.InitServer(`
930+
initServer(t, tester, `
932931
{
933932
skip_install_trust
934933
admin localhost:2999
@@ -968,7 +967,7 @@ func testSingleIniConfiguration(tester *caddytest.Tester, key string, value stri
968967

969968
func TestOsEnv(t *testing.T) {
970969
tester := caddytest.NewTester(t)
971-
tester.InitServer(`
970+
initServer(t, tester, `
972971
{
973972
skip_install_trust
974973
admin localhost:2999
@@ -998,7 +997,7 @@ func TestOsEnv(t *testing.T) {
998997

999998
func TestMaxWaitTime(t *testing.T) {
1000999
tester := caddytest.NewTester(t)
1001-
tester.InitServer(`
1000+
initServer(t, tester, `
10021001
{
10031002
skip_install_trust
10041003
admin localhost:2999
@@ -1039,7 +1038,7 @@ func TestMaxWaitTime(t *testing.T) {
10391038

10401039
func TestMaxWaitTimeWorker(t *testing.T) {
10411040
tester := caddytest.NewTester(t)
1042-
tester.InitServer(`
1041+
initServer(t, tester, `
10431042
{
10441043
skip_install_trust
10451044
admin localhost:2999
@@ -1122,7 +1121,7 @@ func getStatusCode(url string, t *testing.T) int {
11221121
func TestMultiWorkersMetrics(t *testing.T) {
11231122
var wg sync.WaitGroup
11241123
tester := caddytest.NewTester(t)
1125-
tester.InitServer(`
1124+
initServer(t, tester, `
11261125
{
11271126
skip_install_trust
11281127
admin localhost:2999
@@ -1231,7 +1230,7 @@ func TestMultiWorkersMetrics(t *testing.T) {
12311230
func TestDisabledMetrics(t *testing.T) {
12321231
var wg sync.WaitGroup
12331232
tester := caddytest.NewTester(t)
1234-
tester.InitServer(`
1233+
initServer(t, tester, `
12351234
{
12361235
skip_install_trust
12371236
admin localhost:2999
@@ -1311,7 +1310,7 @@ func TestDisabledMetrics(t *testing.T) {
13111310
func TestWorkerRestart(t *testing.T) {
13121311
var wg sync.WaitGroup
13131312
tester := caddytest.NewTester(t)
1314-
tester.InitServer(`
1313+
initServer(t, tester, `
13151314
{
13161315
skip_install_trust
13171316
admin localhost:2999
@@ -1413,7 +1412,7 @@ func TestWorkerRestart(t *testing.T) {
14131412

14141413
func TestWorkerMatchDirective(t *testing.T) {
14151414
tester := caddytest.NewTester(t)
1416-
tester.InitServer(`
1415+
initServer(t, tester, `
14171416
{
14181417
skip_install_trust
14191418
admin localhost:2999
@@ -1446,7 +1445,7 @@ func TestWorkerMatchDirective(t *testing.T) {
14461445

14471446
func TestWorkerMatchDirectiveWithMultipleWorkers(t *testing.T) {
14481447
tester := caddytest.NewTester(t)
1449-
tester.InitServer(`
1448+
initServer(t, tester, `
14501449
{
14511450
skip_install_trust
14521451
admin localhost:2999
@@ -1487,7 +1486,7 @@ func TestWorkerMatchDirectiveWithMultipleWorkers(t *testing.T) {
14871486

14881487
func TestWorkerMatchDirectiveWithoutFileServer(t *testing.T) {
14891488
tester := caddytest.NewTester(t)
1490-
tester.InitServer(`
1489+
initServer(t, tester, `
14911490
{
14921491
skip_install_trust
14931492
admin localhost:2999
@@ -1520,7 +1519,7 @@ func TestWorkerMatchDirectiveWithoutFileServer(t *testing.T) {
15201519

15211520
func TestDd(t *testing.T) {
15221521
tester := caddytest.NewTester(t)
1523-
tester.InitServer(`
1522+
initServer(t, tester, `
15241523
{
15251524
skip_install_trust
15261525
admin localhost:2999
@@ -1544,7 +1543,7 @@ func TestDd(t *testing.T) {
15441543

15451544
func TestLog(t *testing.T) {
15461545
tester := caddytest.NewTester(t)
1547-
tester.InitServer(`
1546+
initServer(t, tester, `
15481547
{
15491548
skip_install_trust
15501549
admin localhost:2999
@@ -1582,7 +1581,7 @@ func TestSymlinkWorkerPaths(t *testing.T) {
15821581
// When I execute `frankenphp php-server --listen localhost:8080 -w index.php` from `public`
15831582
// Then I expect to see the worker script executed successfully
15841583
tester := caddytest.NewTester(t)
1585-
tester.InitServer(`
1584+
initServer(t, tester, `
15861585
{
15871586
skip_install_trust
15881587
admin localhost:2999
@@ -1612,7 +1611,7 @@ func TestSymlinkWorkerPaths(t *testing.T) {
16121611
// When I execute `frankenphp --listen localhost:8080 -w nested/index.php` from `public`
16131612
// Then I expect to see the worker script executed successfully
16141613
tester := caddytest.NewTester(t)
1615-
tester.InitServer(`
1614+
initServer(t, tester, `
16161615
{
16171616
skip_install_trust
16181617
admin localhost:2999
@@ -1642,7 +1641,7 @@ func TestSymlinkWorkerPaths(t *testing.T) {
16421641
// When I execute `frankenphp --listen localhost:8080 -w public/index.php` from the root folder
16431642
// Then I expect to see the worker script executed successfully
16441643
tester := caddytest.NewTester(t)
1645-
tester.InitServer(`
1644+
initServer(t, tester, `
16461645
{
16471646
skip_install_trust
16481647
admin localhost:2999
@@ -1676,7 +1675,7 @@ func TestSymlinkWorkerPaths(t *testing.T) {
16761675
// When I execute `frankenphp --listen localhost:8080 -w public/index.php -r public` from the root folder
16771676
// Then I expect to see the worker script executed successfully
16781677
tester := caddytest.NewTester(t)
1679-
tester.InitServer(`
1678+
initServer(t, tester, `
16801679
{
16811680
skip_install_trust
16821681
admin localhost:2999
@@ -1715,7 +1714,7 @@ func TestSymlinkResolveRoot(t *testing.T) {
17151714
t.Run("ResolveRootSymlink", func(t *testing.T) {
17161715
// Tests that resolve_root_symlink directive works correctly
17171716
tester := caddytest.NewTester(t)
1718-
tester.InitServer(`
1717+
initServer(t, tester, `
17191718
{
17201719
skip_install_trust
17211720
admin localhost:2999
@@ -1743,7 +1742,7 @@ func TestSymlinkResolveRoot(t *testing.T) {
17431742
t.Run("NoResolveRootSymlink", func(t *testing.T) {
17441743
// Tests that symlinks are preserved when resolve_root_symlink is false (non-worker mode)
17451744
tester := caddytest.NewTester(t)
1746-
tester.InitServer(`
1745+
initServer(t, tester, `
17471746
{
17481747
skip_install_trust
17491748
admin localhost:2999
@@ -1774,7 +1773,7 @@ func TestSymlinkWorkerBehavior(t *testing.T) {
17741773
t.Run("WorkerScriptFailsWithoutWorkerMode", func(t *testing.T) {
17751774
// Tests that accessing a worker-only script without configuring it as a worker actually results in an error
17761775
tester := caddytest.NewTester(t)
1777-
tester.InitServer(`
1776+
initServer(t, tester, `
17781777
{
17791778
skip_install_trust
17801779
admin localhost:2999
@@ -1798,7 +1797,7 @@ func TestSymlinkWorkerBehavior(t *testing.T) {
17981797
t.Run("MultipleRequests", func(t *testing.T) {
17991798
// Tests that symlinked workers handle multiple requests correctly
18001799
tester := caddytest.NewTester(t)
1801-
tester.InitServer(`
1800+
initServer(t, tester, `
18021801
{
18031802
skip_install_trust
18041803
admin localhost:2999

0 commit comments

Comments
 (0)