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.
21 func TestCgoCrashHandler(t *testing.T) {
23 testCrashHandler(t, true)
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).
31 if testing.Short() && runtime.GOOS == "windows" {
32 t.Skip("Skipping in short mode") // takes up to 64 seconds
34 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
37 t.Fatalf("expected %q, but got:\n%s", want, got)
41 func TestCgoTraceback(t *testing.T) {
43 got := runTestProg(t, "testprogcgo", "CgoTraceback")
46 t.Fatalf("expected %q, but got:\n%s", want, got)
50 func TestCgoCallbackGC(t *testing.T) {
53 case "plan9", "windows":
54 t.Skipf("no pthreads on %s", runtime.GOOS)
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")
66 if testenv.Builder() == "darwin-amd64-10_14" {
67 // TODO(#23011): When the 10.14 builders are gone, remove this skip.
68 t.Skip("skipping due to platform bug on macOS 10.14; see https://golang.org/issue/43926")
70 got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
73 t.Fatalf("expected %q, but got:\n%s", want, got)
77 func TestCgoExternalThreadPanic(t *testing.T) {
79 if runtime.GOOS == "plan9" {
80 t.Skipf("no pthreads on %s", runtime.GOOS)
82 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
84 if !strings.Contains(got, want) {
85 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
89 func TestCgoExternalThreadSIGPROF(t *testing.T) {
93 case "plan9", "windows":
94 t.Skipf("no pthreads on %s", runtime.GOOS)
97 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1")
98 if want := "OK\n"; got != want {
99 t.Fatalf("expected %q, but got:\n%s", want, got)
103 func TestCgoExternalThreadSignal(t *testing.T) {
106 switch runtime.GOOS {
107 case "plan9", "windows":
108 t.Skipf("no pthreads on %s", runtime.GOOS)
111 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
112 if want := "OK\n"; got != want {
113 t.Fatalf("expected %q, but got:\n%s", want, got)
117 func TestCgoDLLImports(t *testing.T) {
119 if runtime.GOOS != "windows" {
120 t.Skip("skipping windows specific test")
122 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
125 t.Fatalf("expected %q, but got %v", want, got)
129 func TestCgoExecSignalMask(t *testing.T) {
132 switch runtime.GOOS {
133 case "windows", "plan9":
134 t.Skipf("skipping signal mask test on %s", runtime.GOOS)
136 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system")
139 t.Errorf("expected %q, got %v", want, got)
143 func TestEnsureDropM(t *testing.T) {
145 // Test for issue 13881.
146 switch runtime.GOOS {
147 case "windows", "plan9":
148 t.Skipf("skipping dropm test on %s", runtime.GOOS)
150 got := runTestProg(t, "testprogcgo", "EnsureDropM")
153 t.Errorf("expected %q, got %v", want, got)
157 // Test for issue 14387.
158 // Test that the program that doesn't need any cgo pointer checking
159 // takes about the same amount of time with it as without it.
160 func TestCgoCheckBytes(t *testing.T) {
162 // Make sure we don't count the build time as part of the run time.
163 testenv.MustHaveGoBuild(t)
164 exe, err := buildTestProg(t, "testprogcgo")
169 // Try it 10 times to avoid flakiness.
171 var tot1, tot2 time.Duration
172 for i := 0; i < tries; i++ {
173 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
174 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
178 d1 := time.Since(start)
180 cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
181 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
185 d2 := time.Since(start)
188 // The slow version (d2) was less than 20 times
189 // slower than the fast version (d1), so OK.
197 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
200 func TestCgoPanicDeadlock(t *testing.T) {
203 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
204 want := "panic: cgo error\n\n"
205 if !strings.HasPrefix(got, want) {
206 t.Fatalf("output does not start with %q:\n%s", want, got)
210 func TestCgoCCodeSIGPROF(t *testing.T) {
212 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
215 t.Errorf("expected %q got %v", want, got)
219 func TestCgoPprofCallback(t *testing.T) {
221 switch runtime.GOOS {
222 case "windows", "plan9":
223 t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
225 got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
228 t.Errorf("expected %q got %v", want, got)
232 func TestCgoCrashTraceback(t *testing.T) {
234 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
238 case "linux/ppc64le":
240 t.Skipf("not yet supported on %s", platform)
242 got := runTestProg(t, "testprogcgo", "CrashTraceback")
243 for i := 1; i <= 3; i++ {
244 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
245 t.Errorf("missing cgo symbolizer:%d", i)
250 func TestCgoCrashTracebackGo(t *testing.T) {
252 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
256 case "linux/ppc64le":
258 t.Skipf("not yet supported on %s", platform)
260 got := runTestProg(t, "testprogcgo", "CrashTracebackGo")
261 for i := 1; i <= 3; i++ {
262 want := fmt.Sprintf("main.h%d", i)
263 if !strings.Contains(got, want) {
264 t.Errorf("missing %s", want)
269 func TestCgoTracebackContext(t *testing.T) {
271 got := runTestProg(t, "testprogcgo", "TracebackContext")
274 t.Errorf("expected %q got %v", want, got)
278 func TestCgoTracebackContextPreemption(t *testing.T) {
280 got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
283 t.Errorf("expected %q got %v", want, got)
287 func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
289 if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "arm64") {
290 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
292 testenv.MustHaveGoRun(t)
294 exe, err := buildTestProg(t, "testprogcgo", buildArg)
299 cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
300 got, err := cmd.CombinedOutput()
302 if testenv.Builder() == "linux-amd64-alpine" {
303 // See Issue 18243 and Issue 19938.
304 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
306 t.Fatalf("%s\n\n%v", got, err)
308 fn := strings.TrimSpace(string(got))
311 for try := 0; try < 2; try++ {
312 cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces"))
313 // Check that pprof works both with and without explicit executable on command line.
315 cmd.Args = append(cmd.Args, exe, fn)
317 cmd.Args = append(cmd.Args, fn)
321 for i, e := range cmd.Env {
322 if strings.HasPrefix(e, "PPROF_TMPDIR=") {
323 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
329 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
332 out, err := cmd.CombinedOutput()
333 t.Logf("%s:\n%s", cmd.Args, out)
339 trace := findTrace(string(out), top)
341 t.Errorf("%s traceback missing.", top)
344 if trace[len(trace)-1] != bottom {
345 t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
350 func TestCgoPprof(t *testing.T) {
351 testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
354 func TestCgoPprofPIE(t *testing.T) {
355 testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
358 func TestCgoPprofThread(t *testing.T) {
359 testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
362 func TestCgoPprofThreadNoTraceback(t *testing.T) {
363 testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
366 func TestRaceProf(t *testing.T) {
367 if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
368 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
371 testenv.MustHaveGoRun(t)
373 // This test requires building various packages with -race, so
374 // it's somewhat slow.
376 t.Skip("skipping test in -short mode")
379 exe, err := buildTestProg(t, "testprogcgo", "-race")
384 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
389 if string(got) != want {
390 t.Errorf("expected %q got %s", want, got)
394 func TestRaceSignal(t *testing.T) {
396 if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
397 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
400 testenv.MustHaveGoRun(t)
402 // This test requires building various packages with -race, so
403 // it's somewhat slow.
405 t.Skip("skipping test in -short mode")
408 exe, err := buildTestProg(t, "testprogcgo", "-race")
413 got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
419 if string(got) != want {
420 t.Errorf("expected %q got %s", want, got)
424 func TestCgoNumGoroutine(t *testing.T) {
425 switch runtime.GOOS {
426 case "windows", "plan9":
427 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
430 got := runTestProg(t, "testprogcgo", "NumGoroutine")
433 t.Errorf("expected %q got %v", want, got)
437 func TestCatchPanic(t *testing.T) {
439 switch runtime.GOOS {
440 case "plan9", "windows":
441 t.Skipf("no signals on %s", runtime.GOOS)
443 if runtime.GOARCH == "amd64" {
444 t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
448 testenv.MustHaveGoRun(t)
450 exe, err := buildTestProg(t, "testprogcgo")
455 for _, early := range []bool{true, false} {
456 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
457 // Make sure a panic results in a crash.
458 cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
460 // Tell testprogcgo to install an early signal handler for SIGABRT
461 cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
463 if out, err := cmd.CombinedOutput(); err != nil {
464 t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
469 func TestCgoLockOSThreadExit(t *testing.T) {
470 switch runtime.GOOS {
471 case "plan9", "windows":
472 t.Skipf("no pthreads on %s", runtime.GOOS)
475 testLockOSThreadExit(t, "testprogcgo")
478 func TestWindowsStackMemoryCgo(t *testing.T) {
479 if runtime.GOOS != "windows" {
480 t.Skip("skipping windows specific test")
482 testenv.SkipFlaky(t, 22575)
483 o := runTestProg(t, "testprogcgo", "StackMemory")
484 stackUsage, err := strconv.Atoi(o)
486 t.Fatalf("Failed to read stack usage: %v", err)
488 if expected, got := 100<<10, stackUsage; got > expected {
489 t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
493 func TestSigStackSwapping(t *testing.T) {
494 switch runtime.GOOS {
495 case "plan9", "windows":
496 t.Skipf("no sigaltstack on %s", runtime.GOOS)
499 got := runTestProg(t, "testprogcgo", "SigStack")
502 t.Errorf("expected %q got %v", want, got)
506 func TestCgoTracebackSigpanic(t *testing.T) {
507 // Test unwinding over a sigpanic in C code without a C
508 // symbolizer. See issue #23576.
509 if runtime.GOOS == "windows" {
510 // On Windows if we get an exception in C code, we let
511 // the Windows exception handler unwind it, rather
512 // than injecting a sigpanic.
513 t.Skip("no sigpanic in C on windows")
516 got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
518 want := "runtime.sigpanic"
519 if !strings.Contains(got, want) {
520 t.Errorf("did not see %q in output", want)
522 // No runtime errors like "runtime: unexpected return pc".
523 nowant := "runtime: "
524 if strings.Contains(got, nowant) {
525 t.Errorf("unexpectedly saw %q in output", nowant)
529 func TestCgoPanicCallback(t *testing.T) {
531 got := runTestProg(t, "testprogcgo", "PanicCallback")
533 want := "panic: runtime error: invalid memory address or nil pointer dereference"
534 if !strings.Contains(got, want) {
535 t.Errorf("did not see %q in output", want)
537 want = "panic_callback"
538 if !strings.Contains(got, want) {
539 t.Errorf("did not see %q in output", want)
541 want = "PanicCallback"
542 if !strings.Contains(got, want) {
543 t.Errorf("did not see %q in output", want)
545 // No runtime errors like "runtime: unexpected return pc".
546 nowant := "runtime: "
547 if strings.Contains(got, nowant) {
548 t.Errorf("did not see %q in output", want)
552 // Test that C code called via cgo can use large Windows thread stacks
553 // and call back in to Go without crashing. See issue #20975.
555 // See also TestBigStackCallbackSyscall.
556 func TestBigStackCallbackCgo(t *testing.T) {
557 if runtime.GOOS != "windows" {
558 t.Skip("skipping windows specific test")
561 got := runTestProg(t, "testprogcgo", "BigStack")
564 t.Errorf("expected %q got %v", want, got)
568 func nextTrace(lines []string) ([]string, []string) {
570 for n, line := range lines {
571 if strings.HasPrefix(line, "---") {
572 return trace, lines[n+1:]
574 fields := strings.Fields(strings.TrimSpace(line))
575 if len(fields) == 0 {
578 // Last field contains the function name.
579 trace = append(trace, fields[len(fields)-1])
584 func findTrace(text, top string) []string {
585 lines := strings.Split(text, "\n")
586 _, lines = nextTrace(lines) // Skip the header.
589 t, lines = nextTrace(lines)
600 func TestSegv(t *testing.T) {
601 switch runtime.GOOS {
602 case "plan9", "windows":
603 t.Skipf("no signals on %s", runtime.GOOS)
606 for _, test := range []string{"Segv", "SegvInCgo", "TgkillSegv", "TgkillSegvInCgo"} {
609 // The tgkill variants only run on Linux.
610 if runtime.GOOS != "linux" && strings.HasPrefix(test, "Tgkill") {
614 t.Run(test, func(t *testing.T) {
616 got := runTestProg(t, "testprogcgo", test)
619 if !strings.Contains(got, want) {
620 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
621 testenv.SkipFlaky(t, 39457)
623 t.Errorf("did not see %q in output", want)
626 // No runtime errors like "runtime: unknown pc".
627 switch runtime.GOOS {
628 case "darwin", "illumos", "solaris":
629 // Runtime sometimes throws when generating the traceback.
630 testenv.SkipFlaky(t, 49182)
632 if runtime.GOARCH == "386" {
633 // Runtime throws when generating a traceback from
634 // a VDSO call via asmcgocall.
635 testenv.SkipFlaky(t, 50504)
638 if test == "SegvInCgo" && strings.Contains(got, "unknown pc") {
639 testenv.SkipFlaky(t, 50979)
642 for _, nowant := range []string{"fatal error: ", "runtime: "} {
643 if strings.Contains(got, nowant) {
644 if runtime.GOOS == "darwin" && strings.Contains(got, "0xb01dfacedebac1e") {
645 // See the comment in signal_darwin_amd64.go.
646 t.Skip("skipping due to Darwin handling of malformed addresses")
648 t.Errorf("unexpectedly saw %q in output", nowant)
655 func TestAbortInCgo(t *testing.T) {
656 switch runtime.GOOS {
657 case "plan9", "windows":
658 // N.B. On Windows, C abort() causes the program to exit
659 // without going through the runtime at all.
660 t.Skipf("no signals on %s", runtime.GOOS)
664 got := runTestProg(t, "testprogcgo", "Abort")
667 if !strings.Contains(got, want) {
668 t.Errorf("did not see %q in output", want)
670 // No runtime errors like "runtime: unknown pc".
671 nowant := "runtime: "
672 if strings.Contains(got, nowant) {
673 t.Errorf("did not see %q in output", want)
677 // TestEINTR tests that we handle EINTR correctly.
678 // See issue #20400 and friends.
679 func TestEINTR(t *testing.T) {
680 switch runtime.GOOS {
681 case "plan9", "windows":
682 t.Skipf("no EINTR on %s", runtime.GOOS)
684 if runtime.GOARCH == "386" {
685 // On linux-386 the Go signal handler sets
686 // a restorer function that is not preserved
687 // by the C sigaction call in the test,
688 // causing the signal handler to crash when
689 // returning the normal code. The test is not
690 // architecture-specific, so just skip on 386
691 // rather than doing a complicated workaround.
692 t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer")
697 output := runTestProg(t, "testprogcgo", "EINTR")
700 t.Fatalf("want %s, got %s\n", want, output)
705 func TestNeedmDeadlock(t *testing.T) {
706 switch runtime.GOOS {
707 case "plan9", "windows":
708 t.Skipf("no signals on %s", runtime.GOOS)
710 output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
713 t.Fatalf("want %s, got %s\n", want, output)
717 func TestCgoTracebackGoroutineProfile(t *testing.T) {
718 output := runTestProg(t, "testprogcgo", "GoroutineProfile")
721 t.Fatalf("want %s, got %s\n", want, output)
725 func TestCgoTraceParser(t *testing.T) {
727 switch runtime.GOOS {
728 case "plan9", "windows":
729 t.Skipf("no pthreads on %s", runtime.GOOS)
731 output := runTestProg(t, "testprogcgo", "CgoTraceParser")
733 ErrTimeOrder := "ErrTimeOrder\n"
734 if output == ErrTimeOrder {
735 t.Skipf("skipping due to golang.org/issue/16755: %v", output)
736 } else if output != want {
737 t.Fatalf("want %s, got %s\n", want, output)
741 func TestCgoTraceParserWithOneProc(t *testing.T) {
743 switch runtime.GOOS {
744 case "plan9", "windows":
745 t.Skipf("no pthreads on %s", runtime.GOOS)
747 output := runTestProg(t, "testprogcgo", "CgoTraceParser", "GOMAXPROCS=1")
749 ErrTimeOrder := "ErrTimeOrder\n"
750 if output == ErrTimeOrder {
751 t.Skipf("skipping due to golang.org/issue/16755: %v", output)
752 } else if output != want {
753 t.Fatalf("GOMAXPROCS=1, want %s, got %s\n", want, output)