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