]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/crash_cgo_test.go
misc/cgo/testsigfwd: move to runtime/testprog/testprogcgo
[gostls13.git] / src / runtime / crash_cgo_test.go
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.
4
5 //go:build cgo
6
7 package runtime_test
8
9 import (
10         "fmt"
11         "internal/goos"
12         "internal/testenv"
13         "os"
14         "os/exec"
15         "runtime"
16         "strconv"
17         "strings"
18         "testing"
19         "time"
20 )
21
22 func TestCgoCrashHandler(t *testing.T) {
23         t.Parallel()
24         testCrashHandler(t, true)
25 }
26
27 func TestCgoSignalDeadlock(t *testing.T) {
28         // Don't call t.Parallel, since too much work going on at the
29         // same time can cause the testprogcgo code to overrun its
30         // timeouts (issue #18598).
31
32         if testing.Short() && runtime.GOOS == "windows" {
33                 t.Skip("Skipping in short mode") // takes up to 64 seconds
34         }
35         got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
36         want := "OK\n"
37         if got != want {
38                 t.Fatalf("expected %q, but got:\n%s", want, got)
39         }
40 }
41
42 func TestCgoTraceback(t *testing.T) {
43         t.Parallel()
44         got := runTestProg(t, "testprogcgo", "CgoTraceback")
45         want := "OK\n"
46         if got != want {
47                 t.Fatalf("expected %q, but got:\n%s", want, got)
48         }
49 }
50
51 func TestCgoCallbackGC(t *testing.T) {
52         t.Parallel()
53         switch runtime.GOOS {
54         case "plan9", "windows":
55                 t.Skipf("no pthreads on %s", runtime.GOOS)
56         }
57         if testing.Short() {
58                 switch {
59                 case runtime.GOOS == "dragonfly":
60                         t.Skip("see golang.org/issue/11990")
61                 case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
62                         t.Skip("too slow for arm builders")
63                 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
64                         t.Skip("too slow for mips64x builders")
65                 }
66         }
67         if testenv.Builder() == "darwin-amd64-10_14" {
68                 // TODO(#23011): When the 10.14 builders are gone, remove this skip.
69                 t.Skip("skipping due to platform bug on macOS 10.14; see https://golang.org/issue/43926")
70         }
71         got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
72         want := "OK\n"
73         if got != want {
74                 t.Fatalf("expected %q, but got:\n%s", want, got)
75         }
76 }
77
78 func TestCgoExternalThreadPanic(t *testing.T) {
79         t.Parallel()
80         if runtime.GOOS == "plan9" {
81                 t.Skipf("no pthreads on %s", runtime.GOOS)
82         }
83         got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
84         want := "panic: BOOM"
85         if !strings.Contains(got, want) {
86                 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
87         }
88 }
89
90 func TestCgoExternalThreadSIGPROF(t *testing.T) {
91         t.Parallel()
92         // issue 9456.
93         switch runtime.GOOS {
94         case "plan9", "windows":
95                 t.Skipf("no pthreads on %s", runtime.GOOS)
96         }
97
98         got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF", "GO_START_SIGPROF_THREAD=1")
99         if want := "OK\n"; got != want {
100                 t.Fatalf("expected %q, but got:\n%s", want, got)
101         }
102 }
103
104 func TestCgoExternalThreadSignal(t *testing.T) {
105         t.Parallel()
106         // issue 10139
107         switch runtime.GOOS {
108         case "plan9", "windows":
109                 t.Skipf("no pthreads on %s", runtime.GOOS)
110         }
111
112         got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
113         if want := "OK\n"; got != want {
114                 t.Fatalf("expected %q, but got:\n%s", want, got)
115         }
116 }
117
118 func TestCgoDLLImports(t *testing.T) {
119         // test issue 9356
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         // Test issue 13164.
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         // Test for issue 13881.
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 // Test for issue 14387.
159 // Test that the program that doesn't need any cgo pointer checking
160 // takes about the same amount of time with it as without it.
161 func TestCgoCheckBytes(t *testing.T) {
162         t.Parallel()
163         // Make sure we don't count the build time as part of the run time.
164         testenv.MustHaveGoBuild(t)
165         exe, err := buildTestProg(t, "testprogcgo")
166         if err != nil {
167                 t.Fatal(err)
168         }
169
170         // Try it 10 times to avoid flakiness.
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                         // The slow version (d2) was less than 20 times
190                         // slower than the fast version (d1), so OK.
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         // test issue 14432
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         t.Parallel()
222         switch runtime.GOOS {
223         case "windows", "plan9":
224                 t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
225         }
226         got := runTestProg(t, "testprogcgo", "CgoPprofCallback")
227         want := "OK\n"
228         if got != want {
229                 t.Errorf("expected %q got %v", want, got)
230         }
231 }
232
233 func TestCgoCrashTraceback(t *testing.T) {
234         t.Parallel()
235         switch platform := runtime.GOOS + "/" + runtime.GOARCH; platform {
236         case "darwin/amd64":
237         case "linux/amd64":
238         case "linux/arm64":
239         case "linux/ppc64le":
240         default:
241                 t.Skipf("not yet supported on %s", platform)
242         }
243         got := runTestProg(t, "testprogcgo", "CrashTraceback")
244         for i := 1; i <= 3; i++ {
245                 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
246                         t.Errorf("missing cgo symbolizer:%d", i)
247                 }
248         }
249 }
250
251 func TestCgoCrashTracebackGo(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", "CrashTracebackGo")
262         for i := 1; i <= 3; i++ {
263                 want := fmt.Sprintf("main.h%d", i)
264                 if !strings.Contains(got, want) {
265                         t.Errorf("missing %s", want)
266                 }
267         }
268 }
269
270 func TestCgoTracebackContext(t *testing.T) {
271         t.Parallel()
272         got := runTestProg(t, "testprogcgo", "TracebackContext")
273         want := "OK\n"
274         if got != want {
275                 t.Errorf("expected %q got %v", want, got)
276         }
277 }
278
279 func TestCgoTracebackContextPreemption(t *testing.T) {
280         t.Parallel()
281         got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
282         want := "OK\n"
283         if got != want {
284                 t.Errorf("expected %q got %v", want, got)
285         }
286 }
287
288 func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
289         t.Parallel()
290         if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "arm64") {
291                 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
292         }
293         testenv.MustHaveGoRun(t)
294
295         exe, err := buildTestProg(t, "testprogcgo", buildArg)
296         if err != nil {
297                 t.Fatal(err)
298         }
299
300         cmd := testenv.CleanCmdEnv(exec.Command(exe, runArg))
301         got, err := cmd.CombinedOutput()
302         if err != nil {
303                 if testenv.Builder() == "linux-amd64-alpine" {
304                         // See Issue 18243 and Issue 19938.
305                         t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
306                 }
307                 t.Fatalf("%s\n\n%v", got, err)
308         }
309         fn := strings.TrimSpace(string(got))
310         defer os.Remove(fn)
311
312         for try := 0; try < 2; try++ {
313                 cmd := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-tagignore=ignore", "-traces"))
314                 // Check that pprof works both with and without explicit executable on command line.
315                 if try == 0 {
316                         cmd.Args = append(cmd.Args, exe, fn)
317                 } else {
318                         cmd.Args = append(cmd.Args, fn)
319                 }
320
321                 found := false
322                 for i, e := range cmd.Env {
323                         if strings.HasPrefix(e, "PPROF_TMPDIR=") {
324                                 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
325                                 found = true
326                                 break
327                         }
328                 }
329                 if !found {
330                         cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
331                 }
332
333                 out, err := cmd.CombinedOutput()
334                 t.Logf("%s:\n%s", cmd.Args, out)
335                 if err != nil {
336                         t.Error(err)
337                         continue
338                 }
339
340                 trace := findTrace(string(out), top)
341                 if len(trace) == 0 {
342                         t.Errorf("%s traceback missing.", top)
343                         continue
344                 }
345                 if trace[len(trace)-1] != bottom {
346                         t.Errorf("invalid traceback origin: got=%v; want=[%s ... %s]", trace, top, bottom)
347                 }
348         }
349 }
350
351 func TestCgoPprof(t *testing.T) {
352         testCgoPprof(t, "", "CgoPprof", "cpuHog", "runtime.main")
353 }
354
355 func TestCgoPprofPIE(t *testing.T) {
356         testCgoPprof(t, "-buildmode=pie", "CgoPprof", "cpuHog", "runtime.main")
357 }
358
359 func TestCgoPprofThread(t *testing.T) {
360         testCgoPprof(t, "", "CgoPprofThread", "cpuHogThread", "cpuHogThread2")
361 }
362
363 func TestCgoPprofThreadNoTraceback(t *testing.T) {
364         testCgoPprof(t, "", "CgoPprofThreadNoTraceback", "cpuHogThread", "runtime._ExternalCode")
365 }
366
367 func TestRaceProf(t *testing.T) {
368         if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
369                 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
370         }
371
372         testenv.MustHaveGoRun(t)
373
374         // This test requires building various packages with -race, so
375         // it's somewhat slow.
376         if testing.Short() {
377                 t.Skip("skipping test in -short mode")
378         }
379
380         exe, err := buildTestProg(t, "testprogcgo", "-race")
381         if err != nil {
382                 t.Fatal(err)
383         }
384
385         got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
386         if err != nil {
387                 t.Fatal(err)
388         }
389         want := "OK\n"
390         if string(got) != want {
391                 t.Errorf("expected %q got %s", want, got)
392         }
393 }
394
395 func TestRaceSignal(t *testing.T) {
396         t.Parallel()
397         if (runtime.GOOS != "linux" && runtime.GOOS != "freebsd") || runtime.GOARCH != "amd64" {
398                 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
399         }
400
401         testenv.MustHaveGoRun(t)
402
403         // This test requires building various packages with -race, so
404         // it's somewhat slow.
405         if testing.Short() {
406                 t.Skip("skipping test in -short mode")
407         }
408
409         exe, err := buildTestProg(t, "testprogcgo", "-race")
410         if err != nil {
411                 t.Fatal(err)
412         }
413
414         got, err := testenv.CleanCmdEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
415         if err != nil {
416                 t.Logf("%s\n", got)
417                 t.Fatal(err)
418         }
419         want := "OK\n"
420         if string(got) != want {
421                 t.Errorf("expected %q got %s", want, got)
422         }
423 }
424
425 func TestCgoNumGoroutine(t *testing.T) {
426         switch runtime.GOOS {
427         case "windows", "plan9":
428                 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
429         }
430         t.Parallel()
431         got := runTestProg(t, "testprogcgo", "NumGoroutine")
432         want := "OK\n"
433         if got != want {
434                 t.Errorf("expected %q got %v", want, got)
435         }
436 }
437
438 func TestCatchPanic(t *testing.T) {
439         t.Parallel()
440         switch runtime.GOOS {
441         case "plan9", "windows":
442                 t.Skipf("no signals on %s", runtime.GOOS)
443         case "darwin":
444                 if runtime.GOARCH == "amd64" {
445                         t.Skipf("crash() on darwin/amd64 doesn't raise SIGABRT")
446                 }
447         }
448
449         testenv.MustHaveGoRun(t)
450
451         exe, err := buildTestProg(t, "testprogcgo")
452         if err != nil {
453                 t.Fatal(err)
454         }
455
456         for _, early := range []bool{true, false} {
457                 cmd := testenv.CleanCmdEnv(exec.Command(exe, "CgoCatchPanic"))
458                 // Make sure a panic results in a crash.
459                 cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
460                 if early {
461                         // Tell testprogcgo to install an early signal handler for SIGABRT
462                         cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
463                 }
464                 if out, err := cmd.CombinedOutput(); err != nil {
465                         t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
466                 }
467         }
468 }
469
470 func TestCgoLockOSThreadExit(t *testing.T) {
471         switch runtime.GOOS {
472         case "plan9", "windows":
473                 t.Skipf("no pthreads on %s", runtime.GOOS)
474         }
475         t.Parallel()
476         testLockOSThreadExit(t, "testprogcgo")
477 }
478
479 func TestWindowsStackMemoryCgo(t *testing.T) {
480         if runtime.GOOS != "windows" {
481                 t.Skip("skipping windows specific test")
482         }
483         testenv.SkipFlaky(t, 22575)
484         o := runTestProg(t, "testprogcgo", "StackMemory")
485         stackUsage, err := strconv.Atoi(o)
486         if err != nil {
487                 t.Fatalf("Failed to read stack usage: %v", err)
488         }
489         if expected, got := 100<<10, stackUsage; got > expected {
490                 t.Fatalf("expected < %d bytes of memory per thread, got %d", expected, got)
491         }
492 }
493
494 func TestSigStackSwapping(t *testing.T) {
495         switch runtime.GOOS {
496         case "plan9", "windows":
497                 t.Skipf("no sigaltstack on %s", runtime.GOOS)
498         }
499         t.Parallel()
500         got := runTestProg(t, "testprogcgo", "SigStack")
501         want := "OK\n"
502         if got != want {
503                 t.Errorf("expected %q got %v", want, got)
504         }
505 }
506
507 func TestCgoTracebackSigpanic(t *testing.T) {
508         // Test unwinding over a sigpanic in C code without a C
509         // symbolizer. See issue #23576.
510         if runtime.GOOS == "windows" {
511                 // On Windows if we get an exception in C code, we let
512                 // the Windows exception handler unwind it, rather
513                 // than injecting a sigpanic.
514                 t.Skip("no sigpanic in C on windows")
515         }
516         t.Parallel()
517         got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
518         t.Log(got)
519         want := "runtime.sigpanic"
520         if !strings.Contains(got, want) {
521                 t.Errorf("did not see %q in output", want)
522         }
523         // No runtime errors like "runtime: unexpected return pc".
524         nowant := "runtime: "
525         if strings.Contains(got, nowant) {
526                 t.Errorf("unexpectedly saw %q in output", nowant)
527         }
528 }
529
530 func TestCgoPanicCallback(t *testing.T) {
531         t.Parallel()
532         got := runTestProg(t, "testprogcgo", "PanicCallback")
533         t.Log(got)
534         want := "panic: runtime error: invalid memory address or nil pointer dereference"
535         if !strings.Contains(got, want) {
536                 t.Errorf("did not see %q in output", want)
537         }
538         want = "panic_callback"
539         if !strings.Contains(got, want) {
540                 t.Errorf("did not see %q in output", want)
541         }
542         want = "PanicCallback"
543         if !strings.Contains(got, want) {
544                 t.Errorf("did not see %q in output", want)
545         }
546         // No runtime errors like "runtime: unexpected return pc".
547         nowant := "runtime: "
548         if strings.Contains(got, nowant) {
549                 t.Errorf("did not see %q in output", want)
550         }
551 }
552
553 // Test that C code called via cgo can use large Windows thread stacks
554 // and call back in to Go without crashing. See issue #20975.
555 //
556 // See also TestBigStackCallbackSyscall.
557 func TestBigStackCallbackCgo(t *testing.T) {
558         if runtime.GOOS != "windows" {
559                 t.Skip("skipping windows specific test")
560         }
561         t.Parallel()
562         got := runTestProg(t, "testprogcgo", "BigStack")
563         want := "OK\n"
564         if got != want {
565                 t.Errorf("expected %q got %v", want, got)
566         }
567 }
568
569 func nextTrace(lines []string) ([]string, []string) {
570         var trace []string
571         for n, line := range lines {
572                 if strings.HasPrefix(line, "---") {
573                         return trace, lines[n+1:]
574                 }
575                 fields := strings.Fields(strings.TrimSpace(line))
576                 if len(fields) == 0 {
577                         continue
578                 }
579                 // Last field contains the function name.
580                 trace = append(trace, fields[len(fields)-1])
581         }
582         return nil, nil
583 }
584
585 func findTrace(text, top string) []string {
586         lines := strings.Split(text, "\n")
587         _, lines = nextTrace(lines) // Skip the header.
588         for len(lines) > 0 {
589                 var t []string
590                 t, lines = nextTrace(lines)
591                 if len(t) == 0 {
592                         continue
593                 }
594                 if t[0] == top {
595                         return t
596                 }
597         }
598         return nil
599 }
600
601 func TestSegv(t *testing.T) {
602         switch runtime.GOOS {
603         case "plan9", "windows":
604                 t.Skipf("no signals on %s", runtime.GOOS)
605         }
606
607         for _, test := range []string{"Segv", "SegvInCgo", "TgkillSegv", "TgkillSegvInCgo"} {
608                 test := test
609
610                 // The tgkill variants only run on Linux.
611                 if runtime.GOOS != "linux" && strings.HasPrefix(test, "Tgkill") {
612                         continue
613                 }
614
615                 t.Run(test, func(t *testing.T) {
616                         t.Parallel()
617                         got := runTestProg(t, "testprogcgo", test)
618                         t.Log(got)
619                         want := "SIGSEGV"
620                         if !strings.Contains(got, want) {
621                                 if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" && strings.Contains(got, "fatal: morestack on g0") {
622                                         testenv.SkipFlaky(t, 39457)
623                                 }
624                                 t.Errorf("did not see %q in output", want)
625                         }
626
627                         // No runtime errors like "runtime: unknown pc".
628                         switch runtime.GOOS {
629                         case "darwin", "illumos", "solaris":
630                                 // Runtime sometimes throws when generating the traceback.
631                                 testenv.SkipFlaky(t, 49182)
632                         case "linux":
633                                 if runtime.GOARCH == "386" {
634                                         // Runtime throws when generating a traceback from
635                                         // a VDSO call via asmcgocall.
636                                         testenv.SkipFlaky(t, 50504)
637                                 }
638                         }
639                         if test == "SegvInCgo" && strings.Contains(got, "unknown pc") {
640                                 testenv.SkipFlaky(t, 50979)
641                         }
642
643                         for _, nowant := range []string{"fatal error: ", "runtime: "} {
644                                 if strings.Contains(got, nowant) {
645                                         if runtime.GOOS == "darwin" && strings.Contains(got, "0xb01dfacedebac1e") {
646                                                 // See the comment in signal_darwin_amd64.go.
647                                                 t.Skip("skipping due to Darwin handling of malformed addresses")
648                                         }
649                                         t.Errorf("unexpectedly saw %q in output", nowant)
650                                 }
651                         }
652                 })
653         }
654 }
655
656 func TestAbortInCgo(t *testing.T) {
657         switch runtime.GOOS {
658         case "plan9", "windows":
659                 // N.B. On Windows, C abort() causes the program to exit
660                 // without going through the runtime at all.
661                 t.Skipf("no signals on %s", runtime.GOOS)
662         }
663
664         t.Parallel()
665         got := runTestProg(t, "testprogcgo", "Abort")
666         t.Log(got)
667         want := "SIGABRT"
668         if !strings.Contains(got, want) {
669                 t.Errorf("did not see %q in output", want)
670         }
671         // No runtime errors like "runtime: unknown pc".
672         nowant := "runtime: "
673         if strings.Contains(got, nowant) {
674                 t.Errorf("did not see %q in output", want)
675         }
676 }
677
678 // TestEINTR tests that we handle EINTR correctly.
679 // See issue #20400 and friends.
680 func TestEINTR(t *testing.T) {
681         switch runtime.GOOS {
682         case "plan9", "windows":
683                 t.Skipf("no EINTR on %s", runtime.GOOS)
684         case "linux":
685                 if runtime.GOARCH == "386" {
686                         // On linux-386 the Go signal handler sets
687                         // a restorer function that is not preserved
688                         // by the C sigaction call in the test,
689                         // causing the signal handler to crash when
690                         // returning the normal code. The test is not
691                         // architecture-specific, so just skip on 386
692                         // rather than doing a complicated workaround.
693                         t.Skip("skipping on linux-386; C sigaction does not preserve Go restorer")
694                 }
695         }
696
697         t.Parallel()
698         output := runTestProg(t, "testprogcgo", "EINTR")
699         want := "OK\n"
700         if output != want {
701                 t.Fatalf("want %s, got %s\n", want, output)
702         }
703 }
704
705 // Issue #42207.
706 func TestNeedmDeadlock(t *testing.T) {
707         switch runtime.GOOS {
708         case "plan9", "windows":
709                 t.Skipf("no signals on %s", runtime.GOOS)
710         }
711         output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
712         want := "OK\n"
713         if output != want {
714                 t.Fatalf("want %s, got %s\n", want, output)
715         }
716 }
717
718 func TestCgoTracebackGoroutineProfile(t *testing.T) {
719         output := runTestProg(t, "testprogcgo", "GoroutineProfile")
720         want := "OK\n"
721         if output != want {
722                 t.Fatalf("want %s, got %s\n", want, output)
723         }
724 }
725
726 func TestCgoTraceParser(t *testing.T) {
727         // Test issue 29707.
728         switch runtime.GOOS {
729         case "plan9", "windows":
730                 t.Skipf("no pthreads on %s", runtime.GOOS)
731         }
732         output := runTestProg(t, "testprogcgo", "CgoTraceParser")
733         want := "OK\n"
734         ErrTimeOrder := "ErrTimeOrder\n"
735         if output == ErrTimeOrder {
736                 t.Skipf("skipping due to golang.org/issue/16755: %v", output)
737         } else if output != want {
738                 t.Fatalf("want %s, got %s\n", want, output)
739         }
740 }
741
742 func TestCgoTraceParserWithOneProc(t *testing.T) {
743         // Test issue 29707.
744         switch runtime.GOOS {
745         case "plan9", "windows":
746                 t.Skipf("no pthreads on %s", runtime.GOOS)
747         }
748         output := runTestProg(t, "testprogcgo", "CgoTraceParser", "GOMAXPROCS=1")
749         want := "OK\n"
750         ErrTimeOrder := "ErrTimeOrder\n"
751         if output == ErrTimeOrder {
752                 t.Skipf("skipping due to golang.org/issue/16755: %v", output)
753         } else if output != want {
754                 t.Fatalf("GOMAXPROCS=1, want %s, got %s\n", want, output)
755         }
756 }
757
758 func TestCgoSigfwd(t *testing.T) {
759         t.Parallel()
760         if goos.IsLinux == 0 {
761                 t.Skipf("only supported on Linux")
762         }
763
764         got := runTestProg(t, "testprogcgo", "CgoSigfwd", "GO_TEST_CGOSIGFWD=1")
765         if want := "OK\n"; got != want {
766                 t.Fatalf("expected %q, but got:\n%s", want, got)
767         }
768 }