@@ -275,6 +275,212 @@ func TestWithCustomType(t *testing.T) {
275
275
}
276
276
}
277
277
278
+ func helpTB (tb testing.TB ) {
279
+ tb .FailNow ()
280
+ }
281
+
282
+ func TestTB (t * testing.T ) {
283
+ go helpTB (t ) // want "call to .+TB.+FailNow from a non-test goroutine"
284
+ }
285
+
278
286
func TestIssue48124 (t * testing.T ) {
279
- go h ()
287
+ go helper (t ) // want "call to .+T.+Skip from a non-test goroutine"
288
+ }
289
+
290
+ func TestEachCall (t * testing.T ) {
291
+ go helper (t ) // want "call to .+T.+Skip from a non-test goroutine"
292
+ go helper (t ) // want "call to .+T.+Skip from a non-test goroutine"
293
+ }
294
+
295
+ func TestWithSubtest (t * testing.T ) {
296
+ t .Run ("name" , func (t2 * testing.T ) {
297
+ t .FailNow () // want "call to .+T.+FailNow on t defined outside of the subtest"
298
+ t2 .Fatal ()
299
+ })
300
+
301
+ f := func (t3 * testing.T ) {
302
+ t .FailNow ()
303
+ t3 .Fatal ()
304
+ }
305
+ t .Run ("name" , f ) // want "call to .+T.+FailNow on t defined outside of the subtest"
306
+
307
+ g := func (t4 * testing.T ) {
308
+ t .FailNow ()
309
+ t4 .Fatal ()
310
+ }
311
+ g (t )
312
+
313
+ t .Run ("name" , helper )
314
+
315
+ go t .Run ("name" , func (t2 * testing.T ) {
316
+ t .FailNow () // want "call to .+T.+FailNow on t defined outside of the subtest"
317
+ t2 .Fatal ()
318
+ })
319
+ }
320
+
321
+ func TestMultipleVariables (t * testing.T ) {
322
+ { // short decl
323
+ f , g := func (t1 * testing.T ) {
324
+ t1 .Fatal ()
325
+ }, func (t2 * testing.T ) {
326
+ t2 .Error ()
327
+ }
328
+
329
+ go f (t ) // want "call to .+T.+Fatal from a non-test goroutine"
330
+ go g (t )
331
+
332
+ t .Run ("name" , f )
333
+ t .Run ("name" , g )
334
+ }
335
+
336
+ { // var decl
337
+ var f , g = func (t1 * testing.T ) {
338
+ t1 .Fatal ()
339
+ }, func (t2 * testing.T ) {
340
+ t2 .Error ()
341
+ }
342
+
343
+ go f (t ) // want "call to .+T.+Fatal from a non-test goroutine"
344
+ go g (t )
345
+
346
+ t .Run ("name" , f )
347
+ t .Run ("name" , g )
348
+ }
349
+ }
350
+
351
+ func BadIgnoresMultipleAssignments (t * testing.T ) {
352
+ {
353
+ f := func (t1 * testing.T ) {
354
+ t1 .Fatal ()
355
+ }
356
+ go f (t ) // want "call to .+T.+Fatal from a non-test goroutine"
357
+
358
+ f = func (t2 * testing.T ) {
359
+ t2 .Error ()
360
+ }
361
+ go f (t ) // want "call to .+T.+Fatal from a non-test goroutine"
362
+ }
363
+ {
364
+ f := func (t1 * testing.T ) {
365
+ t1 .Error ()
366
+ }
367
+ go f (t )
368
+
369
+ f = func (t2 * testing.T ) {
370
+ t2 .FailNow ()
371
+ }
372
+ go f (t ) // false negative
373
+ }
374
+ }
375
+
376
+ func TestGoDoesNotDescendIntoSubtest (t * testing.T ) {
377
+ f := func (t2 * testing.T ) {
378
+ g := func (t3 * testing.T ) {
379
+ t3 .Fatal () // fine
380
+ }
381
+ t2 .Run ("name" , g )
382
+ t2 .FailNow () // bad
383
+ }
384
+ go f (t ) // want "call to .+T.+FailNow from a non-test goroutine"
385
+ }
386
+
387
+ func TestFreeVariableAssignedWithinEnclosing (t * testing.T ) {
388
+ f := func (t2 * testing.T ) {
389
+ inner := t
390
+ inner .FailNow ()
391
+ }
392
+
393
+ go f (nil ) // want "call to .+T.+FailNow from a non-test goroutine"
394
+
395
+ t .Run ("name" , func (t3 * testing.T ) {
396
+ go f (nil ) // want "call to .+T.+FailNow from a non-test goroutine"
397
+ })
398
+
399
+ // Without pointer analysis we cannot tell if inner is t or t2.
400
+ // So we accept a false negatives on the following examples.
401
+ t .Run ("name" , f )
402
+
403
+ go func (_ * testing.T ) {
404
+ t .Run ("name" , f )
405
+ }(nil )
406
+
407
+ go t .Run ("name" , f )
408
+ }
409
+
410
+ func TestWithUnusedSelection (t * testing.T ) {
411
+ go func () {
412
+ _ = t .FailNow
413
+ }()
414
+ t .Run ("name" , func (t2 * testing.T ) {
415
+ _ = t .FailNow
416
+ })
417
+ }
418
+
419
+ func TestMethodExprsAreIgnored (t * testing.T ) {
420
+ go func () {
421
+ (* testing .T ).FailNow (t )
422
+ }()
423
+ }
424
+
425
+ func TestRecursive (t * testing.T ) {
426
+ t .SkipNow ()
427
+
428
+ go TestRecursive (t ) // want "call to .+T.+SkipNow from a non-test goroutine"
429
+
430
+ t .Run ("name" , TestRecursive )
431
+ }
432
+
433
+ func TestMethodSelection (t * testing.T ) {
434
+ var h helperType
435
+
436
+ go h .help (t ) // want "call to .+T.+SkipNow from a non-test goroutine"
437
+ t .Run ("name" , h .help )
438
+ }
439
+
440
+ type helperType struct {}
441
+
442
+ func (h * helperType ) help (t * testing.T ) { t .SkipNow () }
443
+
444
+ func TestIssue63799a (t * testing.T ) {
445
+ done := make (chan struct {})
446
+ go func () {
447
+ defer close (done )
448
+ t .Run ("" , func (t * testing.T ) {
449
+ t .Fatal () // No warning. This is in a subtest.
450
+ })
451
+ }()
452
+ <- done
453
+ }
454
+
455
+ func TestIssue63799b (t * testing.T ) {
456
+ // Simplified from go.dev/cl/538698
457
+
458
+ // nondet is some unspecified boolean placeholder.
459
+ var nondet func () bool
460
+
461
+ t .Run ("nohup" , func (t * testing.T ) {
462
+ if nondet () {
463
+ t .Skip ("ignored" )
464
+ }
465
+
466
+ go t .Run ("nohup-i" , func (t * testing.T ) {
467
+ t .Parallel ()
468
+ if nondet () {
469
+ if nondet () {
470
+ t .Skip ("go.dev/cl/538698 wanted to have skip here" )
471
+ }
472
+
473
+ t .Error ("ignored" )
474
+ } else {
475
+ t .Log ("ignored" )
476
+ }
477
+ })
478
+ })
479
+ }
480
+
481
+ func TestIssue63849 (t * testing.T ) {
482
+ go func () {
483
+ helper (t ) // False negative. We do not do an actual interprodecural reachability analysis.
484
+ }()
485
+ go helper (t ) // want "call to .+T.+Skip from a non-test goroutine"
280
486
}
0 commit comments