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.
4
5package testing_test
6
7import (
8	"bytes"
9	"fmt"
10	"internal/race"
11	"internal/testenv"
12	"os"
13	"os/exec"
14	"path/filepath"
15	"regexp"
16	"slices"
17	"strings"
18	"sync"
19	"testing"
20	"time"
21)
22
23// This is exactly what a test would do without a TestMain.
24// It's here only so that there is at least one package in the
25// standard library with a TestMain, so that code is executed.
26
27func TestMain(m *testing.M) {
28	if os.Getenv("GO_WANT_RACE_BEFORE_TESTS") == "1" {
29		doRace()
30	}
31
32	m.Run()
33
34	// Note: m.Run currently prints the final "PASS" line, so if any race is
35	// reported here (after m.Run but before the process exits), it will print
36	// "PASS", then print the stack traces for the race, then exit with nonzero
37	// status.
38	//
39	// This is a somewhat fundamental race: because the race detector hooks into
40	// the runtime at a very low level, no matter where we put the printing it
41	// would be possible to report a race that occurs afterward. However, we could
42	// theoretically move the printing after TestMain, which would at least do a
43	// better job of diagnosing races in cleanup functions within TestMain itself.
44}
45
46func TestTempDirInCleanup(t *testing.T) {
47	var dir string
48
49	t.Run("test", func(t *testing.T) {
50		t.Cleanup(func() {
51			dir = t.TempDir()
52		})
53		_ = t.TempDir()
54	})
55
56	fi, err := os.Stat(dir)
57	if fi != nil {
58		t.Fatalf("Directory %q from user Cleanup still exists", dir)
59	}
60	if !os.IsNotExist(err) {
61		t.Fatalf("Unexpected error: %v", err)
62	}
63}
64
65func TestTempDirInBenchmark(t *testing.T) {
66	testing.Benchmark(func(b *testing.B) {
67		if !b.Run("test", func(b *testing.B) {
68			// Add a loop so that the test won't fail. See issue 38677.
69			for i := 0; i < b.N; i++ {
70				_ = b.TempDir()
71			}
72		}) {
73			t.Fatal("Sub test failure in a benchmark")
74		}
75	})
76}
77
78func TestTempDir(t *testing.T) {
79	testTempDir(t)
80	t.Run("InSubtest", testTempDir)
81	t.Run("test/subtest", testTempDir)
82	t.Run("test\\subtest", testTempDir)
83	t.Run("test:subtest", testTempDir)
84	t.Run("test/..", testTempDir)
85	t.Run("../test", testTempDir)
86	t.Run("test[]", testTempDir)
87	t.Run("test*", testTempDir)
88	t.Run("äöüéè", testTempDir)
89}
90
91func testTempDir(t *testing.T) {
92	dirCh := make(chan string, 1)
93	t.Cleanup(func() {
94		// Verify directory has been removed.
95		select {
96		case dir := <-dirCh:
97			fi, err := os.Stat(dir)
98			if os.IsNotExist(err) {
99				// All good
100				return
101			}
102			if err != nil {
103				t.Fatal(err)
104			}
105			t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir())
106		default:
107			if !t.Failed() {
108				t.Fatal("never received dir channel")
109			}
110		}
111	})
112
113	dir := t.TempDir()
114	if dir == "" {
115		t.Fatal("expected dir")
116	}
117	dir2 := t.TempDir()
118	if dir == dir2 {
119		t.Fatal("subsequent calls to TempDir returned the same directory")
120	}
121	if filepath.Dir(dir) != filepath.Dir(dir2) {
122		t.Fatalf("calls to TempDir do not share a parent; got %q, %q", dir, dir2)
123	}
124	dirCh <- dir
125	fi, err := os.Stat(dir)
126	if err != nil {
127		t.Fatal(err)
128	}
129	if !fi.IsDir() {
130		t.Errorf("dir %q is not a dir", dir)
131	}
132	files, err := os.ReadDir(dir)
133	if err != nil {
134		t.Fatal(err)
135	}
136	if len(files) > 0 {
137		t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
138	}
139
140	glob := filepath.Join(dir, "*.txt")
141	if _, err := filepath.Glob(glob); err != nil {
142		t.Error(err)
143	}
144}
145
146func TestSetenv(t *testing.T) {
147	tests := []struct {
148		name               string
149		key                string
150		initialValueExists bool
151		initialValue       string
152		newValue           string
153	}{
154		{
155			name:               "initial value exists",
156			key:                "GO_TEST_KEY_1",
157			initialValueExists: true,
158			initialValue:       "111",
159			newValue:           "222",
160		},
161		{
162			name:               "initial value exists but empty",
163			key:                "GO_TEST_KEY_2",
164			initialValueExists: true,
165			initialValue:       "",
166			newValue:           "222",
167		},
168		{
169			name:               "initial value is not exists",
170			key:                "GO_TEST_KEY_3",
171			initialValueExists: false,
172			initialValue:       "",
173			newValue:           "222",
174		},
175	}
176
177	for _, test := range tests {
178		if test.initialValueExists {
179			if err := os.Setenv(test.key, test.initialValue); err != nil {
180				t.Fatalf("unable to set env: got %v", err)
181			}
182		} else {
183			os.Unsetenv(test.key)
184		}
185
186		t.Run(test.name, func(t *testing.T) {
187			t.Setenv(test.key, test.newValue)
188			if os.Getenv(test.key) != test.newValue {
189				t.Fatalf("unexpected value after t.Setenv: got %s, want %s", os.Getenv(test.key), test.newValue)
190			}
191		})
192
193		got, exists := os.LookupEnv(test.key)
194		if got != test.initialValue {
195			t.Fatalf("unexpected value after t.Setenv cleanup: got %s, want %s", got, test.initialValue)
196		}
197		if exists != test.initialValueExists {
198			t.Fatalf("unexpected value after t.Setenv cleanup: got %t, want %t", exists, test.initialValueExists)
199		}
200	}
201}
202
203func TestSetenvWithParallelAfterSetenv(t *testing.T) {
204	defer func() {
205		want := "testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests"
206		if got := recover(); got != want {
207			t.Fatalf("expected panic; got %#v want %q", got, want)
208		}
209	}()
210
211	t.Setenv("GO_TEST_KEY_1", "value")
212
213	t.Parallel()
214}
215
216func TestSetenvWithParallelBeforeSetenv(t *testing.T) {
217	defer func() {
218		want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
219		if got := recover(); got != want {
220			t.Fatalf("expected panic; got %#v want %q", got, want)
221		}
222	}()
223
224	t.Parallel()
225
226	t.Setenv("GO_TEST_KEY_1", "value")
227}
228
229func TestSetenvWithParallelParentBeforeSetenv(t *testing.T) {
230	t.Parallel()
231
232	t.Run("child", func(t *testing.T) {
233		defer func() {
234			want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
235			if got := recover(); got != want {
236				t.Fatalf("expected panic; got %#v want %q", got, want)
237			}
238		}()
239
240		t.Setenv("GO_TEST_KEY_1", "value")
241	})
242}
243
244func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) {
245	t.Parallel()
246
247	t.Run("child", func(t *testing.T) {
248		t.Run("grand-child", func(t *testing.T) {
249			defer func() {
250				want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
251				if got := recover(); got != want {
252					t.Fatalf("expected panic; got %#v want %q", got, want)
253				}
254			}()
255
256			t.Setenv("GO_TEST_KEY_1", "value")
257		})
258	})
259}
260
261// testingTrueInInit is part of TestTesting.
262var testingTrueInInit = false
263
264// testingTrueInPackageVarInit is part of TestTesting.
265var testingTrueInPackageVarInit = testing.Testing()
266
267// init is part of TestTesting.
268func init() {
269	if testing.Testing() {
270		testingTrueInInit = true
271	}
272}
273
274var testingProg = `
275package main
276
277import (
278	"fmt"
279	"testing"
280)
281
282func main() {
283	fmt.Println(testing.Testing())
284}
285`
286
287func TestTesting(t *testing.T) {
288	if !testing.Testing() {
289		t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
290	}
291	if !testingTrueInInit {
292		t.Errorf("testing.Testing() called by init function == %t, want %t", testingTrueInInit, true)
293	}
294	if !testingTrueInPackageVarInit {
295		t.Errorf("testing.Testing() variable initialized as %t, want %t", testingTrueInPackageVarInit, true)
296	}
297
298	if testing.Short() {
299		t.Skip("skipping building a binary in short mode")
300	}
301	testenv.MustHaveGoRun(t)
302
303	fn := filepath.Join(t.TempDir(), "x.go")
304	if err := os.WriteFile(fn, []byte(testingProg), 0644); err != nil {
305		t.Fatal(err)
306	}
307
308	cmd := testenv.Command(t, testenv.GoToolPath(t), "run", fn)
309	out, err := cmd.CombinedOutput()
310	if err != nil {
311		t.Fatalf("%v failed: %v\n%s", cmd, err, out)
312	}
313
314	s := string(bytes.TrimSpace(out))
315	if s != "false" {
316		t.Errorf("in non-test testing.Test() returned %q, want %q", s, "false")
317	}
318}
319
320// runTest runs a helper test with -test.v, ignoring its exit status.
321// runTest both logs and returns the test output.
322func runTest(t *testing.T, test string) []byte {
323	t.Helper()
324
325	testenv.MustHaveExec(t)
326
327	exe, err := os.Executable()
328	if err != nil {
329		t.Skipf("can't find test executable: %v", err)
330	}
331
332	cmd := testenv.Command(t, exe, "-test.run=^"+test+"$", "-test.bench="+test, "-test.v", "-test.parallel=2", "-test.benchtime=2x")
333	cmd = testenv.CleanCmdEnv(cmd)
334	cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
335	out, err := cmd.CombinedOutput()
336	t.Logf("%v: %v\n%s", cmd, err, out)
337
338	return out
339}
340
341// doRace provokes a data race that generates a race detector report if run
342// under the race detector and is otherwise benign.
343func doRace() {
344	var x int
345	c1 := make(chan bool)
346	go func() {
347		x = 1 // racy write
348		c1 <- true
349	}()
350	_ = x // racy read
351	<-c1
352}
353
354func TestRaceReports(t *testing.T) {
355	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
356		// Generate a race detector report in a sub test.
357		t.Run("Sub", func(t *testing.T) {
358			doRace()
359		})
360		return
361	}
362
363	out := runTest(t, "TestRaceReports")
364
365	// We should see at most one race detector report.
366	c := bytes.Count(out, []byte("race detected"))
367	want := 0
368	if race.Enabled {
369		want = 1
370	}
371	if c != want {
372		t.Errorf("got %d race reports, want %d", c, want)
373	}
374}
375
376// Issue #60083. This used to fail on the race builder.
377func TestRaceName(t *testing.T) {
378	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
379		doRace()
380		return
381	}
382
383	out := runTest(t, "TestRaceName")
384
385	if regexp.MustCompile(`=== NAME\s*$`).Match(out) {
386		t.Errorf("incorrectly reported test with no name")
387	}
388}
389
390func TestRaceSubReports(t *testing.T) {
391	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
392		t.Parallel()
393		c1 := make(chan bool, 1)
394		t.Run("sub", func(t *testing.T) {
395			t.Run("subsub1", func(t *testing.T) {
396				t.Parallel()
397				doRace()
398				c1 <- true
399			})
400			t.Run("subsub2", func(t *testing.T) {
401				t.Parallel()
402				doRace()
403				<-c1
404			})
405		})
406		doRace()
407		return
408	}
409
410	out := runTest(t, "TestRaceSubReports")
411
412	// There should be three race reports: one for each subtest, and one for the
413	// race after the subtests complete. Note that because the subtests run in
414	// parallel, the race stacks may both be printed in with one or the other
415	// test's logs.
416	cReport := bytes.Count(out, []byte("race detected during execution of test"))
417	wantReport := 0
418	if race.Enabled {
419		wantReport = 3
420	}
421	if cReport != wantReport {
422		t.Errorf("got %d race reports, want %d", cReport, wantReport)
423	}
424
425	// Regardless of when the stacks are printed, we expect each subtest to be
426	// marked as failed, and that failure should propagate up to the parents.
427	cFail := bytes.Count(out, []byte("--- FAIL:"))
428	wantFail := 0
429	if race.Enabled {
430		wantFail = 4
431	}
432	if cFail != wantFail {
433		t.Errorf(`got %d "--- FAIL:" lines, want %d`, cReport, wantReport)
434	}
435}
436
437func TestRaceInCleanup(t *testing.T) {
438	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
439		t.Cleanup(doRace)
440		t.Parallel()
441		t.Run("sub", func(t *testing.T) {
442			t.Parallel()
443			// No race should be reported for sub.
444		})
445		return
446	}
447
448	out := runTest(t, "TestRaceInCleanup")
449
450	// There should be one race report, for the parent test only.
451	cReport := bytes.Count(out, []byte("race detected during execution of test"))
452	wantReport := 0
453	if race.Enabled {
454		wantReport = 1
455	}
456	if cReport != wantReport {
457		t.Errorf("got %d race reports, want %d", cReport, wantReport)
458	}
459
460	// Only the parent test should be marked as failed.
461	// (The subtest does not race, and should pass.)
462	cFail := bytes.Count(out, []byte("--- FAIL:"))
463	wantFail := 0
464	if race.Enabled {
465		wantFail = 1
466	}
467	if cFail != wantFail {
468		t.Errorf(`got %d "--- FAIL:" lines, want %d`, cReport, wantReport)
469	}
470}
471
472func TestDeepSubtestRace(t *testing.T) {
473	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
474		t.Run("sub", func(t *testing.T) {
475			t.Run("subsub", func(t *testing.T) {
476				t.Run("subsubsub", func(t *testing.T) {
477					doRace()
478				})
479			})
480			doRace()
481		})
482		return
483	}
484
485	out := runTest(t, "TestDeepSubtestRace")
486
487	c := bytes.Count(out, []byte("race detected during execution of test"))
488	want := 0
489	// There should be two race reports.
490	if race.Enabled {
491		want = 2
492	}
493	if c != want {
494		t.Errorf("got %d race reports, want %d", c, want)
495	}
496}
497
498func TestRaceDuringParallelFailsAllSubtests(t *testing.T) {
499	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
500		var ready sync.WaitGroup
501		ready.Add(2)
502		done := make(chan struct{})
503		go func() {
504			ready.Wait()
505			doRace() // This race happens while both subtests are running.
506			close(done)
507		}()
508
509		t.Run("sub", func(t *testing.T) {
510			t.Run("subsub1", func(t *testing.T) {
511				t.Parallel()
512				ready.Done()
513				<-done
514			})
515			t.Run("subsub2", func(t *testing.T) {
516				t.Parallel()
517				ready.Done()
518				<-done
519			})
520		})
521
522		return
523	}
524
525	out := runTest(t, "TestRaceDuringParallelFailsAllSubtests")
526
527	c := bytes.Count(out, []byte("race detected during execution of test"))
528	want := 0
529	// Each subtest should report the race independently.
530	if race.Enabled {
531		want = 2
532	}
533	if c != want {
534		t.Errorf("got %d race reports, want %d", c, want)
535	}
536}
537
538func TestRaceBeforeParallel(t *testing.T) {
539	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
540		t.Run("sub", func(t *testing.T) {
541			doRace()
542			t.Parallel()
543		})
544		return
545	}
546
547	out := runTest(t, "TestRaceBeforeParallel")
548
549	c := bytes.Count(out, []byte("race detected during execution of test"))
550	want := 0
551	// We should see one race detector report.
552	if race.Enabled {
553		want = 1
554	}
555	if c != want {
556		t.Errorf("got %d race reports, want %d", c, want)
557	}
558}
559
560func TestRaceBeforeTests(t *testing.T) {
561	testenv.MustHaveExec(t)
562
563	exe, err := os.Executable()
564	if err != nil {
565		t.Skipf("can't find test executable: %v", err)
566	}
567
568	cmd := testenv.Command(t, exe, "-test.run=^$")
569	cmd = testenv.CleanCmdEnv(cmd)
570	cmd.Env = append(cmd.Env, "GO_WANT_RACE_BEFORE_TESTS=1")
571	out, _ := cmd.CombinedOutput()
572	t.Logf("%s", out)
573
574	c := bytes.Count(out, []byte("race detected outside of test execution"))
575
576	want := 0
577	if race.Enabled {
578		want = 1
579	}
580	if c != want {
581		t.Errorf("got %d race reports; want %d", c, want)
582	}
583}
584
585func TestBenchmarkRace(t *testing.T) {
586	out := runTest(t, "BenchmarkRacy")
587	c := bytes.Count(out, []byte("race detected during execution of test"))
588
589	want := 0
590	// We should see one race detector report.
591	if race.Enabled {
592		want = 1
593	}
594	if c != want {
595		t.Errorf("got %d race reports; want %d", c, want)
596	}
597}
598
599func BenchmarkRacy(b *testing.B) {
600	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
601		b.Skipf("skipping intentionally-racy benchmark")
602	}
603	for i := 0; i < b.N; i++ {
604		doRace()
605	}
606}
607
608func TestBenchmarkSubRace(t *testing.T) {
609	out := runTest(t, "BenchmarkSubRacy")
610	c := bytes.Count(out, []byte("race detected during execution of test"))
611
612	want := 0
613	// We should see two race detector reports:
614	// one in the sub-bencmark, and one in the parent afterward.
615	if race.Enabled {
616		want = 2
617	}
618	if c != want {
619		t.Errorf("got %d race reports; want %d", c, want)
620	}
621}
622
623func BenchmarkSubRacy(b *testing.B) {
624	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
625		b.Skipf("skipping intentionally-racy benchmark")
626	}
627
628	b.Run("non-racy", func(b *testing.B) {
629		tot := 0
630		for i := 0; i < b.N; i++ {
631			tot++
632		}
633		_ = tot
634	})
635
636	b.Run("racy", func(b *testing.B) {
637		for i := 0; i < b.N; i++ {
638			doRace()
639		}
640	})
641
642	doRace() // should be reported separately
643}
644
645func TestRunningTests(t *testing.T) {
646	t.Parallel()
647
648	// Regression test for https://go.dev/issue/64404:
649	// on timeout, the "running tests" message should not include
650	// tests that are waiting on parked subtests.
651
652	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
653		for i := 0; i < 2; i++ {
654			t.Run(fmt.Sprintf("outer%d", i), func(t *testing.T) {
655				t.Parallel()
656				for j := 0; j < 2; j++ {
657					t.Run(fmt.Sprintf("inner%d", j), func(t *testing.T) {
658						t.Parallel()
659						for {
660							time.Sleep(1 * time.Millisecond)
661						}
662					})
663				}
664			})
665		}
666	}
667
668	timeout := 10 * time.Millisecond
669	for {
670		cmd := testenv.Command(t, os.Args[0], "-test.run=^"+t.Name()+"$", "-test.timeout="+timeout.String(), "-test.parallel=4")
671		cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
672		out, err := cmd.CombinedOutput()
673		t.Logf("%v:\n%s", cmd, out)
674		if _, ok := err.(*exec.ExitError); !ok {
675			t.Fatal(err)
676		}
677
678		// Because the outer subtests (and TestRunningTests itself) are marked as
679		// parallel, their test functions return (and are no longer “running”)
680		// before the inner subtests are released to run and hang.
681		// Only those inner subtests should be reported as running.
682		want := []string{
683			"TestRunningTests/outer0/inner0",
684			"TestRunningTests/outer0/inner1",
685			"TestRunningTests/outer1/inner0",
686			"TestRunningTests/outer1/inner1",
687		}
688
689		got, ok := parseRunningTests(out)
690		if slices.Equal(got, want) {
691			break
692		}
693		if ok {
694			t.Logf("found running tests:\n%s\nwant:\n%s", strings.Join(got, "\n"), strings.Join(want, "\n"))
695		} else {
696			t.Logf("no running tests found")
697		}
698		t.Logf("retrying with longer timeout")
699		timeout *= 2
700	}
701}
702
703func TestRunningTestsInCleanup(t *testing.T) {
704	t.Parallel()
705
706	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
707		for i := 0; i < 2; i++ {
708			t.Run(fmt.Sprintf("outer%d", i), func(t *testing.T) {
709				// Not parallel: we expect to see only one outer test,
710				// stuck in cleanup after its subtest finishes.
711
712				t.Cleanup(func() {
713					for {
714						time.Sleep(1 * time.Millisecond)
715					}
716				})
717
718				for j := 0; j < 2; j++ {
719					t.Run(fmt.Sprintf("inner%d", j), func(t *testing.T) {
720						t.Parallel()
721					})
722				}
723			})
724		}
725	}
726
727	timeout := 10 * time.Millisecond
728	for {
729		cmd := testenv.Command(t, os.Args[0], "-test.run=^"+t.Name()+"$", "-test.timeout="+timeout.String())
730		cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1")
731		out, err := cmd.CombinedOutput()
732		t.Logf("%v:\n%s", cmd, out)
733		if _, ok := err.(*exec.ExitError); !ok {
734			t.Fatal(err)
735		}
736
737		// TestRunningTestsInCleanup is blocked in the call to t.Run,
738		// but its test function has not yet returned so it should still
739		// be considered to be running.
740		// outer1 hasn't even started yet, so only outer0 and the top-level
741		// test function should be reported as running.
742		want := []string{
743			"TestRunningTestsInCleanup",
744			"TestRunningTestsInCleanup/outer0",
745		}
746
747		got, ok := parseRunningTests(out)
748		if slices.Equal(got, want) {
749			break
750		}
751		if ok {
752			t.Logf("found running tests:\n%s\nwant:\n%s", strings.Join(got, "\n"), strings.Join(want, "\n"))
753		} else {
754			t.Logf("no running tests found")
755		}
756		t.Logf("retrying with longer timeout")
757		timeout *= 2
758	}
759}
760
761func parseRunningTests(out []byte) (runningTests []string, ok bool) {
762	inRunningTests := false
763	for _, line := range strings.Split(string(out), "\n") {
764		if inRunningTests {
765			// Package testing adds one tab, the panic printer adds another.
766			if trimmed, ok := strings.CutPrefix(line, "\t\t"); ok {
767				if name, _, ok := strings.Cut(trimmed, " "); ok {
768					runningTests = append(runningTests, name)
769					continue
770				}
771			}
772
773			// This line is not the name of a running test.
774			return runningTests, true
775		}
776
777		if strings.TrimSpace(line) == "running tests:" {
778			inRunningTests = true
779		}
780	}
781
782	return nil, false
783}
784
785func TestConcurrentRun(t *testing.T) {
786	// Regression test for https://go.dev/issue/64402:
787	// this deadlocked after https://go.dev/cl/506755.
788
789	block := make(chan struct{})
790	var ready, done sync.WaitGroup
791	for i := 0; i < 2; i++ {
792		ready.Add(1)
793		done.Add(1)
794		go t.Run("", func(*testing.T) {
795			ready.Done()
796			<-block
797			done.Done()
798		})
799	}
800	ready.Wait()
801	close(block)
802	done.Wait()
803}
804
805func TestParentRun(t1 *testing.T) {
806	// Regression test for https://go.dev/issue/64402:
807	// this deadlocked after https://go.dev/cl/506755.
808
809	t1.Run("outer", func(t2 *testing.T) {
810		t2.Log("Hello outer!")
811		t1.Run("not_inner", func(t3 *testing.T) { // Note: this is t1.Run, not t2.Run.
812			t3.Log("Hello inner!")
813		})
814	})
815}
816