github.com/gidoBOSSftw5731/go/src@v0.0.0-20210226122457-d24b0edbf019/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 //go:build race 6 // +build race 7 8 package race_test 9 10 import ( 11 "fmt" 12 "internal/testenv" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "regexp" 17 "runtime" 18 "strings" 19 "testing" 20 ) 21 22 func TestOutput(t *testing.T) { 23 pkgdir, err := os.MkdirTemp("", "go-build-race-output") 24 if err != nil { 25 t.Fatal(err) 26 } 27 defer os.RemoveAll(pkgdir) 28 out, err := exec.Command(testenv.GoToolPath(t), "install", "-race", "-pkgdir="+pkgdir, "testing").CombinedOutput() 29 if err != nil { 30 t.Fatalf("go install -race: %v\n%s", err, out) 31 } 32 33 for _, test := range tests { 34 if test.goos != "" && test.goos != runtime.GOOS { 35 t.Logf("test %v runs only on %v, skipping: ", test.name, test.goos) 36 continue 37 } 38 dir, err := os.MkdirTemp("", "go-build") 39 if err != nil { 40 t.Fatalf("failed to create temp directory: %v", err) 41 } 42 defer os.RemoveAll(dir) 43 source := "main.go" 44 if test.run == "test" { 45 source = "main_test.go" 46 } 47 src := filepath.Join(dir, source) 48 f, err := os.Create(src) 49 if err != nil { 50 t.Fatalf("failed to create file: %v", err) 51 } 52 _, err = f.WriteString(test.source) 53 if err != nil { 54 f.Close() 55 t.Fatalf("failed to write: %v", err) 56 } 57 if err := f.Close(); err != nil { 58 t.Fatalf("failed to close file: %v", err) 59 } 60 61 cmd := exec.Command(testenv.GoToolPath(t), test.run, "-race", "-pkgdir="+pkgdir, src) 62 // GODEBUG spoils program output, GOMAXPROCS makes it flaky. 63 for _, env := range os.Environ() { 64 if strings.HasPrefix(env, "GODEBUG=") || 65 strings.HasPrefix(env, "GOMAXPROCS=") || 66 strings.HasPrefix(env, "GORACE=") { 67 continue 68 } 69 cmd.Env = append(cmd.Env, env) 70 } 71 cmd.Env = append(cmd.Env, 72 "GOMAXPROCS=1", // see comment in race_test.go 73 "GORACE="+test.gorace, 74 ) 75 got, _ := cmd.CombinedOutput() 76 matched := false 77 for _, re := range test.re { 78 if regexp.MustCompile(re).MatchString(string(got)) { 79 matched = true 80 break 81 } 82 } 83 if !matched { 84 exp := fmt.Sprintf("expect:\n%v\n", test.re[0]) 85 if len(test.re) > 1 { 86 exp = fmt.Sprintf("expected one of %d patterns:\n", 87 len(test.re)) 88 for k, re := range test.re { 89 exp += fmt.Sprintf("pattern %d:\n%v\n", k, re) 90 } 91 } 92 t.Fatalf("failed test case %v, %sgot:\n%s", 93 test.name, exp, got) 94 } 95 } 96 } 97 98 var tests = []struct { 99 name string 100 run string 101 goos string 102 gorace string 103 source string 104 re []string 105 }{ 106 {"simple", "run", "", "atexit_sleep_ms=0", ` 107 package main 108 import "time" 109 func main() { 110 done := make(chan bool) 111 x := 0 112 startRacer(&x, done) 113 store(&x, 43) 114 <-done 115 } 116 func store(x *int, v int) { 117 *x = v 118 } 119 func startRacer(x *int, done chan bool) { 120 go racer(x, done) 121 } 122 func racer(x *int, done chan bool) { 123 time.Sleep(10*time.Millisecond) 124 store(x, 42) 125 done <- true 126 } 127 `, []string{`================== 128 WARNING: DATA RACE 129 Write at 0x[0-9,a-f]+ by goroutine [0-9]: 130 main\.store\(\) 131 .+/main\.go:12 \+0x[0-9,a-f]+ 132 main\.racer\(\) 133 .+/main\.go:19 \+0x[0-9,a-f]+ 134 135 Previous write at 0x[0-9,a-f]+ by main goroutine: 136 main\.store\(\) 137 .+/main\.go:12 \+0x[0-9,a-f]+ 138 main\.main\(\) 139 .+/main\.go:8 \+0x[0-9,a-f]+ 140 141 Goroutine [0-9] \(running\) created at: 142 main\.startRacer\(\) 143 .+/main\.go:15 \+0x[0-9,a-f]+ 144 main\.main\(\) 145 .+/main\.go:7 \+0x[0-9,a-f]+ 146 ================== 147 Found 1 data race\(s\) 148 exit status 66 149 `}}, 150 151 {"exitcode", "run", "", "atexit_sleep_ms=0 exitcode=13", ` 152 package main 153 func main() { 154 done := make(chan bool) 155 x := 0 156 go func() { 157 x = 42 158 done <- true 159 }() 160 x = 43 161 <-done 162 } 163 `, []string{`exit status 13`}}, 164 165 {"strip_path_prefix", "run", "", "atexit_sleep_ms=0 strip_path_prefix=/main.", ` 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 `, []string{` 178 go:7 \+0x[0-9,a-f]+ 179 `}}, 180 181 {"halt_on_error", "run", "", "atexit_sleep_ms=0 halt_on_error=1", ` 182 package main 183 func main() { 184 done := make(chan bool) 185 x := 0 186 go func() { 187 x = 42 188 done <- true 189 }() 190 x = 43 191 <-done 192 } 193 `, []string{` 194 ================== 195 exit status 66 196 `}}, 197 198 {"test_fails_on_race", "test", "", "atexit_sleep_ms=0", ` 199 package main_test 200 import "testing" 201 func TestFail(t *testing.T) { 202 done := make(chan bool) 203 x := 0 204 _ = x 205 go func() { 206 x = 42 207 done <- true 208 }() 209 x = 43 210 <-done 211 t.Log(t.Failed()) 212 } 213 `, []string{` 214 ================== 215 --- FAIL: TestFail \(0...s\) 216 .*main_test.go:14: true 217 .*testing.go:.*: race detected during execution of test 218 FAIL`}}, 219 220 {"slicebytetostring_pc", "run", "", "atexit_sleep_ms=0", ` 221 package main 222 func main() { 223 done := make(chan string) 224 data := make([]byte, 10) 225 go func() { 226 done <- string(data) 227 }() 228 data[0] = 1 229 <-done 230 } 231 `, []string{` 232 runtime\.slicebytetostring\(\) 233 .*/runtime/string\.go:.* 234 main\.main\.func1\(\) 235 .*/main.go:7`}}, 236 237 // Test for https://golang.org/issue/33309 238 {"midstack_inlining_traceback", "run", "linux", "atexit_sleep_ms=0", ` 239 package main 240 241 var x int 242 243 func main() { 244 c := make(chan int) 245 go f(c) 246 x = 1 247 <-c 248 } 249 250 func f(c chan int) { 251 g(c) 252 } 253 254 func g(c chan int) { 255 h(c) 256 } 257 258 func h(c chan int) { 259 c <- x 260 } 261 `, []string{`================== 262 WARNING: DATA RACE 263 Read at 0x[0-9,a-f]+ by goroutine [0-9]: 264 main\.h\(\) 265 .+/main\.go:22 \+0x[0-9,a-f]+ 266 main\.g\(\) 267 .+/main\.go:18 \+0x[0-9,a-f]+ 268 main\.f\(\) 269 .+/main\.go:14 \+0x[0-9,a-f]+ 270 271 Previous write at 0x[0-9,a-f]+ by main goroutine: 272 main\.main\(\) 273 .+/main\.go:9 \+0x[0-9,a-f]+ 274 275 Goroutine [0-9] \(running\) created at: 276 main\.main\(\) 277 .+/main\.go:8 \+0x[0-9,a-f]+ 278 ================== 279 Found 1 data race\(s\) 280 exit status 66 281 `}}, 282 283 // Test for https://golang.org/issue/17190 284 {"external_cgo_thread", "run", "linux", "atexit_sleep_ms=0", ` 285 package main 286 287 /* 288 #include <pthread.h> 289 typedef struct cb { 290 int foo; 291 } cb; 292 extern void goCallback(); 293 static inline void *threadFunc(void *p) { 294 goCallback(); 295 return 0; 296 } 297 static inline void startThread(cb* c) { 298 pthread_t th; 299 pthread_create(&th, 0, threadFunc, 0); 300 } 301 */ 302 import "C" 303 304 var done chan bool 305 var racy int 306 307 //export goCallback 308 func goCallback() { 309 racy++ 310 done <- true 311 } 312 313 func main() { 314 done = make(chan bool) 315 var c C.cb 316 C.startThread(&c) 317 racy++ 318 <- done 319 } 320 `, []string{`================== 321 WARNING: DATA RACE 322 Read at 0x[0-9,a-f]+ by main goroutine: 323 main\.main\(\) 324 .*/main\.go:34 \+0x[0-9,a-f]+ 325 326 Previous write at 0x[0-9,a-f]+ by goroutine [0-9]: 327 main\.goCallback\(\) 328 .*/main\.go:27 \+0x[0-9,a-f]+ 329 _cgoexp_[0-9a-z]+_goCallback\(\) 330 .*_cgo_gotypes\.go:[0-9]+ \+0x[0-9,a-f]+ 331 _cgoexp_[0-9a-z]+_goCallback\(\) 332 <autogenerated>:1 \+0x[0-9,a-f]+ 333 334 Goroutine [0-9] \(running\) created at: 335 runtime\.newextram\(\) 336 .*/runtime/proc.go:[0-9]+ \+0x[0-9,a-f]+ 337 ==================`, 338 `================== 339 WARNING: DATA RACE 340 Read at 0x[0-9,a-f]+ by .*: 341 main\..* 342 .*/main\.go:[0-9]+ \+0x[0-9,a-f]+(?s).* 343 344 Previous write at 0x[0-9,a-f]+ by .*: 345 main\..* 346 .*/main\.go:[0-9]+ \+0x[0-9,a-f]+(?s).* 347 348 Goroutine [0-9] \(running\) created at: 349 runtime\.newextram\(\) 350 .*/runtime/proc.go:[0-9]+ \+0x[0-9,a-f]+ 351 ==================`}}, 352 {"second_test_passes", "test", "", "atexit_sleep_ms=0", ` 353 package main_test 354 import "testing" 355 func TestFail(t *testing.T) { 356 done := make(chan bool) 357 x := 0 358 _ = x 359 go func() { 360 x = 42 361 done <- true 362 }() 363 x = 43 364 <-done 365 } 366 367 func TestPass(t *testing.T) { 368 } 369 `, []string{` 370 ================== 371 --- FAIL: TestFail \(0...s\) 372 .*testing.go:.*: race detected during execution of test 373 FAIL`}}, 374 {"mutex", "run", "", "atexit_sleep_ms=0", ` 375 package main 376 import ( 377 "sync" 378 "fmt" 379 ) 380 func main() { 381 c := make(chan bool, 1) 382 threads := 1 383 iterations := 20000 384 data := 0 385 var wg sync.WaitGroup 386 for i := 0; i < threads; i++ { 387 wg.Add(1) 388 go func() { 389 defer wg.Done() 390 for i := 0; i < iterations; i++ { 391 c <- true 392 data += 1 393 <- c 394 } 395 }() 396 } 397 for i := 0; i < iterations; i++ { 398 c <- true 399 data += 1 400 <- c 401 } 402 wg.Wait() 403 if (data == iterations*(threads+1)) { fmt.Println("pass") } 404 }`, []string{`pass`}}, 405 // Test for https://github.com/golang/go/issues/37355 406 {"chanmm", "run", "", "atexit_sleep_ms=0", ` 407 package main 408 import ( 409 "sync" 410 "time" 411 ) 412 func main() { 413 c := make(chan bool, 1) 414 var data uint64 415 var wg sync.WaitGroup 416 wg.Add(2) 417 c <- true 418 go func() { 419 defer wg.Done() 420 c <- true 421 }() 422 go func() { 423 defer wg.Done() 424 time.Sleep(time.Second) 425 <-c 426 data = 2 427 }() 428 data = 1 429 <-c 430 wg.Wait() 431 _ = data 432 } 433 `, []string{`================== 434 WARNING: DATA RACE 435 Write at 0x[0-9,a-f]+ by goroutine [0-9]: 436 main\.main\.func2\(\) 437 .*/main\.go:21 \+0x[0-9,a-f]+ 438 439 Previous write at 0x[0-9,a-f]+ by main goroutine: 440 main\.main\(\) 441 .*/main\.go:23 \+0x[0-9,a-f]+ 442 443 Goroutine [0-9] \(running\) created at: 444 main\.main\(\) 445 .*/main.go:[0-9]+ \+0x[0-9,a-f]+ 446 ==================`}}, 447 }