github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/runtime/crash_cgo_test.go (about) 1 // Copyright 2012 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 cgo 6 7 package runtime_test 8 9 import ( 10 "bytes" 11 "fmt" 12 "internal/testenv" 13 "os" 14 "os/exec" 15 "runtime" 16 "strings" 17 "testing" 18 "time" 19 ) 20 21 func TestCgoCrashHandler(t *testing.T) { 22 t.Parallel() 23 testCrashHandler(t, true) 24 } 25 26 func TestCgoSignalDeadlock(t *testing.T) { 27 t.Parallel() 28 if testing.Short() && runtime.GOOS == "windows" { 29 t.Skip("Skipping in short mode") // takes up to 64 seconds 30 } 31 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock") 32 want := "OK\n" 33 if got != want { 34 t.Fatalf("expected %q, but got:\n%s", want, got) 35 } 36 } 37 38 func TestCgoTraceback(t *testing.T) { 39 t.Parallel() 40 got := runTestProg(t, "testprogcgo", "CgoTraceback") 41 want := "OK\n" 42 if got != want { 43 t.Fatalf("expected %q, but got:\n%s", want, got) 44 } 45 } 46 47 func TestCgoCallbackGC(t *testing.T) { 48 t.Parallel() 49 switch runtime.GOOS { 50 case "plan9", "windows": 51 t.Skipf("no pthreads on %s", runtime.GOOS) 52 } 53 if testing.Short() { 54 switch { 55 case runtime.GOOS == "dragonfly": 56 t.Skip("see golang.org/issue/11990") 57 case runtime.GOOS == "linux" && runtime.GOARCH == "arm": 58 t.Skip("too slow for arm builders") 59 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"): 60 t.Skip("too slow for mips64x builders") 61 } 62 } 63 got := runTestProg(t, "testprogcgo", "CgoCallbackGC") 64 want := "OK\n" 65 if got != want { 66 t.Fatalf("expected %q, but got:\n%s", want, got) 67 } 68 } 69 70 func TestCgoExternalThreadPanic(t *testing.T) { 71 t.Parallel() 72 if runtime.GOOS == "plan9" { 73 t.Skipf("no pthreads on %s", runtime.GOOS) 74 } 75 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic") 76 want := "panic: BOOM" 77 if !strings.Contains(got, want) { 78 t.Fatalf("want failure containing %q. output:\n%s\n", want, got) 79 } 80 } 81 82 func TestCgoExternalThreadSIGPROF(t *testing.T) { 83 t.Parallel() 84 // issue 9456. 85 switch runtime.GOOS { 86 case "plan9", "windows": 87 t.Skipf("no pthreads on %s", runtime.GOOS) 88 case "darwin": 89 if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" { 90 // static constructor needs external linking, but we don't support 91 // external linking on OS X 10.6. 92 out, err := exec.Command("uname", "-r").Output() 93 if err != nil { 94 t.Fatalf("uname -r failed: %v", err) 95 } 96 // OS X 10.6 == Darwin 10.x 97 if strings.HasPrefix(string(out), "10.") { 98 t.Skipf("no external linking on OS X 10.6") 99 } 100 } 101 } 102 if runtime.GOARCH == "ppc64" { 103 // TODO(austin) External linking not implemented on 104 // ppc64 (issue #8912) 105 t.Skipf("no external linking on ppc64") 106 } 107 108 exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof") 109 if err != nil { 110 t.Fatal(err) 111 } 112 113 got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput() 114 if err != nil { 115 t.Fatalf("exit status: %v\n%s", err, got) 116 } 117 118 if want := "OK\n"; string(got) != want { 119 t.Fatalf("expected %q, but got:\n%s", want, got) 120 } 121 } 122 123 func TestCgoExternalThreadSignal(t *testing.T) { 124 t.Parallel() 125 // issue 10139 126 switch runtime.GOOS { 127 case "plan9", "windows": 128 t.Skipf("no pthreads on %s", runtime.GOOS) 129 } 130 131 exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof") 132 if err != nil { 133 t.Fatal(err) 134 } 135 136 got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput() 137 if err != nil { 138 t.Fatalf("exit status: %v\n%s", err, got) 139 } 140 141 want := []byte("OK\n") 142 if !bytes.Equal(got, want) { 143 t.Fatalf("expected %q, but got:\n%s", want, got) 144 } 145 } 146 147 func TestCgoDLLImports(t *testing.T) { 148 // test issue 9356 149 if runtime.GOOS != "windows" { 150 t.Skip("skipping windows specific test") 151 } 152 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain") 153 want := "OK\n" 154 if got != want { 155 t.Fatalf("expected %q, but got %v", want, got) 156 } 157 } 158 159 func TestCgoExecSignalMask(t *testing.T) { 160 t.Parallel() 161 // Test issue 13164. 162 switch runtime.GOOS { 163 case "windows", "plan9": 164 t.Skipf("skipping signal mask test on %s", runtime.GOOS) 165 } 166 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask") 167 want := "OK\n" 168 if got != want { 169 t.Errorf("expected %q, got %v", want, got) 170 } 171 } 172 173 func TestEnsureDropM(t *testing.T) { 174 t.Parallel() 175 // Test for issue 13881. 176 switch runtime.GOOS { 177 case "windows", "plan9": 178 t.Skipf("skipping dropm test on %s", runtime.GOOS) 179 } 180 got := runTestProg(t, "testprogcgo", "EnsureDropM") 181 want := "OK\n" 182 if got != want { 183 t.Errorf("expected %q, got %v", want, got) 184 } 185 } 186 187 // Test for issue 14387. 188 // Test that the program that doesn't need any cgo pointer checking 189 // takes about the same amount of time with it as without it. 190 func TestCgoCheckBytes(t *testing.T) { 191 t.Parallel() 192 // Make sure we don't count the build time as part of the run time. 193 testenv.MustHaveGoBuild(t) 194 exe, err := buildTestProg(t, "testprogcgo") 195 if err != nil { 196 t.Fatal(err) 197 } 198 199 // Try it 10 times to avoid flakiness. 200 const tries = 10 201 var tot1, tot2 time.Duration 202 for i := 0; i < tries; i++ { 203 cmd := testEnv(exec.Command(exe, "CgoCheckBytes")) 204 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i)) 205 206 start := time.Now() 207 cmd.Run() 208 d1 := time.Since(start) 209 210 cmd = testEnv(exec.Command(exe, "CgoCheckBytes")) 211 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i)) 212 213 start = time.Now() 214 cmd.Run() 215 d2 := time.Since(start) 216 217 if d1*20 > d2 { 218 // The slow version (d2) was less than 20 times 219 // slower than the fast version (d1), so OK. 220 return 221 } 222 223 tot1 += d1 224 tot2 += d2 225 } 226 227 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20) 228 } 229 230 func TestCgoPanicDeadlock(t *testing.T) { 231 t.Parallel() 232 // test issue 14432 233 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock") 234 want := "panic: cgo error\n\n" 235 if !strings.HasPrefix(got, want) { 236 t.Fatalf("output does not start with %q:\n%s", want, got) 237 } 238 } 239 240 func TestCgoCCodeSIGPROF(t *testing.T) { 241 t.Parallel() 242 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF") 243 want := "OK\n" 244 if got != want { 245 t.Errorf("expected %q got %v", want, got) 246 } 247 } 248 249 func TestCgoCrashTraceback(t *testing.T) { 250 t.Parallel() 251 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { 252 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) 253 } 254 got := runTestProg(t, "testprogcgo", "CrashTraceback") 255 for i := 1; i <= 3; i++ { 256 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) { 257 t.Errorf("missing cgo symbolizer:%d", i) 258 } 259 } 260 } 261 262 func TestCgoTracebackContext(t *testing.T) { 263 t.Parallel() 264 got := runTestProg(t, "testprogcgo", "TracebackContext") 265 want := "OK\n" 266 if got != want { 267 t.Errorf("expected %q got %v", want, got) 268 } 269 } 270 271 func testCgoPprof(t *testing.T, buildArg, runArg string) { 272 t.Parallel() 273 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { 274 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) 275 } 276 testenv.MustHaveGoRun(t) 277 278 exe, err := buildTestProg(t, "testprogcgo", buildArg) 279 if err != nil { 280 t.Fatal(err) 281 } 282 283 got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput() 284 if err != nil { 285 if testenv.Builder() == "linux-amd64-alpine" { 286 // See Issue 18243 and Issue 19938. 287 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err) 288 } 289 t.Fatal(err) 290 } 291 fn := strings.TrimSpace(string(got)) 292 defer os.Remove(fn) 293 294 for try := 0; try < 2; try++ { 295 cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1")) 296 // Check that pprof works both with and without explicit executable on command line. 297 if try == 0 { 298 cmd.Args = append(cmd.Args, exe, fn) 299 } else { 300 cmd.Args = append(cmd.Args, fn) 301 } 302 303 found := false 304 for i, e := range cmd.Env { 305 if strings.HasPrefix(e, "PPROF_TMPDIR=") { 306 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir() 307 found = true 308 break 309 } 310 } 311 if !found { 312 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir()) 313 } 314 315 top, err := cmd.CombinedOutput() 316 t.Logf("%s:\n%s", cmd.Args, top) 317 if err != nil { 318 t.Error(err) 319 } else if !bytes.Contains(top, []byte("cpuHog")) { 320 t.Error("missing cpuHog in pprof output") 321 } 322 } 323 } 324 325 func TestCgoPprof(t *testing.T) { 326 testCgoPprof(t, "", "CgoPprof") 327 } 328 329 func TestCgoPprofPIE(t *testing.T) { 330 testCgoPprof(t, "-ldflags=-extldflags=-pie", "CgoPprof") 331 } 332 333 func TestCgoPprofThread(t *testing.T) { 334 testCgoPprof(t, "", "CgoPprofThread") 335 } 336 337 func TestCgoPprofThreadNoTraceback(t *testing.T) { 338 testCgoPprof(t, "", "CgoPprofThreadNoTraceback") 339 } 340 341 func TestRaceProf(t *testing.T) { 342 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { 343 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) 344 } 345 346 testenv.MustHaveGoRun(t) 347 348 // This test requires building various packages with -race, so 349 // it's somewhat slow. 350 if testing.Short() { 351 t.Skip("skipping test in -short mode") 352 } 353 354 exe, err := buildTestProg(t, "testprogcgo", "-race") 355 if err != nil { 356 t.Fatal(err) 357 } 358 359 got, err := testEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput() 360 if err != nil { 361 t.Fatal(err) 362 } 363 want := "OK\n" 364 if string(got) != want { 365 t.Errorf("expected %q got %s", want, got) 366 } 367 } 368 369 func TestRaceSignal(t *testing.T) { 370 t.Parallel() 371 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { 372 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) 373 } 374 375 testenv.MustHaveGoRun(t) 376 377 // This test requires building various packages with -race, so 378 // it's somewhat slow. 379 if testing.Short() { 380 t.Skip("skipping test in -short mode") 381 } 382 383 exe, err := buildTestProg(t, "testprogcgo", "-race") 384 if err != nil { 385 t.Fatal(err) 386 } 387 388 got, err := testEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput() 389 if err != nil { 390 t.Logf("%s\n", got) 391 t.Fatal(err) 392 } 393 want := "OK\n" 394 if string(got) != want { 395 t.Errorf("expected %q got %s", want, got) 396 } 397 }