github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/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 "github.com/c12o16h1/go/src/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, "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 60 cmd := exec.Command(testenv.GoToolPath(t), test.run, "-race", "-pkgdir="+pkgdir, 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 https://golang.org/issue/33309 222 {"midstack_inlining_traceback", "run", "linux", "atexit_sleep_ms=0", ` 223 package main 224 225 var x int 226 227 func main() { 228 c := make(chan int) 229 go f(c) 230 x = 1 231 <-c 232 } 233 234 func f(c chan int) { 235 g(c) 236 } 237 238 func g(c chan int) { 239 h(c) 240 } 241 242 func h(c chan int) { 243 c <- x 244 } 245 `, `================== 246 WARNING: DATA RACE 247 Read at 0x[0-9,a-f]+ by goroutine [0-9]: 248 main\.h\(\) 249 .+/main\.go:22 \+0x[0-9,a-f]+ 250 main\.g\(\) 251 .+/main\.go:18 \+0x[0-9,a-f]+ 252 main\.f\(\) 253 .+/main\.go:14 \+0x[0-9,a-f]+ 254 255 Previous write at 0x[0-9,a-f]+ by main goroutine: 256 main\.main\(\) 257 .+/main\.go:9 \+0x[0-9,a-f]+ 258 259 Goroutine [0-9] \(running\) created at: 260 main\.main\(\) 261 .+/main\.go:8 \+0x[0-9,a-f]+ 262 ================== 263 Found 1 data race\(s\) 264 exit status 66 265 `}, 266 267 // Test for https://golang.org/issue/17190 268 {"external_cgo_thread", "run", "linux", "atexit_sleep_ms=0", ` 269 package main 270 271 /* 272 #include <pthread.h> 273 typedef struct cb { 274 int foo; 275 } cb; 276 extern void goCallback(); 277 static inline void *threadFunc(void *p) { 278 goCallback(); 279 return 0; 280 } 281 static inline void startThread(cb* c) { 282 pthread_t th; 283 pthread_create(&th, 0, threadFunc, 0); 284 } 285 */ 286 import "C" 287 288 import "time" 289 290 var racy int 291 292 //export goCallback 293 func goCallback() { 294 racy++ 295 } 296 297 func main() { 298 var c C.cb 299 C.startThread(&c) 300 time.Sleep(time.Second) 301 racy++ 302 } 303 `, `================== 304 WARNING: DATA RACE 305 Read at 0x[0-9,a-f]+ by main goroutine: 306 main\.main\(\) 307 .*/main\.go:34 \+0x[0-9,a-f]+ 308 309 Previous write at 0x[0-9,a-f]+ by goroutine [0-9]: 310 main\.goCallback\(\) 311 .*/main\.go:27 \+0x[0-9,a-f]+ 312 main._cgoexpwrap_[0-9a-z]+_goCallback\(\) 313 .*_cgo_gotypes\.go:[0-9]+ \+0x[0-9,a-f]+ 314 315 Goroutine [0-9] \(running\) created at: 316 runtime\.newextram\(\) 317 .*/runtime/proc.go:[0-9]+ \+0x[0-9,a-f]+ 318 ==================`}, 319 {"second_test_passes", "test", "", "atexit_sleep_ms=0", ` 320 package main_test 321 import "testing" 322 func TestFail(t *testing.T) { 323 done := make(chan bool) 324 x := 0 325 _ = x 326 go func() { 327 x = 42 328 done <- true 329 }() 330 x = 43 331 <-done 332 } 333 334 func TestPass(t *testing.T) { 335 } 336 `, ` 337 ================== 338 --- FAIL: TestFail \(0...s\) 339 .*testing.go:.*: race detected during execution of test 340 FAIL`}, 341 }