}
}
+func TestGoTestRaceFailures(t *testing.T) {
+ if !canRace {
+ t.Skip("skipping because race detector not supported")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+
+ tg.run("test", "testrace")
+
+ tg.runFail("test", "-race", "testrace")
+ tg.grepStdout("FAIL: TestRace", "TestRace did not fail")
+ tg.grepBothNot("PASS", "something passed")
+
+ tg.runFail("test", "-race", "testrace", "-run", "XXX", "-bench", ".")
+ tg.grepStdout("FAIL: BenchmarkRace", "BenchmarkRace did not fail")
+ tg.grepBothNot("PASS", "something passed")
+}
+
func TestGoTestImportErrorStack(t *testing.T) {
const out = `package testdep/p1 (test)
imports testdep/p2
--- /dev/null
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+ for i := 0; i < 10; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ }
+}
+
+func BenchmarkRace(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ }
+}
"runtime/trace": {"L0"},
"text/tabwriter": {"L2"},
- "testing": {"L2", "flag", "fmt", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
+ "testing": {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
"testing/iotest": {"L2", "log"},
"testing/quick": {"L2", "flag", "fmt", "reflect"},
"internal/testenv": {"L2", "OS", "flag", "testing", "syscall"},
func WriteRange(addr unsafe.Pointer, len int) {
}
+
+func Errors() int { return 0 }
func WriteRange(addr unsafe.Pointer, len int) {
runtime.RaceWriteRange(addr, len)
}
+
+func Errors() int {
+ return runtime.RaceErrors()
+}
func RaceSemacquire(s *uint32)
func RaceSemrelease(s *uint32)
+func RaceErrors() int {
+ var n uint64
+ racecall(&__tsan_report_count, uintptr(unsafe.Pointer(&n)), 0, 0, 0)
+ return int(n)
+}
+
// private interface for the runtime
const raceenabled = true
}
`, `
==================
-PASS
-Found 1 data race\(s\)
+--- FAIL: TestFail \(0.00s\)
+.*testing.go:.*: race detected during execution of test
FAIL`},
{"slicebytetostring_pc", "run", "", "atexit_sleep_ms=0", `
// (that's what is done for C++ ThreadSanitizer tests). This is issue #14119.
cmd.Env = append(cmd.Env,
"GOMAXPROCS=1",
- "GORACE=suppress_equal_stacks=0 suppress_equal_addresses=0 exitcode=0",
+ "GORACE=suppress_equal_stacks=0 suppress_equal_addresses=0",
)
- return cmd.CombinedOutput()
+ // There are races: we expect tests to fail and the exit code to be non-zero.
+ out, _ := cmd.CombinedOutput()
+ return out, nil
}
func TestIssue8102(t *testing.T) {
import (
"flag"
"fmt"
+ "internal/race"
"os"
"runtime"
"sync"
// Try to get a comparable environment for each run
// by clearing garbage from previous runs.
runtime.GC()
+ b.raceErrors = -race.Errors()
b.N = n
b.parallelism = 1
b.ResetTimer()
b.StopTimer()
b.previousN = n
b.previousDuration = b.duration
+ b.raceErrors += race.Errors()
+ if b.raceErrors > 0 {
+ b.Errorf("race detected during execution of benchmark")
+ }
}
func min(x, y int) int {
"errors"
"flag"
"fmt"
+ "internal/race"
"io"
"os"
"runtime"
// common holds the elements common between T and B and
// captures common methods such as Errorf.
type common struct {
- mu sync.RWMutex // guards output, failed, and done.
- output []byte // Output generated by test or benchmark.
- w io.Writer // For flushToParent.
- chatty bool // A copy of the chatty flag.
- ran bool // Test or benchmark (or one of its subtests) was executed.
- failed bool // Test or benchmark has failed.
- skipped bool // Test of benchmark has been skipped.
- finished bool // Test function has completed.
- done bool // Test is finished and all subtests have completed.
- hasSub bool
+ mu sync.RWMutex // guards output, failed, and done.
+ output []byte // Output generated by test or benchmark.
+ w io.Writer // For flushToParent.
+ chatty bool // A copy of the chatty flag.
+ ran bool // Test or benchmark (or one of its subtests) was executed.
+ failed bool // Test or benchmark has failed.
+ skipped bool // Test of benchmark has been skipped.
+ finished bool // Test function has completed.
+ done bool // Test is finished and all subtests have completed.
+ hasSub bool
+ raceErrors int // number of races detected during test
parent *common
level int // Nesting depth of test or benchmark.
// Add to the list of tests to be released by the parent.
t.parent.sub = append(t.parent.sub, t)
+ t.raceErrors += race.Errors()
t.signal <- true // Release calling test.
<-t.parent.barrier // Wait for the parent test to complete.
t.context.waitParallel()
t.start = time.Now()
+ t.raceErrors += -race.Errors()
}
// An internal type but exported because it is cross-package; part of the implementation
// a call to runtime.Goexit, record the duration and send
// a signal saying that the test is done.
defer func() {
+ t.raceErrors += race.Errors()
+ if t.raceErrors > 0 {
+ t.Errorf("race detected during execution of test")
+ }
+
t.duration += time.Now().Sub(t.start)
// If the test panicked, print any test output before dying.
err := recover()
}()
t.start = time.Now()
+ t.raceErrors = -race.Errors()
fn(t)
t.finished = true
}
if !testRan && !exampleRan && *matchBenchmarks == "" {
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
}
- if !testOk || !exampleOk || !runBenchmarks(m.deps.MatchString, m.benchmarks) {
+ if !testOk || !exampleOk || !runBenchmarks(m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
fmt.Println("FAIL")
m.after()
return 1