@@ -144,20 +144,19 @@ func TestPortForward(t *testing.T) {
144
144
145
145
for _ , c := range cases { //nolint:paralleltest // the `c := c` confuses the linter
146
146
c := c
147
+ // Avoid parallel test here because setupLocal reserves
148
+ // a free open port which is not guaranteed to be free
149
+ // after the listener closes.
150
+ //nolint:paralleltest
147
151
t .Run (c .name , func (t * testing.T ) {
148
- t .Parallel ()
149
-
152
+ //nolint:paralleltest
150
153
t .Run ("OnePort" , func (t * testing.T ) {
151
- t .Parallel ()
152
154
var (
153
155
client = coderdtest .New (t , & coderdtest.Options {IncludeProvisionerD : true })
154
156
user = coderdtest .CreateFirstUser (t , client )
155
157
_ , workspace = runAgent (t , client , user .UserID )
156
- l1 , p1 = setupTestListener (t , c .setupRemote (t ))
158
+ p1 = setupTestListener (t , c .setupRemote (t ))
157
159
)
158
- t .Cleanup (func () {
159
- _ = l1 .Close ()
160
- })
161
160
162
161
// Create a flag that forwards from local to listener 1.
163
162
localAddress , localFlag := c .setupLocal (t )
@@ -171,9 +170,9 @@ func TestPortForward(t *testing.T) {
171
170
cmd .SetOut (io .MultiWriter (buf , os .Stderr ))
172
171
ctx , cancel := context .WithCancel (context .Background ())
173
172
defer cancel ()
173
+ errC := make (chan error )
174
174
go func () {
175
- err := cmd .ExecuteContext (ctx )
176
- assert .ErrorIs (t , err , context .Canceled )
175
+ errC <- cmd .ExecuteContext (ctx )
177
176
}()
178
177
waitForPortForwardReady (t , buf )
179
178
@@ -188,21 +187,21 @@ func TestPortForward(t *testing.T) {
188
187
defer c2 .Close ()
189
188
testDial (t , c2 )
190
189
testDial (t , c1 )
190
+
191
+ cancel ()
192
+ err = <- errC
193
+ require .ErrorIs (t , err , context .Canceled )
191
194
})
192
195
196
+ //nolint:paralleltest
193
197
t .Run ("TwoPorts" , func (t * testing.T ) {
194
- t .Parallel ()
195
198
var (
196
199
client = coderdtest .New (t , & coderdtest.Options {IncludeProvisionerD : true })
197
200
user = coderdtest .CreateFirstUser (t , client )
198
201
_ , workspace = runAgent (t , client , user .UserID )
199
- l1 , p1 = setupTestListener (t , c .setupRemote (t ))
200
- l2 , p2 = setupTestListener (t , c .setupRemote (t ))
202
+ p1 = setupTestListener (t , c .setupRemote (t ))
203
+ p2 = setupTestListener (t , c .setupRemote (t ))
201
204
)
202
- t .Cleanup (func () {
203
- _ = l1 .Close ()
204
- _ = l2 .Close ()
205
- })
206
205
207
206
// Create a flags for listener 1 and listener 2.
208
207
localAddress1 , localFlag1 := c .setupLocal (t )
@@ -218,9 +217,9 @@ func TestPortForward(t *testing.T) {
218
217
cmd .SetOut (io .MultiWriter (buf , os .Stderr ))
219
218
ctx , cancel := context .WithCancel (context .Background ())
220
219
defer cancel ()
220
+ errC := make (chan error )
221
221
go func () {
222
- err := cmd .ExecuteContext (ctx )
223
- assert .ErrorIs (t , err , context .Canceled )
222
+ errC <- cmd .ExecuteContext (ctx )
224
223
}()
225
224
waitForPortForwardReady (t , buf )
226
225
@@ -235,13 +234,17 @@ func TestPortForward(t *testing.T) {
235
234
defer c2 .Close ()
236
235
testDial (t , c2 )
237
236
testDial (t , c1 )
237
+
238
+ cancel ()
239
+ err = <- errC
240
+ require .ErrorIs (t , err , context .Canceled )
238
241
})
239
242
})
240
243
}
241
244
242
245
// Test doing a TCP -> Unix forward.
246
+ //nolint:paralleltest
243
247
t .Run ("TCP2Unix" , func (t * testing.T ) {
244
- t .Parallel ()
245
248
var (
246
249
client = coderdtest .New (t , & coderdtest.Options {IncludeProvisionerD : true })
247
250
user = coderdtest .CreateFirstUser (t , client )
@@ -253,11 +256,8 @@ func TestPortForward(t *testing.T) {
253
256
unixCase = cases [2 ]
254
257
255
258
// Setup remote Unix listener.
256
- l1 , p1 = setupTestListener (t , unixCase .setupRemote (t ))
259
+ p1 = setupTestListener (t , unixCase .setupRemote (t ))
257
260
)
258
- t .Cleanup (func () {
259
- _ = l1 .Close ()
260
- })
261
261
262
262
// Create a flag that forwards from local TCP to Unix listener 1.
263
263
// Notably this is a --unix flag.
@@ -272,9 +272,9 @@ func TestPortForward(t *testing.T) {
272
272
cmd .SetOut (io .MultiWriter (buf , os .Stderr ))
273
273
ctx , cancel := context .WithCancel (context .Background ())
274
274
defer cancel ()
275
+ errC := make (chan error )
275
276
go func () {
276
- err := cmd .ExecuteContext (ctx )
277
- assert .ErrorIs (t , err , context .Canceled )
277
+ errC <- cmd .ExecuteContext (ctx )
278
278
}()
279
279
waitForPortForwardReady (t , buf )
280
280
@@ -289,11 +289,15 @@ func TestPortForward(t *testing.T) {
289
289
defer c2 .Close ()
290
290
testDial (t , c2 )
291
291
testDial (t , c1 )
292
+
293
+ cancel ()
294
+ err = <- errC
295
+ require .ErrorIs (t , err , context .Canceled )
292
296
})
293
297
294
298
// Test doing TCP, UDP and Unix at the same time.
299
+ //nolint:paralleltest
295
300
t .Run ("All" , func (t * testing.T ) {
296
- t .Parallel ()
297
301
var (
298
302
client = coderdtest .New (t , & coderdtest.Options {IncludeProvisionerD : true })
299
303
user = coderdtest .CreateFirstUser (t , client )
@@ -311,10 +315,7 @@ func TestPortForward(t *testing.T) {
311
315
continue
312
316
}
313
317
314
- l , p := setupTestListener (t , c .setupRemote (t ))
315
- t .Cleanup (func () {
316
- _ = l .Close ()
317
- })
318
+ p := setupTestListener (t , c .setupRemote (t ))
318
319
319
320
localAddress , localFlag := c .setupLocal (t )
320
321
dials = append (dials , addr {
@@ -332,10 +333,9 @@ func TestPortForward(t *testing.T) {
332
333
cmd .SetOut (io .MultiWriter (buf , os .Stderr ))
333
334
ctx , cancel := context .WithCancel (context .Background ())
334
335
defer cancel ()
336
+ errC := make (chan error )
335
337
go func () {
336
- err := cmd .ExecuteContext (ctx )
337
- assert .Error (t , err )
338
- assert .ErrorIs (t , err , context .Canceled )
338
+ errC <- cmd .ExecuteContext (ctx )
339
339
}()
340
340
waitForPortForwardReady (t , buf )
341
341
@@ -357,6 +357,10 @@ func TestPortForward(t *testing.T) {
357
357
for i := len (conns ) - 1 ; i >= 0 ; i -- {
358
358
testDial (t , conns [i ])
359
359
}
360
+
361
+ cancel ()
362
+ err := <- errC
363
+ require .ErrorIs (t , err , context .Canceled )
360
364
})
361
365
}
362
366
@@ -400,11 +404,15 @@ func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) ([]coders
400
404
// Start workspace agent in a goroutine
401
405
cmd , root := clitest .New (t , "agent" , "--agent-token" , agentToken , "--agent-url" , client .URL .String ())
402
406
clitest .SetupConfig (t , client , root )
407
+ errC := make (chan error )
403
408
agentCtx , agentCancel := context .WithCancel (ctx )
404
- t .Cleanup (agentCancel )
409
+ t .Cleanup (func () {
410
+ agentCancel ()
411
+ err := <- errC
412
+ require .NoError (t , err )
413
+ })
405
414
go func () {
406
- err := cmd .ExecuteContext (agentCtx )
407
- assert .NoError (t , err )
415
+ errC <- cmd .ExecuteContext (agentCtx )
408
416
}()
409
417
410
418
coderdtest .AwaitWorkspaceAgents (t , client , workspace .LatestBuild .ID )
@@ -416,18 +424,30 @@ func runAgent(t *testing.T, client *codersdk.Client, userID uuid.UUID) ([]coders
416
424
417
425
// setupTestListener starts accepting connections and echoing a single packet.
418
426
// Returns the listener and the listen port or Unix path.
419
- func setupTestListener (t * testing.T , l net.Listener ) (net.Listener , string ) {
427
+ func setupTestListener (t * testing.T , l net.Listener ) string {
428
+ // Wait for listener to completely exit before releasing.
429
+ done := make (chan struct {})
420
430
t .Cleanup (func () {
421
431
_ = l .Close ()
432
+ <- done
422
433
})
423
434
go func () {
435
+ defer close (done )
436
+ // Guard against testAccept running require after test completion.
437
+ var wg sync.WaitGroup
438
+ defer wg .Wait ()
439
+
424
440
for {
425
441
c , err := l .Accept ()
426
442
if err != nil {
427
443
return
428
444
}
429
445
430
- go testAccept (t , c )
446
+ wg .Add (1 )
447
+ go func () {
448
+ testAccept (t , c )
449
+ wg .Done ()
450
+ }()
431
451
}
432
452
}()
433
453
@@ -438,7 +458,7 @@ func setupTestListener(t *testing.T, l net.Listener) (net.Listener, string) {
438
458
addr = port
439
459
}
440
460
441
- return l , addr
461
+ return addr
442
462
}
443
463
444
464
var dialTestPayload = []byte ("dean-was-here123" )
@@ -502,8 +522,10 @@ func newThreadSafeBuffer() *threadSafeBuffer {
502
522
}
503
523
}
504
524
505
- var _ io.Reader = & threadSafeBuffer {}
506
- var _ io.Writer = & threadSafeBuffer {}
525
+ var (
526
+ _ io.Reader = & threadSafeBuffer {}
527
+ _ io.Writer = & threadSafeBuffer {}
528
+ )
507
529
508
530
// Read implements io.Reader.
509
531
func (b * threadSafeBuffer ) Read (p []byte ) (int , error ) {
0 commit comments