blob: a5cbbad69bbfd66e0621e54e2a3e6eca86154eb4 [file] [log] [blame]
Alex Brainmanafe0e972012-05-30 15:10:54 +10001// 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// +build cgo
6
7package runtime_test
8
9import (
Ian Lance Taylor84e80802016-04-29 15:20:27 -070010 "bytes"
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -080011 "fmt"
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -080012 "internal/testenv"
Mohit Agarwal4d6788e2016-05-05 00:04:54 +053013 "os"
Shenghou Ma865e5e92015-01-03 00:12:34 -050014 "os/exec"
Dmitriy Vyukov1590abe2013-08-08 00:04:28 +040015 "runtime"
Russ Coxc4efaac2014-10-28 21:53:09 -040016 "strings"
Alex Brainmanafe0e972012-05-30 15:10:54 +100017 "testing"
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -080018 "time"
Alex Brainmanafe0e972012-05-30 15:10:54 +100019)
20
21func TestCgoCrashHandler(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000022 t.Parallel()
Dmitriy Vyukov06a488f2013-02-20 12:15:02 +040023 testCrashHandler(t, true)
Alex Brainmanafe0e972012-05-30 15:10:54 +100024}
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080025
26func TestCgoSignalDeadlock(t *testing.T) {
Ian Lance Taylor7e172502017-07-12 20:51:15 -070027 // Don't call t.Parallel, since too much work going on at the
28 // same time can cause the testprogcgo code to overrun its
29 // timeouts (issue #18598).
30
Dmitriy Vyukov1590abe2013-08-08 00:04:28 +040031 if testing.Short() && runtime.GOOS == "windows" {
32 t.Skip("Skipping in short mode") // takes up to 64 seconds
33 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050034 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080035 want := "OK\n"
36 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050037 t.Fatalf("expected %q, but got:\n%s", want, got)
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080038 }
39}
40
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040041func TestCgoTraceback(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000042 t.Parallel()
Russ Cox8d5ff2e2015-12-21 10:29:21 -050043 got := runTestProg(t, "testprogcgo", "CgoTraceback")
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040044 want := "OK\n"
45 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050046 t.Fatalf("expected %q, but got:\n%s", want, got)
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040047 }
48}
49
Russ Coxfde39262015-07-29 16:16:13 -040050func TestCgoCallbackGC(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000051 t.Parallel()
Josh Bleecher Snyder604efe12016-08-17 16:22:24 -070052 switch runtime.GOOS {
53 case "plan9", "windows":
Russ Coxfde39262015-07-29 16:16:13 -040054 t.Skipf("no pthreads on %s", runtime.GOOS)
55 }
Dave Cheney98400422015-09-11 10:15:17 +100056 if testing.Short() {
57 switch {
58 case runtime.GOOS == "dragonfly":
59 t.Skip("see golang.org/issue/11990")
60 case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
61 t.Skip("too slow for arm builders")
Cherry Zhangbcd4b842016-05-04 22:07:50 -070062 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
63 t.Skip("too slow for mips64x builders")
Dave Cheney98400422015-09-11 10:15:17 +100064 }
Mikio Hara5e15e282015-08-03 12:43:25 +090065 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050066 got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
Russ Coxfde39262015-07-29 16:16:13 -040067 want := "OK\n"
68 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050069 t.Fatalf("expected %q, but got:\n%s", want, got)
Russ Coxfde39262015-07-29 16:16:13 -040070 }
71}
72
Russ Coxc4efaac2014-10-28 21:53:09 -040073func TestCgoExternalThreadPanic(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000074 t.Parallel()
Alex Brainmanf9c4c162014-10-30 10:24:37 +110075 if runtime.GOOS == "plan9" {
Russ Cox3ce6a4f2014-10-29 00:02:29 -040076 t.Skipf("no pthreads on %s", runtime.GOOS)
77 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050078 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
Russ Coxc4efaac2014-10-28 21:53:09 -040079 want := "panic: BOOM"
80 if !strings.Contains(got, want) {
81 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
82 }
83}
84
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050085func TestCgoExternalThreadSIGPROF(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +000086 t.Parallel()
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050087 // issue 9456.
Shenghou Ma2cbe27a2015-01-01 01:10:39 -050088 switch runtime.GOOS {
89 case "plan9", "windows":
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050090 t.Skipf("no pthreads on %s", runtime.GOOS)
Shenghou Ma2cbe27a2015-01-01 01:10:39 -050091 case "darwin":
David Crawshawd6d423b2015-04-11 19:00:53 -040092 if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" {
David Crawshaw95bf77b2015-02-26 18:05:47 -050093 // static constructor needs external linking, but we don't support
94 // external linking on OS X 10.6.
95 out, err := exec.Command("uname", "-r").Output()
96 if err != nil {
97 t.Fatalf("uname -r failed: %v", err)
98 }
99 // OS X 10.6 == Darwin 10.x
100 if strings.HasPrefix(string(out), "10.") {
101 t.Skipf("no external linking on OS X 10.6")
102 }
Shenghou Ma2cbe27a2015-01-01 01:10:39 -0500103 }
Shenghou Ma5da9c8c2014-12-27 19:15:38 -0500104 }
Michael Hudson-Doyle58db5fc2015-11-12 13:05:49 +1300105 if runtime.GOARCH == "ppc64" {
Austin Clementsaf7ca8d2014-12-16 18:34:55 -0500106 // TODO(austin) External linking not implemented on
107 // ppc64 (issue #8912)
108 t.Skipf("no external linking on ppc64")
109 }
Ian Lance Taylore5421e22016-10-05 07:31:11 -0700110
111 exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
112 if err != nil {
113 t.Fatal(err)
114 }
115
116 got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
117 if err != nil {
118 t.Fatalf("exit status: %v\n%s", err, got)
119 }
120
121 if want := "OK\n"; string(got) != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500122 t.Fatalf("expected %q, but got:\n%s", want, got)
Shenghou Ma5da9c8c2014-12-27 19:15:38 -0500123 }
124}
125
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700126func TestCgoExternalThreadSignal(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000127 t.Parallel()
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700128 // issue 10139
129 switch runtime.GOOS {
130 case "plan9", "windows":
131 t.Skipf("no pthreads on %s", runtime.GOOS)
132 }
Ian Lance Taylore5421e22016-10-05 07:31:11 -0700133
134 exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
135 if err != nil {
136 t.Fatal(err)
137 }
138
139 got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
140 if err != nil {
141 t.Fatalf("exit status: %v\n%s", err, got)
142 }
143
144 want := []byte("OK\n")
145 if !bytes.Equal(got, want) {
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500146 t.Fatalf("expected %q, but got:\n%s", want, got)
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700147 }
148}
149
Alex Brainman9b691962015-03-16 15:46:22 +1100150func TestCgoDLLImports(t *testing.T) {
151 // test issue 9356
152 if runtime.GOOS != "windows" {
153 t.Skip("skipping windows specific test")
154 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500155 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
Alex Brainman9b691962015-03-16 15:46:22 +1100156 want := "OK\n"
157 if got != want {
158 t.Fatalf("expected %q, but got %v", want, got)
159 }
160}
Ian Lance Taylor70c9a812015-12-19 10:17:10 -0800161
162func TestCgoExecSignalMask(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000163 t.Parallel()
Ian Lance Taylor70c9a812015-12-19 10:17:10 -0800164 // Test issue 13164.
165 switch runtime.GOOS {
166 case "windows", "plan9":
167 t.Skipf("skipping signal mask test on %s", runtime.GOOS)
168 }
169 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
170 want := "OK\n"
171 if got != want {
172 t.Errorf("expected %q, got %v", want, got)
173 }
174}
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800175
176func TestEnsureDropM(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000177 t.Parallel()
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800178 // Test for issue 13881.
Ian Lance Taylor92709732016-01-18 09:01:48 -0800179 switch runtime.GOOS {
180 case "windows", "plan9":
181 t.Skipf("skipping dropm test on %s", runtime.GOOS)
182 }
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800183 got := runTestProg(t, "testprogcgo", "EnsureDropM")
184 want := "OK\n"
185 if got != want {
186 t.Errorf("expected %q, got %v", want, got)
187 }
188}
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800189
190// Test for issue 14387.
191// Test that the program that doesn't need any cgo pointer checking
192// takes about the same amount of time with it as without it.
193func TestCgoCheckBytes(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000194 t.Parallel()
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800195 // Make sure we don't count the build time as part of the run time.
196 testenv.MustHaveGoBuild(t)
197 exe, err := buildTestProg(t, "testprogcgo")
198 if err != nil {
199 t.Fatal(err)
200 }
201
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800202 // Try it 10 times to avoid flakiness.
203 const tries = 10
204 var tot1, tot2 time.Duration
205 for i := 0; i < tries; i++ {
206 cmd := testEnv(exec.Command(exe, "CgoCheckBytes"))
207 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800208
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800209 start := time.Now()
210 cmd.Run()
211 d1 := time.Since(start)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800212
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800213 cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
214 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800215
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800216 start = time.Now()
217 cmd.Run()
218 d2 := time.Since(start)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800219
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800220 if d1*20 > d2 {
221 // The slow version (d2) was less than 20 times
222 // slower than the fast version (d1), so OK.
223 return
224 }
225
226 tot1 += d1
227 tot2 += d2
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800228 }
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800229
230 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800231}
Shenghou Mae9603022016-02-21 13:56:08 -0500232
233func TestCgoPanicDeadlock(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000234 t.Parallel()
Shenghou Mae9603022016-02-21 13:56:08 -0500235 // test issue 14432
236 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
237 want := "panic: cgo error\n\n"
238 if !strings.HasPrefix(got, want) {
239 t.Fatalf("output does not start with %q:\n%s", want, got)
240 }
241}
Ian Lance Taylor17161622016-03-04 11:29:55 -0800242
243func TestCgoCCodeSIGPROF(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000244 t.Parallel()
Ian Lance Taylor17161622016-03-04 11:29:55 -0800245 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
246 want := "OK\n"
247 if got != want {
248 t.Errorf("expected %q got %v", want, got)
249 }
250}
Ian Lance Taylorea306ae2015-12-11 17:16:48 -0800251
252func TestCgoCrashTraceback(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000253 t.Parallel()
Ian Lance Taylorea306ae2015-12-11 17:16:48 -0800254 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
255 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
256 }
257 got := runTestProg(t, "testprogcgo", "CrashTraceback")
258 for i := 1; i <= 3; i++ {
259 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
260 t.Errorf("missing cgo symbolizer:%d", i)
261 }
262 }
263}
Ian Lance Taylor5f9a8702016-04-27 14:18:29 -0700264
265func TestCgoTracebackContext(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000266 t.Parallel()
Ian Lance Taylor5f9a8702016-04-27 14:18:29 -0700267 got := runTestProg(t, "testprogcgo", "TracebackContext")
268 want := "OK\n"
269 if got != want {
270 t.Errorf("expected %q got %v", want, got)
271 }
272}
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700273
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700274func testCgoPprof(t *testing.T, buildArg, runArg string) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000275 t.Parallel()
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700276 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
277 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
278 }
279 testenv.MustHaveGoRun(t)
280
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700281 exe, err := buildTestProg(t, "testprogcgo", buildArg)
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700282 if err != nil {
283 t.Fatal(err)
284 }
285
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700286 got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput()
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700287 if err != nil {
Brad Fitzpatrick34ee8ec2017-04-25 04:59:14 +0000288 if testenv.Builder() == "linux-amd64-alpine" {
Brad Fitzpatrick16271b82017-04-25 02:46:06 +0000289 // See Issue 18243 and Issue 19938.
290 t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
291 }
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700292 t.Fatal(err)
293 }
294 fn := strings.TrimSpace(string(got))
Mohit Agarwal4d6788e2016-05-05 00:04:54 +0530295 defer os.Remove(fn)
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700296
Russ Cox8c24e522017-02-17 15:27:12 -0500297 for try := 0; try < 2; try++ {
298 cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1"))
299 // Check that pprof works both with and without explicit executable on command line.
300 if try == 0 {
301 cmd.Args = append(cmd.Args, exe, fn)
302 } else {
303 cmd.Args = append(cmd.Args, fn)
Ian Lance Taylor659b9a12016-06-20 09:16:17 -0700304 }
Ian Lance Taylor659b9a12016-06-20 09:16:17 -0700305
Russ Cox8c24e522017-02-17 15:27:12 -0500306 found := false
307 for i, e := range cmd.Env {
308 if strings.HasPrefix(e, "PPROF_TMPDIR=") {
309 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
310 found = true
311 break
312 }
313 }
314 if !found {
315 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
316 }
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700317
Russ Cox8c24e522017-02-17 15:27:12 -0500318 top, err := cmd.CombinedOutput()
319 t.Logf("%s:\n%s", cmd.Args, top)
320 if err != nil {
321 t.Error(err)
322 } else if !bytes.Contains(top, []byte("cpuHog")) {
323 t.Error("missing cpuHog in pprof output")
324 }
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700325 }
326}
Ian Lance Taylor42232942016-05-27 16:03:44 -0700327
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700328func TestCgoPprof(t *testing.T) {
329 testCgoPprof(t, "", "CgoPprof")
330}
331
Ian Lance Taylor42232942016-05-27 16:03:44 -0700332func TestCgoPprofPIE(t *testing.T) {
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700333 testCgoPprof(t, "-ldflags=-extldflags=-pie", "CgoPprof")
334}
Ian Lance Taylor42232942016-05-27 16:03:44 -0700335
Ian Lance Taylor84d8aff2016-06-07 21:46:25 -0700336func TestCgoPprofThread(t *testing.T) {
337 testCgoPprof(t, "", "CgoPprofThread")
Ian Lance Taylor42232942016-05-27 16:03:44 -0700338}
Ian Lance Taylor9d8522f2016-09-21 09:44:40 -0700339
Ian Lance Taylord03e8b22016-10-04 07:11:55 -0700340func TestCgoPprofThreadNoTraceback(t *testing.T) {
341 testCgoPprof(t, "", "CgoPprofThreadNoTraceback")
342}
343
Ian Lance Taylor9d8522f2016-09-21 09:44:40 -0700344func TestRaceProf(t *testing.T) {
345 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
346 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
347 }
348
349 testenv.MustHaveGoRun(t)
350
351 // This test requires building various packages with -race, so
352 // it's somewhat slow.
353 if testing.Short() {
354 t.Skip("skipping test in -short mode")
355 }
356
357 exe, err := buildTestProg(t, "testprogcgo", "-race")
358 if err != nil {
359 t.Fatal(err)
360 }
361
362 got, err := testEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
363 if err != nil {
364 t.Fatal(err)
365 }
366 want := "OK\n"
367 if string(got) != want {
368 t.Errorf("expected %q got %s", want, got)
369 }
370}
Ian Lance Taylor6c13a1d2016-10-03 16:58:34 -0700371
372func TestRaceSignal(t *testing.T) {
Brad Fitzpatrick23416312016-11-04 05:28:01 +0000373 t.Parallel()
Ian Lance Taylor6c13a1d2016-10-03 16:58:34 -0700374 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
375 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
376 }
377
378 testenv.MustHaveGoRun(t)
379
380 // This test requires building various packages with -race, so
381 // it's somewhat slow.
382 if testing.Short() {
383 t.Skip("skipping test in -short mode")
384 }
385
386 exe, err := buildTestProg(t, "testprogcgo", "-race")
387 if err != nil {
388 t.Fatal(err)
389 }
390
391 got, err := testEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
392 if err != nil {
393 t.Logf("%s\n", got)
394 t.Fatal(err)
395 }
396 want := "OK\n"
397 if string(got) != want {
398 t.Errorf("expected %q got %s", want, got)
399 }
400}
Austin Clements4e7067c2017-06-06 18:37:59 -0400401
402func TestCgoNumGoroutine(t *testing.T) {
Ian Lance Taylor03a4a5c2017-06-14 10:17:29 -0700403 switch runtime.GOOS {
404 case "windows", "plan9":
405 t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
406 }
Austin Clements4e7067c2017-06-06 18:37:59 -0400407 t.Parallel()
408 got := runTestProg(t, "testprogcgo", "NumGoroutine")
409 want := "OK\n"
410 if got != want {
411 t.Errorf("expected %q got %v", want, got)
412 }
413}