diff --git a/cmd/testwrapper/testdata/A_baseline/raw.txt b/cmd/testwrapper/testdata/A_baseline/raw.txt new file mode 100644 index 000000000..36bfad518 --- /dev/null +++ b/cmd/testwrapper/testdata/A_baseline/raw.txt @@ -0,0 +1,6 @@ +=== RUN TestOne + a_test.go:6: hello from one +--- PASS: TestOne (0.00s) +=== RUN TestTwo +--- PASS: TestTwo (0.00s) +PASS diff --git a/cmd/testwrapper/testdata/A_baseline/src.go b/cmd/testwrapper/testdata/A_baseline/src.go new file mode 100644 index 000000000..5f90db1dd --- /dev/null +++ b/cmd/testwrapper/testdata/A_baseline/src.go @@ -0,0 +1,13 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +package baseline + +import "testing" + +func TestOne(t *testing.T) { + t.Log("hello from one") +} + +func TestTwo(t *testing.T) { +} diff --git a/cmd/testwrapper/testdata/B_inbody/raw.txt b/cmd/testwrapper/testdata/B_inbody/raw.txt new file mode 100644 index 000000000..108a0ec59 --- /dev/null +++ b/cmd/testwrapper/testdata/B_inbody/raw.txt @@ -0,0 +1,30 @@ +=== RUN TestRace +================== +WARNING: DATA RACE +Read at 0x0000007f12a8 by goroutine 8: + racesurvey/B_inbody.TestRace.func1() + /tmp/racesurvey/B_inbody/b_test.go:13 +0x74 + +Previous write at 0x0000007f12a8 by goroutine 9: + racesurvey/B_inbody.TestRace.func2() + /tmp/racesurvey/B_inbody/b_test.go:14 +0x8c + +Goroutine 8 (running) created at: + racesurvey/B_inbody.TestRace() + /tmp/racesurvey/B_inbody/b_test.go:13 +0xbe + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 + +Goroutine 9 (finished) created at: + racesurvey/B_inbody.TestRace() + /tmp/racesurvey/B_inbody/b_test.go:14 +0x124 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 +================== + testing.go:1712: race detected during execution of test +--- FAIL: TestRace (0.00s) +FAIL diff --git a/cmd/testwrapper/testdata/B_inbody/src.go b/cmd/testwrapper/testdata/B_inbody/src.go new file mode 100644 index 000000000..f0abebb99 --- /dev/null +++ b/cmd/testwrapper/testdata/B_inbody/src.go @@ -0,0 +1,19 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +package inbody + +import ( + "sync" + "testing" +) + +var counter int + +func TestRace(t *testing.T) { + var wg sync.WaitGroup + wg.Add(2) + go func() { defer wg.Done(); counter++ }() + go func() { defer wg.Done(); counter++ }() + wg.Wait() +} diff --git a/cmd/testwrapper/testdata/C_spawnwait/caught.raw.txt b/cmd/testwrapper/testdata/C_spawnwait/caught.raw.txt new file mode 100644 index 000000000..c2dcf3655 --- /dev/null +++ b/cmd/testwrapper/testdata/C_spawnwait/caught.raw.txt @@ -0,0 +1,32 @@ +=== RUN TestSpawn +================== +WARNING: DATA RACE +Read at 0x0000007f12a8 by goroutine 9: + racesurvey/C_spawnwait.TestSpawn.func2() + /tmp/racesurvey/C_spawnwait/c_test.go:14 +0x70 + +Previous write at 0x0000007f12a8 by goroutine 8: + racesurvey/C_spawnwait.TestSpawn.func1() + /tmp/racesurvey/C_spawnwait/c_test.go:13 +0x88 + +Goroutine 9 (running) created at: + racesurvey/C_spawnwait.TestSpawn() + /tmp/racesurvey/C_spawnwait/c_test.go:14 +0x44 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 + +Goroutine 8 (finished) created at: + racesurvey/C_spawnwait.TestSpawn() + /tmp/racesurvey/C_spawnwait/c_test.go:13 +0x34 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 +================== + testing.go:1712: race detected during execution of test +--- FAIL: TestSpawn (0.00s) +=== RUN TestWait +--- PASS: TestWait (0.00s) +FAIL diff --git a/cmd/testwrapper/testdata/C_spawnwait/pass.raw.txt b/cmd/testwrapper/testdata/C_spawnwait/pass.raw.txt new file mode 100644 index 000000000..c7ba6ebf3 --- /dev/null +++ b/cmd/testwrapper/testdata/C_spawnwait/pass.raw.txt @@ -0,0 +1,31 @@ +=== RUN TestSpawn +--- PASS: TestSpawn (0.00s) +=== RUN TestWait +================== +WARNING: DATA RACE +Read at 0x0000007f12a8 by goroutine 8: + racesurvey/C_spawnwait.TestSpawn.func1() + /tmp/racesurvey/C_spawnwait/c_test.go:13 +0x70 + +Previous write at 0x0000007f12a8 by goroutine 9: + racesurvey/C_spawnwait.TestSpawn.func2() + /tmp/racesurvey/C_spawnwait/c_test.go:14 +0x88 + +Goroutine 8 (running) created at: + racesurvey/C_spawnwait.TestSpawn() + /tmp/racesurvey/C_spawnwait/c_test.go:13 +0x34 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 + +Goroutine 9 (finished) created at: + racesurvey/C_spawnwait.TestSpawn() + /tmp/racesurvey/C_spawnwait/c_test.go:14 +0x44 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 +================== +--- PASS: TestWait (0.00s) +FAIL diff --git a/cmd/testwrapper/testdata/C_spawnwait/src.go b/cmd/testwrapper/testdata/C_spawnwait/src.go new file mode 100644 index 000000000..42e13fef1 --- /dev/null +++ b/cmd/testwrapper/testdata/C_spawnwait/src.go @@ -0,0 +1,22 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +package spawnwait + +import ( + "sync" + "testing" +) + +var counter int +var wg sync.WaitGroup + +func TestSpawn(t *testing.T) { + wg.Add(2) + go func() { defer wg.Done(); counter++ }() + go func() { defer wg.Done(); counter++ }() +} + +func TestWait(t *testing.T) { + wg.Wait() +} diff --git a/cmd/testwrapper/testdata/D_delayed/raw.txt b/cmd/testwrapper/testdata/D_delayed/raw.txt new file mode 100644 index 000000000..d7d22f21e --- /dev/null +++ b/cmd/testwrapper/testdata/D_delayed/raw.txt @@ -0,0 +1,32 @@ +=== RUN TestA +--- PASS: TestA (0.00s) +=== RUN TestSleep +================== +WARNING: DATA RACE +Read at 0x0000007f12a8 by goroutine 9: + racesurvey/D_postterminal.TestA.func2() + /tmp/racesurvey/D_postterminal/d_test.go:16 +0x8a + +Previous write at 0x0000007f12a8 by goroutine 8: + racesurvey/D_postterminal.TestA.func1() + /tmp/racesurvey/D_postterminal/d_test.go:15 +0xa4 + +Goroutine 9 (running) created at: + racesurvey/D_postterminal.TestA() + /tmp/racesurvey/D_postterminal/d_test.go:16 +0x44 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 + +Goroutine 8 (finished) created at: + racesurvey/D_postterminal.TestA() + /tmp/racesurvey/D_postterminal/d_test.go:15 +0x34 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 +================== + testing.go:1712: race detected during execution of test +--- FAIL: TestSleep (0.05s) +FAIL diff --git a/cmd/testwrapper/testdata/D_delayed/src.go b/cmd/testwrapper/testdata/D_delayed/src.go new file mode 100644 index 000000000..f0fed3cfc --- /dev/null +++ b/cmd/testwrapper/testdata/D_delayed/src.go @@ -0,0 +1,28 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +package delayed + +import ( + "sync" + "testing" + "time" +) + +var counter int +var wg sync.WaitGroup +var trigger = make(chan struct{}) + +func TestA(t *testing.T) { + wg.Add(2) + go func() { defer wg.Done(); <-trigger; counter++ }() + go func() { defer wg.Done(); <-trigger; counter++ }() +} + +func TestSleep(t *testing.T) { + close(trigger) + // Sleep long enough that the goroutines race during this sleep, + // but TestSleep itself doesn't write to counter. + time.Sleep(50 * time.Millisecond) + wg.Wait() +} diff --git a/cmd/testwrapper/testdata/E_testmain/raw.txt b/cmd/testwrapper/testdata/E_testmain/raw.txt new file mode 100644 index 000000000..df96dbe1f --- /dev/null +++ b/cmd/testwrapper/testdata/E_testmain/raw.txt @@ -0,0 +1,26 @@ +=== RUN TestPass +--- PASS: TestPass (0.00s) +PASS +================== +WARNING: DATA RACE +Read at 0x0000007f52a8 by goroutine 9: + racesurvey/E_testmain.TestMain.func2() + /tmp/racesurvey/E_testmain/e_test.go:18 +0x74 + +Previous write at 0x0000007f52a8 by goroutine 8: + racesurvey/E_testmain.TestMain.func1() + /tmp/racesurvey/E_testmain/e_test.go:17 +0x8c + +Goroutine 9 (running) created at: + racesurvey/E_testmain.TestMain() + /tmp/racesurvey/E_testmain/e_test.go:18 +0x139 + main.main() + _testmain.go:48 +0x171 + +Goroutine 8 (finished) created at: + racesurvey/E_testmain.TestMain() + /tmp/racesurvey/E_testmain/e_test.go:17 +0xcc + main.main() + _testmain.go:48 +0x171 +================== +Found 1 data race(s) diff --git a/cmd/testwrapper/testdata/E_testmain/src.go b/cmd/testwrapper/testdata/E_testmain/src.go new file mode 100644 index 000000000..ec15be22b --- /dev/null +++ b/cmd/testwrapper/testdata/E_testmain/src.go @@ -0,0 +1,24 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +package testmain + +import ( + "sync" + "testing" +) + +var counter int + +func TestPass(t *testing.T) { +} + +func TestMain(m *testing.M) { + code := m.Run() + var wg sync.WaitGroup + wg.Add(2) + go func() { defer wg.Done(); counter++ }() + go func() { defer wg.Done(); counter++ }() + wg.Wait() + _ = code +} diff --git a/cmd/testwrapper/testdata/F_parallel/split.raw.txt b/cmd/testwrapper/testdata/F_parallel/split.raw.txt new file mode 100644 index 000000000..6c8e1137d --- /dev/null +++ b/cmd/testwrapper/testdata/F_parallel/split.raw.txt @@ -0,0 +1,57 @@ +=== RUN TestParA +=== PAUSE TestParA +=== RUN TestParB +=== PAUSE TestParB +=== CONT TestParA +=== CONT TestParB +--- PASS: TestParA (0.00s) +================== +WARNING: DATA RACE +Read at 0x0000007f02b0 by goroutine 8: + racesurvey/F_parallel.TestParB() + /tmp/racesurvey/F_parallel/f_test.go:17 +0x3b + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 + +Previous write at 0x0000007f02b0 by goroutine 7: + racesurvey/F_parallel.TestParA() + /tmp/racesurvey/F_parallel/f_test.go:10 +0x53 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.(*T).Run.gowrap1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0x38 + +Goroutine 8 (running) created at: + testing.(*T).Run() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0xb12 + testing.runTests.func1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2585 +0x84 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.runTests() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2583 +0x9e9 + testing.(*M).Run() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2443 +0xf4b + main.main() + _testmain.go:48 +0x164 + +Goroutine 7 (running) created at: + testing.(*T).Run() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2101 +0xb12 + testing.runTests.func1() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2585 +0x84 + testing.tRunner() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2036 +0x21c + testing.runTests() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2583 +0x9e9 + testing.(*M).Run() + /home/ubuntu/sdk/go1.26.3/src/testing/testing.go:2443 +0xf4b + main.main() + _testmain.go:48 +0x164 +================== +=== NAME TestParB + testing.go:1712: race detected during execution of test +--- FAIL: TestParB (0.00s) +FAIL diff --git a/cmd/testwrapper/testdata/F_parallel/src.go b/cmd/testwrapper/testdata/F_parallel/src.go new file mode 100644 index 000000000..18cd968ff --- /dev/null +++ b/cmd/testwrapper/testdata/F_parallel/src.go @@ -0,0 +1,22 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +package parallel + +import "testing" + +var counter int + +func TestParA(t *testing.T) { + t.Parallel() + for i := 0; i < 100; i++ { + counter++ + } +} + +func TestParB(t *testing.T) { + t.Parallel() + for i := 0; i < 100; i++ { + counter++ + } +} diff --git a/cmd/testwrapper/testdata/README.md b/cmd/testwrapper/testdata/README.md new file mode 100644 index 000000000..d15dc64c3 --- /dev/null +++ b/cmd/testwrapper/testdata/README.md @@ -0,0 +1,133 @@ +# Race-output test corpus + +This directory is a corpus of captured Go test binary outputs that +exercise the various ways the `-race` detector's `WARNING: DATA RACE` +text can land relative to `=== RUN` / `--- PASS:` / `--- FAIL:` / +`=== NAME` lines, and how `cmd/internal/test2json` attributes that +output to tests. + +Each scenario subdirectory contains: + +- `src.go` — the Go source code that was compiled and run to produce + the captured output. Reproduce via + `go test -race -c -o /tmp/scenario.test .//`. +- `raw.txt` (or scenario-specific name) — the raw stdout+stderr of + the resulting test binary when run as `./scenario.test -test.v`. + This is the byte stream that `go test -json` feeds to + `go tool test2json` in production. + +`go test -json` adds two things on top of what `test2json` sees, +which are NOT in these captures: a `FAIL\t\t