Source file
src/testing/testing_test.go
1
2
3
4
5 package testing_test
6
7 import (
8 "bytes"
9 "context"
10 "errors"
11 "fmt"
12 "internal/race"
13 "internal/testenv"
14 "os"
15 "os/exec"
16 "path/filepath"
17 "regexp"
18 "runtime"
19 "slices"
20 "strings"
21 "sync"
22 "testing"
23 "time"
24 )
25
26
27
28
29
30 func TestMain(m *testing.M) {
31 if os.Getenv("GO_WANT_RACE_BEFORE_TESTS") == "1" {
32 doRace()
33 }
34
35 m.Run()
36
37
38
39
40
41
42
43
44
45
46
47 }
48
49 func TestTempDirInCleanup(t *testing.T) {
50 var dir string
51
52 t.Run("test", func(t *testing.T) {
53 t.Cleanup(func() {
54 dir = t.TempDir()
55 })
56 _ = t.TempDir()
57 })
58
59 fi, err := os.Stat(dir)
60 if fi != nil {
61 t.Fatalf("Directory %q from user Cleanup still exists", dir)
62 }
63 if !os.IsNotExist(err) {
64 t.Fatalf("Unexpected error: %v", err)
65 }
66 }
67
68 func TestTempDirInBenchmark(t *testing.T) {
69 testing.Benchmark(func(b *testing.B) {
70 if !b.Run("test", func(b *testing.B) {
71
72 for i := 0; i < b.N; i++ {
73 _ = b.TempDir()
74 }
75 }) {
76 t.Fatal("Sub test failure in a benchmark")
77 }
78 })
79 }
80
81 func TestTempDir(t *testing.T) {
82 testTempDir(t)
83 t.Run("InSubtest", testTempDir)
84 t.Run("test/subtest", testTempDir)
85 t.Run("test\\subtest", testTempDir)
86 t.Run("test:subtest", testTempDir)
87 t.Run("test/..", testTempDir)
88 t.Run("../test", testTempDir)
89 t.Run("test[]", testTempDir)
90 t.Run("test*", testTempDir)
91 t.Run("äöüéè", testTempDir)
92 }
93
94 func testTempDir(t *testing.T) {
95 dirCh := make(chan string, 1)
96 t.Cleanup(func() {
97
98 select {
99 case dir := <-dirCh:
100 fi, err := os.Stat(dir)
101 if os.IsNotExist(err) {
102
103 return
104 }
105 if err != nil {
106 t.Fatal(err)
107 }
108 t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir())
109 default:
110 if !t.Failed() {
111 t.Fatal("never received dir channel")
112 }
113 }
114 })
115
116 dir := t.TempDir()
117 if dir == "" {
118 t.Fatal("expected dir")
119 }
120 dir2 := t.TempDir()
121 if dir == dir2 {
122 t.Fatal("subsequent calls to TempDir returned the same directory")
123 }
124 if filepath.Dir(dir) != filepath.Dir(dir2) {
125 t.Fatalf("calls to TempDir do not share a parent; got %q, %q", dir, dir2)
126 }
127 dirCh <- dir
128 fi, err := os.Stat(dir)
129 if err != nil {
130 t.Fatal(err)
131 }
132 if !fi.IsDir() {
133 t.Errorf("dir %q is not a dir", dir)
134 }
135 files, err := os.ReadDir(dir)
136 if err != nil {
137 t.Fatal(err)
138 }
139 if len(files) > 0 {
140 t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
141 }
142
143 glob := filepath.Join(dir, "*.txt")
144 if _, err := filepath.Glob(glob); err != nil {
145 t.Error(err)
146 }
147 }
148
149 func TestSetenv(t *testing.T) {
150 tests := []struct {
151 name string
152 key string
153 initialValueExists bool
154 initialValue string
155 newValue string
156 }{
157 {
158 name: "initial value exists",
159 key: "GO_TEST_KEY_1",
160 initialValueExists: true,
161 initialValue: "111",
162 newValue: "222",
163 },
164 {
165 name: "initial value exists but empty",
166 key: "GO_TEST_KEY_2",
167 initialValueExists: true,
168 initialValue: "",
169 newValue: "222",
170 },
171 {
172 name: "initial value is not exists",
173 key: "GO_TEST_KEY_3",
174 initialValueExists: false,
175 initialValue: "",
176 newValue: "222",
177 },
178 }
179
180 for _, test := range tests {
181 if test.initialValueExists {
182 if err := os.Setenv(test.key, test.initialValue); err != nil {
183 t.Fatalf("unable to set env: got %v", err)
184 }
185 } else {
186 os.Unsetenv(test.key)
187 }
188
189 t.Run(test.name, func(t *testing.T) {
190 t.Setenv(test.key, test.newValue)
191 if os.Getenv(test.key) != test.newValue {
192 t.Fatalf("unexpected value after t.Setenv: got %s, want %s", os.Getenv(test.key), test.newValue)
193 }
194 })
195
196 got, exists := os.LookupEnv(test.key)
197 if got != test.initialValue {
198 t.Fatalf("unexpected value after t.Setenv cleanup: got %s, want %s", got, test.initialValue)
199 }
200 if exists != test.initialValueExists {
201 t.Fatalf("unexpected value after t.Setenv cleanup: got %t, want %t", exists, test.initialValueExists)
202 }
203 }
204 }
205
206 func expectParallelConflict(t *testing.T) {
207 want := testing.ParallelConflict
208 if got := recover(); got != want {
209 t.Fatalf("expected panic; got %#v want %q", got, want)
210 }
211 }
212
213 func testWithParallelAfter(t *testing.T, fn func(*testing.T)) {
214 defer expectParallelConflict(t)
215
216 fn(t)
217 t.Parallel()
218 }
219
220 func testWithParallelBefore(t *testing.T, fn func(*testing.T)) {
221 defer expectParallelConflict(t)
222
223 t.Parallel()
224 fn(t)
225 }
226
227 func testWithParallelParentBefore(t *testing.T, fn func(*testing.T)) {
228 t.Parallel()
229
230 t.Run("child", func(t *testing.T) {
231 defer expectParallelConflict(t)
232
233 fn(t)
234 })
235 }
236
237 func testWithParallelGrandParentBefore(t *testing.T, fn func(*testing.T)) {
238 t.Parallel()
239
240 t.Run("child", func(t *testing.T) {
241 t.Run("grand-child", func(t *testing.T) {
242 defer expectParallelConflict(t)
243
244 fn(t)
245 })
246 })
247 }
248
249 func tSetenv(t *testing.T) {
250 t.Setenv("GO_TEST_KEY_1", "value")
251 }
252
253 func TestSetenvWithParallelAfter(t *testing.T) {
254 testWithParallelAfter(t, tSetenv)
255 }
256
257 func TestSetenvWithParallelBefore(t *testing.T) {
258 testWithParallelBefore(t, tSetenv)
259 }
260
261 func TestSetenvWithParallelParentBefore(t *testing.T) {
262 testWithParallelParentBefore(t, tSetenv)
263 }
264
265 func TestSetenvWithParallelGrandParentBefore(t *testing.T) {
266 testWithParallelGrandParentBefore(t, tSetenv)
267 }
268
269 func tChdir(t *testing.T) {
270 t.Chdir(t.TempDir())
271 }
272
273 func TestChdirWithParallelAfter(t *testing.T) {
274 testWithParallelAfter(t, tChdir)
275 }
276
277 func TestChdirWithParallelBefore(t *testing.T) {
278 testWithParallelBefore(t, tChdir)
279 }
280
281 func TestChdirWithParallelParentBefore(t *testing.T) {
282 testWithParallelParentBefore(t, tChdir)
283 }
284
285 func TestChdirWithParallelGrandParentBefore(t *testing.T) {
286 testWithParallelGrandParentBefore(t, tChdir)
287 }
288
289 func TestChdir(t *testing.T) {
290 oldDir, err := os.Getwd()
291 if err != nil {
292 t.Fatal(err)
293 }
294 defer os.Chdir(oldDir)
295
296
297 tmp, err := filepath.EvalSymlinks(t.TempDir())
298 if err != nil {
299 t.Fatal(err)
300 }
301 rel, err := filepath.Rel(oldDir, tmp)
302 if err != nil {
303
304
305 rel = "skip"
306 }
307
308 for _, tc := range []struct {
309 name, dir, pwd string
310 extraChdir bool
311 }{
312 {
313 name: "absolute",
314 dir: tmp,
315 pwd: tmp,
316 },
317 {
318 name: "relative",
319 dir: rel,
320 pwd: tmp,
321 },
322 {
323 name: "current (absolute)",
324 dir: oldDir,
325 pwd: oldDir,
326 },
327 {
328 name: "current (relative) with extra os.Chdir",
329 dir: ".",
330 pwd: oldDir,
331
332 extraChdir: true,
333 },
334 } {
335 t.Run(tc.name, func(t *testing.T) {
336 if tc.dir == "skip" {
337 t.Skipf("skipping test because there is no relative path between %s and %s", oldDir, tmp)
338 }
339 if !filepath.IsAbs(tc.pwd) {
340 t.Fatalf("Bad tc.pwd: %q (must be absolute)", tc.pwd)
341 }
342
343 t.Chdir(tc.dir)
344
345 newDir, err := os.Getwd()
346 if err != nil {
347 t.Fatal(err)
348 }
349 if newDir != tc.pwd {
350 t.Fatalf("failed to chdir to %q: getwd: got %q, want %q", tc.dir, newDir, tc.pwd)
351 }
352
353 switch runtime.GOOS {
354 case "windows", "plan9":
355
356 default:
357 if pwd := os.Getenv("PWD"); pwd != tc.pwd {
358 t.Fatalf("PWD: got %q, want %q", pwd, tc.pwd)
359 }
360 }
361
362 if tc.extraChdir {
363 os.Chdir("..")
364 }
365 })
366
367 newDir, err := os.Getwd()
368 if err != nil {
369 t.Fatal(err)
370 }
371 if newDir != oldDir {
372 t.Fatalf("failed to restore wd to %s: getwd: %s", oldDir, newDir)
373 }
374 }
375 }
376
377
378 var testingTrueInInit = false
379
380
381 var testingTrueInPackageVarInit = testing.Testing()
382
383
384 func init() {
385 if testing.Testing() {
386 testingTrueInInit = true
387 }
388 }
389
390 var testingProg = `
391 package main
392
393 import (
394 "fmt"
395 "testing"
396 )
397
398 func main() {
399 fmt.Println(testing.Testing())
400 }
401 `
402
403 func TestTesting(t *testing.T) {
404 if !testing.Testing() {
405 t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
406 }
407 if !testingTrueInInit {
408 t.Errorf("testing.Testing() called by init function == %t, want %t", testingTrueInInit, true)
409 }
410 if !testingTrueInPackageVarInit {
411 t.Errorf("testing.Testing() variable initialized as %t, want %t", testingTrueInPackageVarInit, true)
412 }
413
414 if testing.Short() {
415 t.Skip("skipping building a binary in short mode")
416 }
417 testenv.MustHaveGoRun(t)
418
419 fn := filepath.Join(t.TempDir(), "x.go")
420 if err := os.WriteFile(fn, []byte(testingProg), 0644); err != nil {
421 t.Fatal(err)
422 }
423
424 cmd := testenv.Command(t, testenv.GoToolPath(t), "run", fn)
425 out, err := cmd.CombinedOutput()
426 if err != nil {
427 t.Fatalf("%v failed: %v\n%s", cmd, err, out)
428 }
429
430 s := string(bytes.TrimSpace(out))
431 if s != "false" {
432 t.Errorf("in non-test testing.Test() returned %q, want %q", s, "false")
433 }
434 }
435
436
437
438 func runTest(t *testing.T, test string) []byte {
439 t.Helper()
440
441 testenv.MustHaveExec(t)
442
443 cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^"+test+"$", "-test.bench="+test, "-test.v", "-test.parallel=2", "-test.benchtime=2x")
444 cmd = testenv.CleanCmdEnv(cmd)
445 cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
446 out, err := cmd.CombinedOutput()
447 t.Logf("%v: %v\n%s", cmd, err, out)
448
449 return out
450 }
451
452
453
454 func doRace() {
455 var x int
456 c1 := make(chan bool)
457 go func() {
458 x = 1
459 c1 <- true
460 }()
461 _ = x
462 <-c1
463 }
464
465 func TestRaceReports(t *testing.T) {
466 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
467
468 t.Run("Sub", func(t *testing.T) {
469 doRace()
470 })
471 return
472 }
473
474 out := runTest(t, "TestRaceReports")
475
476
477 c := bytes.Count(out, []byte("race detected"))
478 want := 0
479 if race.Enabled {
480 want = 1
481 }
482 if c != want {
483 t.Errorf("got %d race reports, want %d", c, want)
484 }
485 }
486
487
488 func TestRaceName(t *testing.T) {
489 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
490 doRace()
491 return
492 }
493
494 out := runTest(t, "TestRaceName")
495
496 if regexp.MustCompile(`=== NAME\s*$`).Match(out) {
497 t.Errorf("incorrectly reported test with no name")
498 }
499 }
500
501 func TestRaceSubReports(t *testing.T) {
502 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
503 t.Parallel()
504 c1 := make(chan bool, 1)
505 t.Run("sub", func(t *testing.T) {
506 t.Run("subsub1", func(t *testing.T) {
507 t.Parallel()
508 doRace()
509 c1 <- true
510 })
511 t.Run("subsub2", func(t *testing.T) {
512 t.Parallel()
513 doRace()
514 <-c1
515 })
516 })
517 doRace()
518 return
519 }
520
521 out := runTest(t, "TestRaceSubReports")
522
523
524
525
526
527 cReport := bytes.Count(out, []byte("race detected during execution of test"))
528 wantReport := 0
529 if race.Enabled {
530 wantReport = 3
531 }
532 if cReport != wantReport {
533 t.Errorf("got %d race reports, want %d", cReport, wantReport)
534 }
535
536
537
538 cFail := bytes.Count(out, []byte("--- FAIL:"))
539 wantFail := 0
540 if race.Enabled {
541 wantFail = 4
542 }
543 if cFail != wantFail {
544 t.Errorf(`got %d "--- FAIL:" lines, want %d`, cReport, wantReport)
545 }
546 }
547
548 func TestRaceInCleanup(t *testing.T) {
549 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
550 t.Cleanup(doRace)
551 t.Parallel()
552 t.Run("sub", func(t *testing.T) {
553 t.Parallel()
554
555 })
556 return
557 }
558
559 out := runTest(t, "TestRaceInCleanup")
560
561
562 cReport := bytes.Count(out, []byte("race detected during execution of test"))
563 wantReport := 0
564 if race.Enabled {
565 wantReport = 1
566 }
567 if cReport != wantReport {
568 t.Errorf("got %d race reports, want %d", cReport, wantReport)
569 }
570
571
572
573 cFail := bytes.Count(out, []byte("--- FAIL:"))
574 wantFail := 0
575 if race.Enabled {
576 wantFail = 1
577 }
578 if cFail != wantFail {
579 t.Errorf(`got %d "--- FAIL:" lines, want %d`, cReport, wantReport)
580 }
581 }
582
583 func TestDeepSubtestRace(t *testing.T) {
584 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
585 t.Run("sub", func(t *testing.T) {
586 t.Run("subsub", func(t *testing.T) {
587 t.Run("subsubsub", func(t *testing.T) {
588 doRace()
589 })
590 })
591 doRace()
592 })
593 return
594 }
595
596 out := runTest(t, "TestDeepSubtestRace")
597
598 c := bytes.Count(out, []byte("race detected during execution of test"))
599 want := 0
600
601 if race.Enabled {
602 want = 2
603 }
604 if c != want {
605 t.Errorf("got %d race reports, want %d", c, want)
606 }
607 }
608
609 func TestRaceDuringParallelFailsAllSubtests(t *testing.T) {
610 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
611 var ready sync.WaitGroup
612 ready.Add(2)
613 done := make(chan struct{})
614 go func() {
615 ready.Wait()
616 doRace()
617 close(done)
618 }()
619
620 t.Run("sub", func(t *testing.T) {
621 t.Run("subsub1", func(t *testing.T) {
622 t.Parallel()
623 ready.Done()
624 <-done
625 })
626 t.Run("subsub2", func(t *testing.T) {
627 t.Parallel()
628 ready.Done()
629 <-done
630 })
631 })
632
633 return
634 }
635
636 out := runTest(t, "TestRaceDuringParallelFailsAllSubtests")
637
638 c := bytes.Count(out, []byte("race detected during execution of test"))
639 want := 0
640
641 if race.Enabled {
642 want = 2
643 }
644 if c != want {
645 t.Errorf("got %d race reports, want %d", c, want)
646 }
647 }
648
649 func TestRaceBeforeParallel(t *testing.T) {
650 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
651 t.Run("sub", func(t *testing.T) {
652 doRace()
653 t.Parallel()
654 })
655 return
656 }
657
658 out := runTest(t, "TestRaceBeforeParallel")
659
660 c := bytes.Count(out, []byte("race detected during execution of test"))
661 want := 0
662
663 if race.Enabled {
664 want = 1
665 }
666 if c != want {
667 t.Errorf("got %d race reports, want %d", c, want)
668 }
669 }
670
671 func TestRaceBeforeTests(t *testing.T) {
672 cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^$")
673 cmd = testenv.CleanCmdEnv(cmd)
674 cmd.Env = append(cmd.Env, "GO_WANT_RACE_BEFORE_TESTS=1")
675 out, _ := cmd.CombinedOutput()
676 t.Logf("%s", out)
677
678 c := bytes.Count(out, []byte("race detected outside of test execution"))
679
680 want := 0
681 if race.Enabled {
682 want = 1
683 }
684 if c != want {
685 t.Errorf("got %d race reports; want %d", c, want)
686 }
687 }
688
689 func TestBenchmarkRace(t *testing.T) {
690 out := runTest(t, "BenchmarkRacy")
691 c := bytes.Count(out, []byte("race detected during execution of test"))
692
693 want := 0
694
695 if race.Enabled {
696 want = 1
697 }
698 if c != want {
699 t.Errorf("got %d race reports; want %d", c, want)
700 }
701 }
702
703 func BenchmarkRacy(b *testing.B) {
704 if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
705 b.Skipf("skipping intentionally-racy benchmark")
706 }
707 for i := 0; i < b.N; i++ {
708 doRace()
709 }
710 }
711
712 func TestBenchmarkSubRace(t *testing.T) {
713 out := runTest(t, "BenchmarkSubRacy")
714 c := bytes.Count(out, []byte("race detected during execution of test"))
715
716 want := 0
717
718
719 if race.Enabled {
720 want = 2
721 }
722 if c != want {
723 t.Errorf("got %d race reports; want %d", c, want)
724 }
725 }
726
727 func BenchmarkSubRacy(b *testing.B) {
728 if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
729 b.Skipf("skipping intentionally-racy benchmark")
730 }
731
732 b.Run("non-racy", func(b *testing.B) {
733 tot := 0
734 for i := 0; i < b.N; i++ {
735 tot++
736 }
737 _ = tot
738 })
739
740 b.Run("racy", func(b *testing.B) {
741 for i := 0; i < b.N; i++ {
742 doRace()
743 }
744 })
745
746 doRace()
747 }
748
749 func TestRunningTests(t *testing.T) {
750 t.Parallel()
751
752
753
754
755
756 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
757 for i := 0; i < 2; i++ {
758 t.Run(fmt.Sprintf("outer%d", i), func(t *testing.T) {
759 t.Parallel()
760 for j := 0; j < 2; j++ {
761 t.Run(fmt.Sprintf("inner%d", j), func(t *testing.T) {
762 t.Parallel()
763 for {
764 time.Sleep(1 * time.Millisecond)
765 }
766 })
767 }
768 })
769 }
770 }
771
772 timeout := 10 * time.Millisecond
773 for {
774 cmd := testenv.Command(t, os.Args[0], "-test.run=^"+t.Name()+"$", "-test.timeout="+timeout.String(), "-test.parallel=4")
775 cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
776 out, err := cmd.CombinedOutput()
777 t.Logf("%v:\n%s", cmd, out)
778 if _, ok := err.(*exec.ExitError); !ok {
779 t.Fatal(err)
780 }
781
782
783
784
785
786 want := []string{
787 "TestRunningTests/outer0/inner0",
788 "TestRunningTests/outer0/inner1",
789 "TestRunningTests/outer1/inner0",
790 "TestRunningTests/outer1/inner1",
791 }
792
793 got, ok := parseRunningTests(out)
794 if slices.Equal(got, want) {
795 break
796 }
797 if ok {
798 t.Logf("found running tests:\n%s\nwant:\n%s", strings.Join(got, "\n"), strings.Join(want, "\n"))
799 } else {
800 t.Logf("no running tests found")
801 }
802 t.Logf("retrying with longer timeout")
803 timeout *= 2
804 }
805 }
806
807 func TestRunningTestsInCleanup(t *testing.T) {
808 t.Parallel()
809
810 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
811 for i := 0; i < 2; i++ {
812 t.Run(fmt.Sprintf("outer%d", i), func(t *testing.T) {
813
814
815
816 t.Cleanup(func() {
817 for {
818 time.Sleep(1 * time.Millisecond)
819 }
820 })
821
822 for j := 0; j < 2; j++ {
823 t.Run(fmt.Sprintf("inner%d", j), func(t *testing.T) {
824 t.Parallel()
825 })
826 }
827 })
828 }
829 }
830
831 timeout := 10 * time.Millisecond
832 for {
833 cmd := testenv.Command(t, os.Args[0], "-test.run=^"+t.Name()+"$", "-test.timeout="+timeout.String())
834 cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
835 out, err := cmd.CombinedOutput()
836 t.Logf("%v:\n%s", cmd, out)
837 if _, ok := err.(*exec.ExitError); !ok {
838 t.Fatal(err)
839 }
840
841
842
843
844
845
846 want := []string{
847 "TestRunningTestsInCleanup",
848 "TestRunningTestsInCleanup/outer0",
849 }
850
851 got, ok := parseRunningTests(out)
852 if slices.Equal(got, want) {
853 break
854 }
855 if ok {
856 t.Logf("found running tests:\n%s\nwant:\n%s", strings.Join(got, "\n"), strings.Join(want, "\n"))
857 } else {
858 t.Logf("no running tests found")
859 }
860 t.Logf("retrying with longer timeout")
861 timeout *= 2
862 }
863 }
864
865 func parseRunningTests(out []byte) (runningTests []string, ok bool) {
866 inRunningTests := false
867 for _, line := range strings.Split(string(out), "\n") {
868 if inRunningTests {
869
870 if trimmed, ok := strings.CutPrefix(line, "\t\t"); ok {
871 if name, _, ok := strings.Cut(trimmed, " "); ok {
872 runningTests = append(runningTests, name)
873 continue
874 }
875 }
876
877
878 return runningTests, true
879 }
880
881 if strings.TrimSpace(line) == "running tests:" {
882 inRunningTests = true
883 }
884 }
885
886 return nil, false
887 }
888
889 func TestConcurrentRun(t *testing.T) {
890
891
892
893 block := make(chan struct{})
894 var ready, done sync.WaitGroup
895 for i := 0; i < 2; i++ {
896 ready.Add(1)
897 done.Add(1)
898 go t.Run("", func(*testing.T) {
899 ready.Done()
900 <-block
901 done.Done()
902 })
903 }
904 ready.Wait()
905 close(block)
906 done.Wait()
907 }
908
909 func TestParentRun(t1 *testing.T) {
910
911
912
913 t1.Run("outer", func(t2 *testing.T) {
914 t2.Log("Hello outer!")
915 t1.Run("not_inner", func(t3 *testing.T) {
916 t3.Log("Hello inner!")
917 })
918 })
919 }
920
921 func TestContext(t *testing.T) {
922 ctx := t.Context()
923 if err := ctx.Err(); err != nil {
924 t.Fatalf("expected non-canceled context, got %v", err)
925 }
926
927 var innerCtx context.Context
928 t.Run("inner", func(t *testing.T) {
929 innerCtx = t.Context()
930 if err := innerCtx.Err(); err != nil {
931 t.Fatalf("expected inner test to not inherit canceled context, got %v", err)
932 }
933 })
934 t.Run("inner2", func(t *testing.T) {
935 if !errors.Is(innerCtx.Err(), context.Canceled) {
936 t.Fatal("expected context of sibling test to be canceled after its test function finished")
937 }
938 })
939
940 t.Cleanup(func() {
941 if !errors.Is(ctx.Err(), context.Canceled) {
942 t.Fatal("expected context canceled before cleanup")
943 }
944 })
945 }
946
View as plain text