summaryrefslogtreecommitdiff
path: root/src/runtime/race/output_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/race/output_test.go')
-rw-r--r--src/runtime/race/output_test.go156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go
new file mode 100644
index 000000000..d2303f7af
--- /dev/null
+++ b/src/runtime/race/output_test.go
@@ -0,0 +1,156 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+package race_test
+
+import (
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "testing"
+)
+
+func TestOutput(t *testing.T) {
+ for _, test := range tests {
+ dir, err := ioutil.TempDir("", "go-build")
+ if err != nil {
+ t.Fatalf("failed to create temp directory: %v", err)
+ }
+ defer os.RemoveAll(dir)
+ src := filepath.Join(dir, "main.go")
+ f, err := os.Create(src)
+ if err != nil {
+ t.Fatalf("failed to create file: %v", err)
+ }
+ _, err = f.WriteString(test.source)
+ if err != nil {
+ f.Close()
+ t.Fatalf("failed to write: %v", err)
+ }
+ if err := f.Close(); err != nil {
+ t.Fatalf("failed to close file: %v", err)
+ }
+ // Pass -l to the compiler to test stack traces.
+ cmd := exec.Command("go", "run", "-race", "-gcflags=-l", src)
+ // GODEBUG spoils program output, GOMAXPROCS makes it flaky.
+ for _, env := range os.Environ() {
+ if strings.HasPrefix(env, "GODEBUG=") ||
+ strings.HasPrefix(env, "GOMAXPROCS=") ||
+ strings.HasPrefix(env, "GORACE=") {
+ continue
+ }
+ cmd.Env = append(cmd.Env, env)
+ }
+ cmd.Env = append(cmd.Env, "GORACE="+test.gorace)
+ got, _ := cmd.CombinedOutput()
+ if !regexp.MustCompile(test.re).MatchString(string(got)) {
+ t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s",
+ test.name, test.re, got)
+ }
+ }
+}
+
+var tests = []struct {
+ name string
+ gorace string
+ source string
+ re string
+}{
+ {"simple", "atexit_sleep_ms=0", `
+package main
+import "time"
+func main() {
+ done := make(chan bool)
+ x := 0
+ startRacer(&x, done)
+ store(&x, 43)
+ <-done
+}
+func store(x *int, v int) {
+ *x = v
+}
+func startRacer(x *int, done chan bool) {
+ go racer(x, done)
+}
+func racer(x *int, done chan bool) {
+ time.Sleep(10*time.Millisecond)
+ store(x, 42)
+ done <- true
+}
+`, `==================
+WARNING: DATA RACE
+Write by goroutine [0-9]:
+ main\.store\(\)
+ .+/main\.go:12 \+0x[0-9,a-f]+
+ main\.racer\(\)
+ .+/main\.go:19 \+0x[0-9,a-f]+
+
+Previous write by main goroutine:
+ main\.store\(\)
+ .+/main\.go:12 \+0x[0-9,a-f]+
+ main\.main\(\)
+ .+/main\.go:8 \+0x[0-9,a-f]+
+
+Goroutine [0-9] \(running\) created at:
+ main\.startRacer\(\)
+ .+/main\.go:15 \+0x[0-9,a-f]+
+ main\.main\(\)
+ .+/main\.go:7 \+0x[0-9,a-f]+
+==================
+Found 1 data race\(s\)
+exit status 66
+`},
+
+ {"exitcode", "atexit_sleep_ms=0 exitcode=13", `
+package main
+func main() {
+ done := make(chan bool)
+ x := 0
+ go func() {
+ x = 42
+ done <- true
+ }()
+ x = 43
+ <-done
+}
+`, `exit status 13`},
+
+ {"strip_path_prefix", "atexit_sleep_ms=0 strip_path_prefix=/main.", `
+package main
+func main() {
+ done := make(chan bool)
+ x := 0
+ go func() {
+ x = 42
+ done <- true
+ }()
+ x = 43
+ <-done
+}
+`, `
+ go:7 \+0x[0-9,a-f]+
+`},
+
+ {"halt_on_error", "atexit_sleep_ms=0 halt_on_error=1", `
+package main
+func main() {
+ done := make(chan bool)
+ x := 0
+ go func() {
+ x = 42
+ done <- true
+ }()
+ x = 43
+ <-done
+}
+`, `
+==================
+exit status 66
+`},
+}