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