Source file
src/runtime/crash_cgo_test.go
1
2
3
4
5
6
7 package runtime_test
8
9 import (
10 "fmt"
11 "internal/goos"
12 "internal/platform"
13 "internal/testenv"
14 "os"
15 "os/exec"
16 "runtime"
17 "strconv"
18 "strings"
19 "testing"
20 "time"
21 )
22
23 func TestCgoCrashHandler(t *testing.T) {
24 t.Parallel()
25 testCrashHandler(t, true)
26 }
27
28 func TestCgoSignalDeadlock(t *testing.T) {
29
30
31
32
33 if testing.Short() && runtime.GOOS == "windows" {
34 t.Skip("Skipping in short mode")
35 }
36 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
37 want := "OK\n"
38 if got != want {
39 t.Fatalf("expected %q, but got:\n%s", want, got)
40 }
41 }
42
43 func TestCgoTraceback(t *testing.T) {
44 t.Parallel()
45 got := runTestProg(t, "testprogcgo", "CgoTraceback")
46 want := "OK\n"
47 if got != want {
48 t.Fatalf("expected %q, but got:\n%s", want, got)
49 }
50 }
51
52 func TestCgoCallbackGC(t *testing.T) {
53 t.Parallel()
54 switch runtime.GOOS {
55 case "plan9", "windows":
56 t.Skipf("no pthreads on %s", runtime.GOOS)
57 }
58 if testing.Short() {
59 switch {
60 case runtime.GOOS == "dragonfly":
61 t.Skip("see golang.org/issue/11990")
62 case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
63 t.Skip("too slow for arm builders")
64 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
65 t.Skip("too slow for mips64x builders")
66 }
67 }
68 got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
69 want := "OK\n"
70 if got != want {
71 t.Fatalf("expected %q, but got:\n%s", want, got)
72 }
73 }
74
75 func TestCgoExternalThreadPanic(t *testing.T) {
76 t.Parallel()
77 if runtime.GOOS == "plan9" {
78 t.Skipf("no pthreads on %s", runtime.GOOS)
79 }
80 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
81 want := "panic: BOOM"
82 if !strings.Contains(got, want) {
83 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
84 }
85 }
86
87 func TestCgoExternalThreadSIGPROF(t *testing.T) {
88 t.Parallel()
89
90 switch runtime.GOOS {
91 case "plan9", "windows":
92 t.Skipf("no pthreads on %s", runtime.GOOS)
93 }
94
95 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1")
96 if want := "OK\n"; got != want {
97 t.Fatalf("expected %q, but got:\n%s", want, got)
98 }
99 }
100
101 func TestCgoExternalThreadSignal(t *testing.T) {
102 t.Parallel()
103
104 switch runtime.GOOS {
105 case "plan9", "windows":
106 t.Skipf("no pthreads on %s", runtime.GOOS)
107 }
108
109 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
110 if want := "OK\n"; got != want {
111 if runtime.GOOS == "ios" && strings.Contains(got, "C signal did not crash as expected") {
112 testenv.SkipFlaky(t, 59913)
113 }
114 t.Fatalf("expected %q, but got:\n%s", want, got)
115 }
116 }
117
118 func TestCgoDLLImports(t *testing.T) {
119
120 if runtime.GOOS != "windows" {
121 t.Skip("skipping windows specific test")
122 }
123 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
124 want := "OK\n"
125 if got != want {
126 t.Fatalf("expected %q, but got %v", want, got)
127 }
128 }
129
130 func TestCgoExecSignalMask(t *testing.T) {
131 t.Parallel()
132
133 switch runtime.GOOS {
134 case "windows", "plan9":
135 t.Skipf("skipping signal mask test on %s", runtime.GOOS)
136 }
137 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system")
138 want := "OK\n"
139 if got != want {
140 t.Errorf("expected %q, got %v", want, got)
141 }
142 }
143
144 func TestEnsureDropM(t *testing.T) {
145 t.Parallel()
146
147 switch runtime.GOOS {
148 case "windows", "plan9":
149 t.Skipf("skipping dropm test on %s", runtime.GOOS)
150 }
151 got := runTestProg(t, "testprogcgo", "EnsureDropM")
152 want := "OK\n"
153 if got != want {
154 t.Errorf("expected %q, got %v", want, got)
155 }
156 }
157
158
159
160
161 func TestCgoCheckBytes(t *testing.T) {
162 t.Parallel()
163
164 testenv.MustHaveGoBuild(t)
165 exe, err := buildTestProg(t, "testprogcgo")
166 if err != nil {
167 t.Fatal(err)
168 }
169
170
171 const tries = 10
172 var tot1, tot2 time.Duration
173 for i := 0; i < tries; i++ {
174 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
175 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
176
177 start := time.Now()
178 cmd.Run()
179 d1 := time.Since(start)
180
181 cmd = testenv.CleanCmdEnv(exec.Command(exe, "CgoCheckBytes"))
182 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
183
184 start = time.Now()
185 cmd.Run()
186 d2 := time.Since(start)
187
188 if d1*20 > d2 {
189
190
191 return
192 }
193
194 tot1 += d1
195 tot2 += d2
196 }
197
198 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
199 }
200
201 func TestCgoPanicDeadlock(t *testing.T) {
202 t.Parallel()
203
204 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
205 want := "panic: cgo error\n\n"
206 if !strings.HasPrefix(got, want) {
207 t.Fatalf("output does not start with %q:\n%s", want, got)
208 }
209 }
210
211 func TestCgoCCodeSIGPROF(t *testing.T) {
212 t.Parallel()
213 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
214 want := "OK\n"
215 if got != want {
216 t.Errorf("expected %q got %v", want, got)
217 }
218 }
219
220 func TestCgoPprofCallback(t *testing.T) {
221 if testing.Short() {
222 t.Skip("skipping in short mode")
223 }
224 switch runtime.GOOS {
225 case "windows", "plan9":
226 t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
227 }
228 got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
229 want := "OK\n"
230 if got != want {
231 t.Errorf("expected %q got %v", want, got)
232 }
233 }
234
235 func TestCgoCrashTraceback(t *testing.T) {
236 t.Parallel()
237 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
238 case "darwin/amd64":
239 case "linux/amd64":
240 case "linux/arm64":
241 case "linux/ppc64le":
242 default:
243 t.Skipf("not yet supported on %s", platform)
244 }
245 got := runTestProg(t, "testprogcgo", "CrashTraceback")
246 for i := 1; i <= 3; i++ {
247 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
248 t.Errorf("missing cgo symbolizer:%d", i)
249 }
250 }
251 }
252
253 func TestCgoCrashTracebackGo(t *testing.T) {
254 t.Parallel()
255 switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
256 case "darwin/amd64":
257 case "linux/amd64":
258 case "linux/arm64":
259 case "linux/ppc64le":
260 default:
261 t.Skipf("not yet supported on %s", platform)
262 }
263 got := runTestProg(t, "testprogcgo", "CrashTracebackGo")
264 for i := 1; i <= 3; i++ {
265 want := fmt.Sprintf("main.h%d", i)
266 if !strings.Contains(got, want) {
267 t.Errorf("missing %s", want)
268 }
269 }
270 }
271
272 func TestCgoTracebackContext(t *testing.T) {
273 t.Parallel()
274 got := runTestProg(t, "testprogcgo", "TracebackContext")
275 want := "OK\n"
276 if got != want {
277 t.Errorf("expected %q got %v", want, got)
278 }
279 }
280
281 func TestCgoTracebackContextPreemption(t *testing.T) {
282 t.Parallel()
283 got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
284 want := "OK\n"
285 if got != want {
286 t.Errorf("expected %q got %v", want, got)
287 }
288 }
289
290 func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
291 t.Parallel()
292 if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "arm64") {
293 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
294 }
295 testenv.MustHaveGoRun(t)
296
297 exe, err := buildTestProg(t, "testprogcgo", buildArg)
298 if err != nil {
299 t.Fatal(err)
300 }
301
302 cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
303 got, err := cmd.CombinedOutput()
304 if err != nil {
305 if testenv.Builder() == "linux-amd64-alpine" {
306
307 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
308 }
309 t.Fatalf("%s\n\n%v", got, err)
310 }
311 fn := strings.TrimSpace(string(got))
312 defer os.Remove(fn)
313
314 for try := 0; try < 2; try++ {
315 cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces"))
316
317 if try == 0 {
318 cmd.Args = append(cmd.Args, exe, fn)
319 } else {
320 cmd.Args = append(cmd.Args, fn)
321 }
322
323 found := false
324 for i, e := range cmd.Env {
325 if strings.HasPrefix(e, "PPROF_TMPDIR=") {
326 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
327 found = true
328 break
329 }
330 }
331 if !found {
332 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
333 }
334
335 out, err := cmd.CombinedOutput()
336 t.Logf("%s:\n%s", cmd.Args, out)
337 if err != nil {
338 t.Error(err)
339 continue
340 }
341
342 trace := findTrace(string(out), top)
343 if len(trace) == 0 {
344 t.Errorf("%s traceback missing.", top)
345 continue
346 }
347 if trace[len(trace)-1] != bottom {
348 t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
349 }
350 }
351 }
352
353 func TestCgoPprof(t *testing.T) {
354 testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
355 }
356
357 func TestCgoPprofPIE(t *testing.T) {
358 testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
359 }
360
361 func TestCgoPprofThread(t *testing.T) {
362 testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
363 }
364
365 func TestCgoPprofThreadNoTraceback(t *testing.T) {
366 testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
367 }
368
369 func TestRaceProf(t *testing.T) {
370 if !platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) {
371 t.Skipf("skipping on %s/%s because race detector not supported", runtime.GOOS, runtime.GOARCH)
372 }
373 if runtime.GOOS == "windows" {
374 t.Skipf("skipping: test requires pthread support")
375
376 }
377
378 testenv.MustHaveGoRun(t)
379
380
381
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.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
392 if err != nil {
393 t.Fatal(err)
394 }
395 want := "OK\n"
396 if string(got) != want {
397 t.Errorf("expected %q got %s", want, got)
398 }
399 }
400
401 func TestRaceSignal(t *testing.T) {
402 if !platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) {
403 t.Skipf("skipping on %s/%s because race detector not supported", runtime.GOOS, runtime.GOARCH)
404 }
405 if runtime.GOOS == "windows" {
406 t.Skipf("skipping: test requires pthread support")
407
408 }
409 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
410 testenv.SkipFlaky(t, 60316)
411 }
412
413 t.Parallel()
414
415 testenv.MustHaveGoRun(t)
416
417
418
419 if testing.Short() {
420 t.Skip("skipping test in -short mode")
421 }
422
423 exe, err := buildTestProg(t, "testprogcgo", "-race")
424 if err != nil {
425 t.Fatal(err)
426 }
427
428 got, err := testenv.CleanCmdEnv(testenv.Command(t, exe, "CgoRaceSignal")).CombinedOutput()
429 if err != nil {
430 t.Logf("%s\n", got)
431 t.Fatal(err)
432 }
433 want := "OK\n"
434 if string(got) != want {
435 t.Errorf("expected %q got %s", want, got)
436 }
437 }
438
439 func TestCgoNumGoroutine(t *testing.T) {
440 switch runtime.GOOS {
441 case "windows", "plan9":
442 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
443 }
444 t.Parallel()
445 got := runTestProg(t, "testprogcgo", "NumGoroutine")
446 want := "OK\n"
447 if got != want {
448 t.Errorf("expected %q got %v", want, got)
449 }
450 }
451
452 func TestCatchPanic(t *testing.T) {
453 t.Parallel()
454 switch runtime.GOOS {
455 case "plan9", "windows":
456 t.Skipf("no signals on %s", runtime.GOOS)
457 case "darwin":
458 if runtime.GOARCH == "amd64" {
459 t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
460 }
461 }
462
463 testenv.MustHaveGoRun(t)
464
465 exe, err := buildTestProg(t, "testprogcgo")
466 if err != nil {
467 t.Fatal(err)
468 }
469
470 for _, early := range []bool{true, false} {
471 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
472
473 cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
474 if early {
475
476 cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
477 }
478 if out, err := cmd.CombinedOutput(); err != nil {
479 t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
480 }
481 }
482 }
483
484 func TestCgoLockOSThreadExit(t *testing.T) {
485 switch runtime.GOOS {
486 case "plan9", "windows":
487 t.Skipf("no pthreads on %s", runtime.GOOS)
488 }
489 t.Parallel()
490 testLockOSThreadExit(t, "testprogcgo")
491 }
492
493 func TestWindowsStackMemoryCgo(t *testing.T) {
494 if runtime.GOOS != "windows" {
495 t.Skip("skipping windows specific test")
496 }
497 testenv.SkipFlaky(t, 22575)
498 o := runTestProg(t, "testprogcgo", "StackMemory")
499 stackUsage, err := strconv.Atoi(o)
500 if err != nil {
501 t.Fatalf("Failed to read stack usage: %v", err)
502 }
503 if expected, got := 100<<10, stackUsage; got > expected {
504 t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
505 }
506 }
507
508 func TestSigStackSwapping(t *testing.T) {
509 switch runtime.GOOS {
510 case "plan9", "windows":
511 t.Skipf("no sigaltstack on %s", runtime.GOOS)
512 }
513 t.Parallel()
514 got := runTestProg(t, "testprogcgo", "SigStack")
515 want := "OK\n"
516 if got != want {
517 t.Errorf("expected %q got %v", want, got)
518 }
519 }
520
521 func TestCgoTracebackSigpanic(t *testing.T) {
522
523
524 if runtime.GOOS == "windows" {
525
526
527
528 t.Skip("no sigpanic in C on windows")
529 }
530 if runtime.GOOS == "ios" {
531 testenv.SkipFlaky(t, 59912)
532 }
533 t.Parallel()
534 got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
535 t.Log(got)
536
537 want := "main.TracebackSigpanic"
538 if !strings.Contains(got, want) {
539 if runtime.GOOS == "android" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
540 testenv.SkipFlaky(t, 58794)
541 }
542 t.Errorf("did not see %q in output", want)
543 }
544
545 nowant := "runtime.sigpanic"
546 if strings.Contains(got, nowant) {
547 t.Errorf("unexpectedly saw %q in output", nowant)
548 }
549
550 nowant = "runtime: "
551 if strings.Contains(got, nowant) {
552 t.Errorf("unexpectedly saw %q in output", nowant)
553 }
554 }
555
556 func TestCgoPanicCallback(t *testing.T) {
557 t.Parallel()
558 got := runTestProg(t, "testprogcgo", "PanicCallback")
559 t.Log(got)
560 want := "panic: runtime error: invalid memory address or nil pointer dereference"
561 if !strings.Contains(got, want) {
562 t.Errorf("did not see %q in output", want)
563 }
564 want = "panic_callback"
565 if !strings.Contains(got, want) {
566 t.Errorf("did not see %q in output", want)
567 }
568 want = "PanicCallback"
569 if !strings.Contains(got, want) {
570 t.Errorf("did not see %q in output", want)
571 }
572
573 nowant := "runtime: "
574 if strings.Contains(got, nowant) {
575 t.Errorf("did not see %q in output", want)
576 }
577 }
578
579
580
581
582
583 func TestBigStackCallbackCgo(t *testing.T) {
584 if runtime.GOOS != "windows" {
585 t.Skip("skipping windows specific test")
586 }
587 t.Parallel()
588 got := runTestProg(t, "testprogcgo", "BigStack")
589 want := "OK\n"
590 if got != want {
591 t.Errorf("expected %q got %v", want, got)
592 }
593 }
594
595 func nextTrace(lines []string) ([]string, []string) {
596 var trace []string
597 for n, line := range lines {
598 if strings.HasPrefix(line, "---") {
599 return trace, lines[n+1:]
600 }
601 fields := strings.Fields(strings.TrimSpace(line))
602 if len(fields) == 0 {
603 continue
604 }
605
606 trace = append(trace, fields[len(fields)-1])
607 }
608 return nil, nil
609 }
610
611 func findTrace(text, top string) []string {
612 lines := strings.Split(text, "\n")
613 _, lines = nextTrace(lines)
614 for len(lines) > 0 {
615 var t []string
616 t, lines = nextTrace(lines)
617 if len(t) == 0 {
618 continue
619 }
620 if t[0] == top {
621 return t
622 }
623 }
624 return nil
625 }
626
627 func TestSegv(t *testing.T) {
628 switch runtime.GOOS {
629 case "plan9", "windows":
630 t.Skipf("no signals on %s", runtime.GOOS)
631 }
632
633 for _, test := range []string{"Segv", "SegvInCgo", "TgkillSegv", "TgkillSegvInCgo"} {
634 test := test
635
636
637 if runtime.GOOS != "linux" && strings.HasPrefix(test, "Tgkill") {
638 continue
639 }
640
641 t.Run(test, func(t *testing.T) {
642 if test == "SegvInCgo" && runtime.GOOS == "ios" {
643 testenv.SkipFlaky(t, 59947)
644 }
645
646 t.Parallel()
647 prog := "testprog"
648 if strings.HasSuffix(test, "InCgo") {
649 prog = "testprogcgo"
650 }
651 got := runTestProg(t, prog, test)
652 t.Log(got)
653 want := "SIGSEGV"
654 if !strings.Contains(got, want) {
655 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
656 testenv.SkipFlaky(t, 39457)
657 }
658 t.Errorf("did not see %q in output", want)
659 }
660
661
662 switch runtime.GOOS {
663 case "darwin", "ios", "illumos", "solaris":
664
665 testenv.SkipFlaky(t, 49182)
666 case "linux":
667 if runtime.GOARCH == "386" {
668
669
670 testenv.SkipFlaky(t, 50504)
671 }
672 }
673 if test == "SegvInCgo" && strings.Contains(got, "unknown pc") {
674 testenv.SkipFlaky(t, 50979)
675 }
676
677 for _, nowant := range []string{"fatal error: ", "runtime: "} {
678 if strings.Contains(got, nowant) {
679 if runtime.GOOS == "darwin" && strings.Contains(got, "0xb01dfacedebac1e") {
680
681 t.Skip("skipping due to Darwin handling of malformed addresses")
682 }
683 t.Errorf("unexpectedly saw %q in output", nowant)
684 }
685 }
686 })
687 }
688 }
689
690 func TestAbortInCgo(t *testing.T) {
691 switch runtime.GOOS {
692 case "plan9", "windows":
693
694
695 t.Skipf("no signals on %s", runtime.GOOS)
696 }
697
698 t.Parallel()
699 got := runTestProg(t, "testprogcgo", "Abort")
700 t.Log(got)
701 want := "SIGABRT"
702 if !strings.Contains(got, want) {
703 t.Errorf("did not see %q in output", want)
704 }
705
706 nowant := "runtime: "
707 if strings.Contains(got, nowant) {
708 t.Errorf("did not see %q in output", want)
709 }
710 }
711
712
713
714 func TestEINTR(t *testing.T) {
715 switch runtime.GOOS {
716 case "plan9", "windows":
717 t.Skipf("no EINTR on %s", runtime.GOOS)
718 case "linux":
719 if runtime.GOARCH == "386" {
720
721
722
723
724
725
726
727 t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer")
728 }
729 }
730
731 t.Parallel()
732 output := runTestProg(t, "testprogcgo", "EINTR")
733 want := "OK\n"
734 if output != want {
735 t.Fatalf("want %s, got %s\n", want, output)
736 }
737 }
738
739
740 func TestNeedmDeadlock(t *testing.T) {
741 switch runtime.GOOS {
742 case "plan9", "windows":
743 t.Skipf("no signals on %s", runtime.GOOS)
744 }
745 output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
746 want := "OK\n"
747 if output != want {
748 t.Fatalf("want %s, got %s\n", want, output)
749 }
750 }
751
752 func TestCgoNoCallback(t *testing.T) {
753 got := runTestProg(t, "testprogcgo", "CgoNoCallback")
754 want := "function marked with #cgo nocallback called back into Go"
755 if !strings.Contains(got, want) {
756 t.Fatalf("did not see %q in output:\n%s", want, got)
757 }
758 }
759
760 func TestCgoNoEscape(t *testing.T) {
761 got := runTestProg(t, "testprogcgo", "CgoNoEscape")
762 want := "OK\n"
763 if got != want {
764 t.Fatalf("want %s, got %s\n", want, got)
765 }
766 }
767
768
769 func TestCgoEscapeWithMultiplePointers(t *testing.T) {
770 got := runTestProg(t, "testprogcgo", "CgoEscapeWithMultiplePointers")
771 want := "OK\n"
772 if got != want {
773 t.Fatalf("output is %s; want %s", got, want)
774 }
775 }
776
777 func TestCgoTracebackGoroutineProfile(t *testing.T) {
778 output := runTestProg(t, "testprogcgo", "GoroutineProfile")
779 want := "OK\n"
780 if output != want {
781 t.Fatalf("want %s, got %s\n", want, output)
782 }
783 }
784
785 func TestCgoSigfwd(t *testing.T) {
786 t.Parallel()
787 if !goos.IsUnix {
788 t.Skipf("no signals on %s", runtime.GOOS)
789 }
790
791 got := runTestProg(t, "testprogcgo", "CgoSigfwd", "GO_TEST_CGOSIGFWD=1")
792 if want := "OK\n"; got != want {
793 t.Fatalf("expected %q, but got:\n%s", want, got)
794 }
795 }
796
797 func TestDestructorCallback(t *testing.T) {
798 t.Parallel()
799 got := runTestProg(t, "testprogcgo", "DestructorCallback")
800 if want := "OK\n"; got != want {
801 t.Errorf("expected %q, but got:\n%s", want, got)
802 }
803 }
804
805 func TestDestructorCallbackRace(t *testing.T) {
806
807
808 if testing.Short() {
809 t.Skip("skipping test in -short mode")
810 }
811
812 if !platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) {
813 t.Skipf("skipping on %s/%s because race detector not supported", runtime.GOOS, runtime.GOARCH)
814 }
815
816 t.Parallel()
817
818 exe, err := buildTestProg(t, "testprogcgo", "-race")
819 if err != nil {
820 t.Fatal(err)
821 }
822
823 got, err := testenv.CleanCmdEnv(exec.Command(exe, "DestructorCallback")).CombinedOutput()
824 if err != nil {
825 t.Fatal(err)
826 }
827
828 if want := "OK\n"; string(got) != want {
829 t.Errorf("expected %q, but got:\n%s", want, got)
830 }
831 }
832
833 func TestEnsureBindM(t *testing.T) {
834 t.Parallel()
835 switch runtime.GOOS {
836 case "windows", "plan9":
837 t.Skipf("skipping bindm test on %s", runtime.GOOS)
838 }
839 got := runTestProg(t, "testprogcgo", "EnsureBindM")
840 want := "OK\n"
841 if got != want {
842 t.Errorf("expected %q, got %v", want, got)
843 }
844 }
845
846 func TestStackSwitchCallback(t *testing.T) {
847 t.Parallel()
848 switch runtime.GOOS {
849 case "windows", "plan9", "android", "ios", "openbsd":
850 t.Skipf("skipping test on %s", runtime.GOOS)
851 }
852 got := runTestProg(t, "testprogcgo", "StackSwitchCallback")
853 skip := "SKIP\n"
854 if got == skip {
855 t.Skip("skipping on musl/bionic libc")
856 }
857 want := "OK\n"
858 if got != want {
859 t.Errorf("expected %q, got %v", want, got)
860 }
861 }
862
863 func TestCgoToGoCallGoexit(t *testing.T) {
864 if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
865 t.Skipf("no pthreads on %s", runtime.GOOS)
866 }
867 output := runTestProg(t, "testprogcgo", "CgoToGoCallGoexit")
868 if !strings.Contains(output, "runtime.Goexit called in a thread that was not created by the Go runtime") {
869 t.Fatalf("output should contain %s, got %s", "runtime.Goexit called in a thread that was not created by the Go runtime", output)
870 }
871 }
872
View as plain text