blob: 4f7c10b923e3769c7849772dac8e7dcd3f38d773 [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) {
Dmitriy Vyukov06a488f2013-02-20 12:15:02 +040022 testCrashHandler(t, true)
Alex Brainmanafe0e972012-05-30 15:10:54 +100023}
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080024
25func TestCgoSignalDeadlock(t *testing.T) {
Dmitriy Vyukov1590abe2013-08-08 00:04:28 +040026 if testing.Short() && runtime.GOOS == "windows" {
27 t.Skip("Skipping in short mode") // takes up to 64 seconds
28 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050029 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080030 want := "OK\n"
31 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050032 t.Fatalf("expected %q, but got:\n%s", want, got)
Shenghou Ma6ecb39f2013-02-28 16:07:26 +080033 }
34}
35
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040036func TestCgoTraceback(t *testing.T) {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050037 got := runTestProg(t, "testprogcgo", "CgoTraceback")
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040038 want := "OK\n"
39 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050040 t.Fatalf("expected %q, but got:\n%s", want, got)
Dmitriy Vyukov326ae8d2013-08-08 00:31:52 +040041 }
42}
43
Russ Coxfde39262015-07-29 16:16:13 -040044func TestCgoCallbackGC(t *testing.T) {
45 if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
46 t.Skipf("no pthreads on %s", runtime.GOOS)
47 }
Dave Cheney98400422015-09-11 10:15:17 +100048 if testing.Short() {
49 switch {
50 case runtime.GOOS == "dragonfly":
51 t.Skip("see golang.org/issue/11990")
52 case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
53 t.Skip("too slow for arm builders")
Cherry Zhangbcd4b842016-05-04 22:07:50 -070054 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
55 t.Skip("too slow for mips64x builders")
Dave Cheney98400422015-09-11 10:15:17 +100056 }
Mikio Hara5e15e282015-08-03 12:43:25 +090057 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050058 got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
Russ Coxfde39262015-07-29 16:16:13 -040059 want := "OK\n"
60 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -050061 t.Fatalf("expected %q, but got:\n%s", want, got)
Russ Coxfde39262015-07-29 16:16:13 -040062 }
63}
64
Russ Coxc4efaac2014-10-28 21:53:09 -040065func TestCgoExternalThreadPanic(t *testing.T) {
Alex Brainmanf9c4c162014-10-30 10:24:37 +110066 if runtime.GOOS == "plan9" {
Russ Cox3ce6a4f2014-10-29 00:02:29 -040067 t.Skipf("no pthreads on %s", runtime.GOOS)
68 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -050069 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
Russ Coxc4efaac2014-10-28 21:53:09 -040070 want := "panic: BOOM"
71 if !strings.Contains(got, want) {
72 t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
73 }
74}
75
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050076func TestCgoExternalThreadSIGPROF(t *testing.T) {
77 // issue 9456.
Shenghou Ma2cbe27a2015-01-01 01:10:39 -050078 switch runtime.GOOS {
79 case "plan9", "windows":
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050080 t.Skipf("no pthreads on %s", runtime.GOOS)
Shenghou Ma2cbe27a2015-01-01 01:10:39 -050081 case "darwin":
David Crawshawd6d423b2015-04-11 19:00:53 -040082 if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" {
David Crawshaw95bf77b2015-02-26 18:05:47 -050083 // static constructor needs external linking, but we don't support
84 // external linking on OS X 10.6.
85 out, err := exec.Command("uname", "-r").Output()
86 if err != nil {
87 t.Fatalf("uname -r failed: %v", err)
88 }
89 // OS X 10.6 == Darwin 10.x
90 if strings.HasPrefix(string(out), "10.") {
91 t.Skipf("no external linking on OS X 10.6")
92 }
Shenghou Ma2cbe27a2015-01-01 01:10:39 -050093 }
Shenghou Ma5da9c8c2014-12-27 19:15:38 -050094 }
Michael Hudson-Doyle58db5fc2015-11-12 13:05:49 +130095 if runtime.GOARCH == "ppc64" {
Austin Clementsaf7ca8d2014-12-16 18:34:55 -050096 // TODO(austin) External linking not implemented on
97 // ppc64 (issue #8912)
98 t.Skipf("no external linking on ppc64")
99 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500100 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF")
Shenghou Ma5da9c8c2014-12-27 19:15:38 -0500101 want := "OK\n"
102 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500103 t.Fatalf("expected %q, but got:\n%s", want, got)
Shenghou Ma5da9c8c2014-12-27 19:15:38 -0500104 }
105}
106
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700107func TestCgoExternalThreadSignal(t *testing.T) {
108 // issue 10139
109 switch runtime.GOOS {
110 case "plan9", "windows":
111 t.Skipf("no pthreads on %s", runtime.GOOS)
112 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500113 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700114 want := "OK\n"
115 if got != want {
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500116 t.Fatalf("expected %q, but got:\n%s", want, got)
Ian Lance Taylor872b1682015-07-21 22:34:48 -0700117 }
118}
119
Alex Brainman9b691962015-03-16 15:46:22 +1100120func TestCgoDLLImports(t *testing.T) {
121 // test issue 9356
122 if runtime.GOOS != "windows" {
123 t.Skip("skipping windows specific test")
124 }
Russ Cox8d5ff2e2015-12-21 10:29:21 -0500125 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
Alex Brainman9b691962015-03-16 15:46:22 +1100126 want := "OK\n"
127 if got != want {
128 t.Fatalf("expected %q, but got %v", want, got)
129 }
130}
Ian Lance Taylor70c9a812015-12-19 10:17:10 -0800131
132func TestCgoExecSignalMask(t *testing.T) {
133 // Test issue 13164.
134 switch runtime.GOOS {
135 case "windows", "plan9":
136 t.Skipf("skipping signal mask test on %s", runtime.GOOS)
137 }
138 got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
139 want := "OK\n"
140 if got != want {
141 t.Errorf("expected %q, got %v", want, got)
142 }
143}
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800144
145func TestEnsureDropM(t *testing.T) {
146 // Test for issue 13881.
Ian Lance Taylor92709732016-01-18 09:01:48 -0800147 switch runtime.GOOS {
148 case "windows", "plan9":
149 t.Skipf("skipping dropm test on %s", runtime.GOOS)
150 }
Ian Lance Taylorc02aa462016-01-08 16:56:02 -0800151 got := runTestProg(t, "testprogcgo", "EnsureDropM")
152 want := "OK\n"
153 if got != want {
154 t.Errorf("expected %q, got %v", want, got)
155 }
156}
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800157
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.
161func TestCgoCheckBytes(t *testing.T) {
162 // Make sure we don't count the build time as part of the run time.
163 testenv.MustHaveGoBuild(t)
164 exe, err := buildTestProg(t, "testprogcgo")
165 if err != nil {
166 t.Fatal(err)
167 }
168
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800169 // Try it 10 times to avoid flakiness.
170 const tries = 10
171 var tot1, tot2 time.Duration
172 for i := 0; i < tries; i++ {
173 cmd := testEnv(exec.Command(exe, "CgoCheckBytes"))
174 cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800175
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800176 start := time.Now()
177 cmd.Run()
178 d1 := time.Since(start)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800179
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800180 cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
181 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800182
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800183 start = time.Now()
184 cmd.Run()
185 d2 := time.Since(start)
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800186
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800187 if d1*20 > d2 {
188 // The slow version (d2) was less than 20 times
189 // slower than the fast version (d1), so OK.
190 return
191 }
192
193 tot1 += d1
194 tot2 += d2
Ian Lance Taylorc8e7b342016-02-18 11:04:05 -0800195 }
Ian Lance Taylor8d94b9b2016-02-25 21:16:45 -0800196
197 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 -0800198}
Shenghou Mae9603022016-02-21 13:56:08 -0500199
200func TestCgoPanicDeadlock(t *testing.T) {
201 // test issue 14432
202 got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
203 want := "panic: cgo error\n\n"
204 if !strings.HasPrefix(got, want) {
205 t.Fatalf("output does not start with %q:\n%s", want, got)
206 }
207}
Ian Lance Taylor17161622016-03-04 11:29:55 -0800208
209func TestCgoCCodeSIGPROF(t *testing.T) {
210 got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
211 want := "OK\n"
212 if got != want {
213 t.Errorf("expected %q got %v", want, got)
214 }
215}
Ian Lance Taylorea306ae2015-12-11 17:16:48 -0800216
217func TestCgoCrashTraceback(t *testing.T) {
218 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
219 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
220 }
221 got := runTestProg(t, "testprogcgo", "CrashTraceback")
222 for i := 1; i <= 3; i++ {
223 if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
224 t.Errorf("missing cgo symbolizer:%d", i)
225 }
226 }
227}
Ian Lance Taylor5f9a8702016-04-27 14:18:29 -0700228
229func TestCgoTracebackContext(t *testing.T) {
Ian Lance Taylor5f9a8702016-04-27 14:18:29 -0700230 got := runTestProg(t, "testprogcgo", "TracebackContext")
231 want := "OK\n"
232 if got != want {
233 t.Errorf("expected %q got %v", want, got)
234 }
235}
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700236
237func TestCgoPprof(t *testing.T) {
238 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
239 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
240 }
241 testenv.MustHaveGoRun(t)
242
243 exe, err := buildTestProg(t, "testprogcgo")
244 if err != nil {
245 t.Fatal(err)
246 }
247
248 got, err := testEnv(exec.Command(exe, "CgoPprof")).CombinedOutput()
249 if err != nil {
250 t.Fatal(err)
251 }
252 fn := strings.TrimSpace(string(got))
Mohit Agarwal4d6788e2016-05-05 00:04:54 +0530253 defer os.Remove(fn)
Ian Lance Taylor84e80802016-04-29 15:20:27 -0700254
255 top, err := exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn).CombinedOutput()
256 if err != nil {
257 t.Fatal(err)
258 }
259
260 t.Logf("%s", top)
261
262 if !bytes.Contains(top, []byte("cpuHog")) {
263 t.Error("missing cpuHog in pprof output")
264 }
265}
Ian Lance Taylor42232942016-05-27 16:03:44 -0700266
267func TestCgoPprofPIE(t *testing.T) {
268 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
269 t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
270 }
271 testenv.MustHaveGoRun(t)
272
273 exe, err := buildTestProg(t, "testprogcgo", "-ldflags=-extldflags=-pie")
274 if err != nil {
275 t.Fatal(err)
276 }
277
278 got, err := testEnv(exec.Command(exe, "CgoPprof")).CombinedOutput()
279 if err != nil {
280 t.Fatal(err)
281 }
282 fn := strings.TrimSpace(string(got))
283 defer os.Remove(fn)
284
285 top, err := exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn).CombinedOutput()
286 if err != nil {
287 t.Fatal(err)
288 }
289
290 t.Logf("%s", top)
291
292 if !bytes.Contains(top, []byte("cpuHog")) {
293 t.Error("missing cpuHog in pprof output")
294 }
295}