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