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