1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
18 // This is exactly what a test would do without a TestMain.
19 // It's here only so that there is at least one package in the
20 // standard library with a TestMain, so that code is executed.
22 func TestMain(m *testing.M) {
23 if os.Getenv("GO_WANT_RACE_BEFORE_TESTS") == "1" {
29 // Note: m.Run currently prints the final "PASS" line, so if any race is
30 // reported here (after m.Run but before the process exits), it will print
31 // "PASS", then print the stack traces for the race, then exit with nonzero
34 // This is a somewhat fundamental race: because the race detector hooks into
35 // the runtime at a very low level, no matter where we put the printing it
36 // would be possible to report a race that occurs afterward. However, we could
37 // theoretically move the printing after TestMain, which would at least do a
38 // better job of diagnosing races in cleanup functions within TestMain itself.
41 func TestTempDirInCleanup(t *testing.T) {
44 t.Run("test", func(t *testing.T) {
51 fi, err := os.Stat(dir)
53 t.Fatalf("Directory %q from user Cleanup still exists", dir)
55 if !os.IsNotExist(err) {
56 t.Fatalf("Unexpected error: %v", err)
60 func TestTempDirInBenchmark(t *testing.T) {
61 testing.Benchmark(func(b *testing.B) {
62 if !b.Run("test", func(b *testing.B) {
63 // Add a loop so that the test won't fail. See issue 38677.
64 for i := 0; i < b.N; i++ {
68 t.Fatal("Sub test failure in a benchmark")
73 func TestTempDir(t *testing.T) {
75 t.Run("InSubtest", testTempDir)
76 t.Run("test/subtest", testTempDir)
77 t.Run("test\\subtest", testTempDir)
78 t.Run("test:subtest", testTempDir)
79 t.Run("test/..", testTempDir)
80 t.Run("../test", testTempDir)
81 t.Run("test[]", testTempDir)
82 t.Run("test*", testTempDir)
83 t.Run("äöüéè", testTempDir)
86 func testTempDir(t *testing.T) {
87 dirCh := make(chan string, 1)
89 // Verify directory has been removed.
92 fi, err := os.Stat(dir)
93 if os.IsNotExist(err) {
100 t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir())
103 t.Fatal("never received dir channel")
110 t.Fatal("expected dir")
114 t.Fatal("subsequent calls to TempDir returned the same directory")
116 if filepath.Dir(dir) != filepath.Dir(dir2) {
117 t.Fatalf("calls to TempDir do not share a parent; got %q, %q", dir, dir2)
120 fi, err := os.Stat(dir)
125 t.Errorf("dir %q is not a dir", dir)
127 files, err := os.ReadDir(dir)
132 t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
135 glob := filepath.Join(dir, "*.txt")
136 if _, err := filepath.Glob(glob); err != nil {
141 func TestSetenv(t *testing.T) {
145 initialValueExists bool
150 name: "initial value exists",
151 key: "GO_TEST_KEY_1",
152 initialValueExists: true,
157 name: "initial value exists but empty",
158 key: "GO_TEST_KEY_2",
159 initialValueExists: true,
164 name: "initial value is not exists",
165 key: "GO_TEST_KEY_3",
166 initialValueExists: false,
172 for _, test := range tests {
173 if test.initialValueExists {
174 if err := os.Setenv(test.key, test.initialValue); err != nil {
175 t.Fatalf("unable to set env: got %v", err)
178 os.Unsetenv(test.key)
181 t.Run(test.name, func(t *testing.T) {
182 t.Setenv(test.key, test.newValue)
183 if os.Getenv(test.key) != test.newValue {
184 t.Fatalf("unexpected value after t.Setenv: got %s, want %s", os.Getenv(test.key), test.newValue)
188 got, exists := os.LookupEnv(test.key)
189 if got != test.initialValue {
190 t.Fatalf("unexpected value after t.Setenv cleanup: got %s, want %s", got, test.initialValue)
192 if exists != test.initialValueExists {
193 t.Fatalf("unexpected value after t.Setenv cleanup: got %t, want %t", exists, test.initialValueExists)
198 func TestSetenvWithParallelAfterSetenv(t *testing.T) {
200 want := "testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests"
201 if got := recover(); got != want {
202 t.Fatalf("expected panic; got %#v want %q", got, want)
206 t.Setenv("GO_TEST_KEY_1", "value")
211 func TestSetenvWithParallelBeforeSetenv(t *testing.T) {
213 want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
214 if got := recover(); got != want {
215 t.Fatalf("expected panic; got %#v want %q", got, want)
221 t.Setenv("GO_TEST_KEY_1", "value")
224 func TestSetenvWithParallelParentBeforeSetenv(t *testing.T) {
227 t.Run("child", func(t *testing.T) {
229 want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
230 if got := recover(); got != want {
231 t.Fatalf("expected panic; got %#v want %q", got, want)
235 t.Setenv("GO_TEST_KEY_1", "value")
239 func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) {
242 t.Run("child", func(t *testing.T) {
243 t.Run("grand-child", func(t *testing.T) {
245 want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
246 if got := recover(); got != want {
247 t.Fatalf("expected panic; got %#v want %q", got, want)
251 t.Setenv("GO_TEST_KEY_1", "value")
256 // testingTrueInInit is part of TestTesting.
257 var testingTrueInInit = false
259 // testingTrueInPackageVarInit is part of TestTesting.
260 var testingTrueInPackageVarInit = testing.Testing()
262 // init is part of TestTesting.
264 if testing.Testing() {
265 testingTrueInInit = true
278 fmt.Println(testing.Testing())
282 func TestTesting(t *testing.T) {
283 if !testing.Testing() {
284 t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
286 if !testingTrueInInit {
287 t.Errorf("testing.Testing() called by init function == %t, want %t", testingTrueInInit, true)
289 if !testingTrueInPackageVarInit {
290 t.Errorf("testing.Testing() variable initialized as %t, want %t", testingTrueInPackageVarInit, true)
294 t.Skip("skipping building a binary in short mode")
296 testenv.MustHaveGoRun(t)
298 fn := filepath.Join(t.TempDir(), "x.go")
299 if err := os.WriteFile(fn, []byte(testingProg), 0644); err != nil {
303 cmd := testenv.Command(t, testenv.GoToolPath(t), "run", fn)
304 out, err := cmd.CombinedOutput()
306 t.Fatalf("%v failed: %v\n%s", cmd, err, out)
309 s := string(bytes.TrimSpace(out))
311 t.Errorf("in non-test testing.Test() returned %q, want %q", s, "false")
315 // runTest runs a helper test with -test.v, ignoring its exit status.
316 // runTest both logs and returns the test output.
317 func runTest(t *testing.T, test string) []byte {
320 testenv.MustHaveExec(t)
322 exe, err := os.Executable()
324 t.Skipf("can't find test executable: %v", err)
327 cmd := testenv.Command(t, exe, "-test.run=^"+test+"$", "-test.bench="+test, "-test.v", "-test.parallel=2", "-test.benchtime=2x")
328 cmd = testenv.CleanCmdEnv(cmd)
329 cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
330 out, err := cmd.CombinedOutput()
331 t.Logf("%v: %v\n%s", cmd, err, out)
336 // doRace provokes a data race that generates a race detector report if run
337 // under the race detector and is otherwise benign.
340 c1 := make(chan bool)
349 func TestRaceReports(t *testing.T) {
350 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
351 // Generate a race detector report in a sub test.
352 t.Run("Sub", func(t *testing.T) {
358 out := runTest(t, "TestRaceReports")
360 // We should see at most one race detector report.
361 c := bytes.Count(out, []byte("race detected"))
367 t.Errorf("got %d race reports, want %d", c, want)
371 // Issue #60083. This used to fail on the race builder.
372 func TestRaceName(t *testing.T) {
373 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
378 out := runTest(t, "TestRaceName")
380 if regexp.MustCompile(`=== NAME\s*$`).Match(out) {
381 t.Errorf("incorrectly reported test with no name")
385 func TestRaceSubReports(t *testing.T) {
386 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
388 c1 := make(chan bool, 1)
389 t.Run("sub", func(t *testing.T) {
390 t.Run("subsub1", func(t *testing.T) {
395 t.Run("subsub2", func(t *testing.T) {
405 out := runTest(t, "TestRaceSubReports")
407 // There should be three race reports: one for each subtest, and one for the
408 // race after the subtests complete. Note that because the subtests run in
409 // parallel, the race stacks may both be printed in with one or the other
411 cReport := bytes.Count(out, []byte("race detected during execution of test"))
416 if cReport != wantReport {
417 t.Errorf("got %d race reports, want %d", cReport, wantReport)
420 // Regardless of when the stacks are printed, we expect each subtest to be
421 // marked as failed, and that failure should propagate up to the parents.
422 cFail := bytes.Count(out, []byte("--- FAIL:"))
427 if cFail != wantFail {
428 t.Errorf(`got %d "--- FAIL:" lines, want %d`, cReport, wantReport)
432 func TestRaceInCleanup(t *testing.T) {
433 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
436 t.Run("sub", func(t *testing.T) {
438 // No race should be reported for sub.
443 out := runTest(t, "TestRaceInCleanup")
445 // There should be one race report, for the parent test only.
446 cReport := bytes.Count(out, []byte("race detected during execution of test"))
451 if cReport != wantReport {
452 t.Errorf("got %d race reports, want %d", cReport, wantReport)
455 // Only the parent test should be marked as failed.
456 // (The subtest does not race, and should pass.)
457 cFail := bytes.Count(out, []byte("--- FAIL:"))
462 if cFail != wantFail {
463 t.Errorf(`got %d "--- FAIL:" lines, want %d`, cReport, wantReport)
467 func TestDeepSubtestRace(t *testing.T) {
468 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
469 t.Run("sub", func(t *testing.T) {
470 t.Run("subsub", func(t *testing.T) {
471 t.Run("subsubsub", func(t *testing.T) {
480 out := runTest(t, "TestDeepSubtestRace")
482 c := bytes.Count(out, []byte("race detected during execution of test"))
484 // There should be two race reports.
489 t.Errorf("got %d race reports, want %d", c, want)
493 func TestRaceDuringParallelFailsAllSubtests(t *testing.T) {
494 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
495 var ready sync.WaitGroup
497 done := make(chan struct{})
500 doRace() // This race happens while both subtests are running.
504 t.Run("sub", func(t *testing.T) {
505 t.Run("subsub1", func(t *testing.T) {
510 t.Run("subsub2", func(t *testing.T) {
520 out := runTest(t, "TestRaceDuringParallelFailsAllSubtests")
522 c := bytes.Count(out, []byte("race detected during execution of test"))
524 // Each subtest should report the race independently.
529 t.Errorf("got %d race reports, want %d", c, want)
533 func TestRaceBeforeParallel(t *testing.T) {
534 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
535 t.Run("sub", func(t *testing.T) {
542 out := runTest(t, "TestRaceBeforeParallel")
544 c := bytes.Count(out, []byte("race detected during execution of test"))
546 // We should see one race detector report.
551 t.Errorf("got %d race reports, want %d", c, want)
555 func TestRaceBeforeTests(t *testing.T) {
556 testenv.MustHaveExec(t)
558 exe, err := os.Executable()
560 t.Skipf("can't find test executable: %v", err)
563 cmd := testenv.Command(t, exe, "-test.run=^$")
564 cmd = testenv.CleanCmdEnv(cmd)
565 cmd.Env = append(cmd.Env, "GO_WANT_RACE_BEFORE_TESTS=1")
566 out, _ := cmd.CombinedOutput()
569 c := bytes.Count(out, []byte("race detected outside of test execution"))
576 t.Errorf("got %d race reports; want %d", c, want)
580 func TestBenchmarkRace(t *testing.T) {
581 out := runTest(t, "BenchmarkRacy")
582 c := bytes.Count(out, []byte("race detected during execution of test"))
585 // We should see one race detector report.
590 t.Errorf("got %d race reports; want %d", c, want)
594 func BenchmarkRacy(b *testing.B) {
595 if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
596 b.Skipf("skipping intentionally-racy benchmark")
598 for i := 0; i < b.N; i++ {
603 func TestBenchmarkSubRace(t *testing.T) {
604 out := runTest(t, "BenchmarkSubRacy")
605 c := bytes.Count(out, []byte("race detected during execution of test"))
608 // We should see two race detector reports:
609 // one in the sub-bencmark, and one in the parent afterward.
614 t.Errorf("got %d race reports; want %d", c, want)
618 func BenchmarkSubRacy(b *testing.B) {
619 if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
620 b.Skipf("skipping intentionally-racy benchmark")
623 b.Run("non-racy", func(b *testing.B) {
625 for i := 0; i < b.N; i++ {
631 b.Run("racy", func(b *testing.B) {
632 for i := 0; i < b.N; i++ {
637 doRace() // should be reported separately