github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/race/output_test.go (about) 1 // Copyright 2013 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 5 // +build race 6 7 package race_test 8 9 import ( 10 "internal/testenv" 11 "io/ioutil" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "regexp" 16 "runtime" 17 "strings" 18 "testing" 19 ) 20 21 func TestOutput(t *testing.T) { 22 pkgdir, err := ioutil.TempDir("", "go-build-race-output") 23 if err != nil { 24 t.Fatal(err) 25 } 26 defer os.RemoveAll(pkgdir) 27 out, err := exec.Command(testenv.GoToolPath(t), "install", "-race", "-pkgdir="+pkgdir, "-gcflags=all=-l", "testing").CombinedOutput() 28 if err != nil { 29 t.Fatalf("go install -race: %v\n%s", err, out) 30 } 31 32 for _, test := range tests { 33 if test.goos != "" && test.goos != runtime.GOOS { 34 t.Logf("test %v runs only on %v, skipping: ", test.name, test.goos) 35 continue 36 } 37 dir, err := ioutil.TempDir("", "go-build") 38 if err != nil { 39 t.Fatalf("failed to create temp directory: %v", err) 40 } 41 defer os.RemoveAll(dir) 42 source := "main.go" 43 if test.run == "test" { 44 source = "main_test.go" 45 } 46 src := filepath.Join(dir, source) 47 f, err := os.Create(src) 48 if err != nil { 49 t.Fatalf("failed to create file: %v", err) 50 } 51 _, err = f.WriteString(test.source) 52 if err != nil { 53 f.Close() 54 t.Fatalf("failed to write: %v", err) 55 } 56 if err := f.Close(); err != nil { 57 t.Fatalf("failed to close file: %v", err) 58 } 59 // Pass -l to the compiler to test stack traces. 60 cmd := exec.Command(testenv.GoToolPath(t), test.run, "-race", "-pkgdir="+pkgdir, "-gcflags=all=-l", src) 61 // GODEBUG spoils program output, GOMAXPROCS makes it flaky. 62 for _, env := range os.Environ() { 63 if strings.HasPrefix(env, "GODEBUG=") || 64 strings.HasPrefix(env, "GOMAXPROCS=") || 65 strings.HasPrefix(env, "GORACE=") { 66 continue 67 } 68 cmd.Env = append(cmd.Env, env) 69 } 70 cmd.Env = append(cmd.Env, 71 "GOMAXPROCS=1", // see comment in race_test.go 72 "GORACE="+test.gorace, 73 ) 74 got, _ := cmd.CombinedOutput() 75 if !regexp.MustCompile(test.re).MatchString(string(got)) { 76 t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s", 77 test.name, test.re, got) 78 } 79 } 80 } 81 82 var tests = []struct { 83 name string 84 run string 85 goos string 86 gorace string 87 source string 88 re string 89 }{ 90 {"simple", "run", "", "atexit_sleep_ms=0", ` 91 package main 92 import "time" 93 func main() { 94 done := make(chan bool) 95 x := 0 96 startRacer(&x, done) 97 store(&x, 43) 98 <-done 99 } 100 func store(x *int, v int) { 101 *x = v 102 } 103 func startRacer(x *int, done chan bool) { 104 go racer(x, done) 105 } 106 func racer(x *int, done chan bool) { 107 time.Sleep(10*time.Millisecond) 108 store(x, 42) 109 done <- true 110 } 111 `, `================== 112 WARNING: DATA RACE 113 Write at 0x[0-9,a-f]+ by goroutine [0-9]: 114 main\.store\(\) 115 .+/main\.go:12 \+0x[0-9,a-f]+ 116 main\.racer\(\) 117 .+/main\.go:19 \+0x[0-9,a-f]+ 118 119 Previous write at 0x[0-9,a-f]+ by main goroutine: 120 main\.store\(\) 121 .+/main\.go:12 \+0x[0-9,a-f]+ 122 main\.main\(\) 123 .+/main\.go:8 \+0x[0-9,a-f]+ 124 125 Goroutine [0-9] \(running\) created at: 126 main\.startRacer\(\) 127 .+/main\.go:15 \+0x[0-9,a-f]+ 128 main\.main\(\) 129 .+/main\.go:7 \+0x[0-9,a-f]+ 130 ================== 131 Found 1 data race\(s\) 132 exit status 66 133 `}, 134 135 {"exitcode", "run", "", "atexit_sleep_ms=0 exitcode=13", ` 136 package main 137 func main() { 138 done := make(chan bool) 139 x := 0 140 go func() { 141 x = 42 142 done <- true 143 }() 144 x = 43 145 <-done 146 } 147 `, `exit status 13`}, 148 149 {"strip_path_prefix", "run", "", "atexit_sleep_ms=0 strip_path_prefix=/main.", ` 150 package main 151 func main() { 152 done := make(chan bool) 153 x := 0 154 go func() { 155 x = 42 156 done <- true 157 }() 158 x = 43 159 <-done 160 } 161 `, ` 162 go:7 \+0x[0-9,a-f]+ 163 `}, 164 165 {"halt_on_error", "run", "", "atexit_sleep_ms=0 halt_on_error=1", ` 166 package main 167 func main() { 168 done := make(chan bool) 169 x := 0 170 go func() { 171 x = 42 172 done <- true 173 }() 174 x = 43 175 <-done 176 } 177 `, ` 178 ================== 179 exit status 66 180 `}, 181 182 {"test_fails_on_race", "test", "", "atexit_sleep_ms=0", ` 183 package main_test 184 import "testing" 185 func TestFail(t *testing.T) { 186 done := make(chan bool) 187 x := 0 188 _ = x 189 go func() { 190 x = 42 191 done <- true 192 }() 193 x = 43 194 <-done 195 t.Log(t.Failed()) 196 } 197 `, ` 198 ================== 199 --- FAIL: TestFail \(0...s\) 200 .*main_test.go:14: true 201 .*testing.go:.*: race detected during execution of test 202 FAIL`}, 203 204 {"slicebytetostring_pc", "run", "", "atexit_sleep_ms=0", ` 205 package main 206 func main() { 207 done := make(chan string) 208 data := make([]byte, 10) 209 go func() { 210 done <- string(data) 211 }() 212 data[0] = 1 213 <-done 214 } 215 `, ` 216 runtime\.slicebytetostring\(\) 217 .*/runtime/string\.go:.* 218 main\.main\.func1\(\) 219 .*/main.go:7`}, 220 221 // Test for http://golang.org/issue/17190 222 {"external_cgo_thread", "run", "linux", "atexit_sleep_ms=0", ` 223 package main 224 225 /* 226 #include <pthread.h> 227 typedef struct cb { 228 int foo; 229 } cb; 230 extern void goCallback(); 231 static inline void *threadFunc(void *p) { 232 goCallback(); 233 return 0; 234 } 235 static inline void startThread(cb* c) { 236 pthread_t th; 237 pthread_create(&th, 0, threadFunc, 0); 238 } 239 */ 240 import "C" 241 242 import "time" 243 244 var racy int 245 246 //export goCallback 247 func goCallback() { 248 racy++ 249 } 250 251 func main() { 252 var c C.cb 253 C.startThread(&c) 254 time.Sleep(time.Second) 255 racy++ 256 } 257 `, `================== 258 WARNING: DATA RACE 259 Read at 0x[0-9,a-f]+ by main goroutine: 260 main\.main\(\) 261 .*/main\.go:34 \+0x[0-9,a-f]+ 262 263 Previous write at 0x[0-9,a-f]+ by goroutine [0-9]: 264 main\.goCallback\(\) 265 .*/main\.go:27 \+0x[0-9,a-f]+ 266 main._cgoexpwrap_[0-9a-z]+_goCallback\(\) 267 .*_cgo_gotypes\.go:[0-9]+ \+0x[0-9,a-f]+ 268 269 Goroutine [0-9] \(running\) created at: 270 runtime\.newextram\(\) 271 .*/runtime/proc.go:[0-9]+ \+0x[0-9,a-f]+ 272 ==================`}, 273 {"second_test_passes", "test", "", "atexit_sleep_ms=0", ` 274 package main_test 275 import "testing" 276 func TestFail(t *testing.T) { 277 done := make(chan bool) 278 x := 0 279 _ = x 280 go func() { 281 x = 42 282 done <- true 283 }() 284 x = 43 285 <-done 286 } 287 288 func TestPass(t *testing.T) { 289 } 290 `, ` 291 ================== 292 --- FAIL: TestFail \(0...s\) 293 .*testing.go:.*: race detected during execution of test 294 FAIL`}, 295 }