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