github.com/letsencrypt/go@v0.0.0-20160714163537-4054769a31f6/src/runtime/crash_cgo_test.go (about) 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 // +build cgo 6 7 package runtime_test 8 9 import ( 10 "bytes" 11 "fmt" 12 "internal/testenv" 13 "os" 14 "os/exec" 15 "runtime" 16 "strings" 17 "testing" 18 "time" 19 ) 20 21 func TestCgoCrashHandler(t *testing.T) { 22 testCrashHandler(t, true) 23 } 24 25 func TestCgoSignalDeadlock(t *testing.T) { 26 if testing.Short() && runtime.GOOS == "windows" { 27 t.Skip("Skipping in short mode") // takes up to 64 seconds 28 } 29 got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock") 30 want := "OK\n" 31 if got != want { 32 t.Fatalf("expected %q, but got:\n%s", want, got) 33 } 34 } 35 36 func TestCgoTraceback(t *testing.T) { 37 got := runTestProg(t, "testprogcgo", "CgoTraceback") 38 want := "OK\n" 39 if got != want { 40 t.Fatalf("expected %q, but got:\n%s", want, got) 41 } 42 } 43 44 func TestCgoCallbackGC(t *testing.T) { 45 if runtime.GOOS == "plan9" || runtime.GOOS == "windows" { 46 t.Skipf("no pthreads on %s", runtime.GOOS) 47 } 48 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") 54 case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"): 55 t.Skip("too slow for mips64x builders") 56 } 57 } 58 got := runTestProg(t, "testprogcgo", "CgoCallbackGC") 59 want := "OK\n" 60 if got != want { 61 t.Fatalf("expected %q, but got:\n%s", want, got) 62 } 63 } 64 65 func TestCgoExternalThreadPanic(t *testing.T) { 66 if runtime.GOOS == "plan9" { 67 t.Skipf("no pthreads on %s", runtime.GOOS) 68 } 69 got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic") 70 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 76 func TestCgoExternalThreadSIGPROF(t *testing.T) { 77 // issue 9456. 78 switch runtime.GOOS { 79 case "plan9", "windows": 80 t.Skipf("no pthreads on %s", runtime.GOOS) 81 case "darwin": 82 if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" { 83 // 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 } 93 } 94 } 95 if runtime.GOARCH == "ppc64" { 96 // TODO(austin) External linking not implemented on 97 // ppc64 (issue #8912) 98 t.Skipf("no external linking on ppc64") 99 } 100 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF") 101 want := "OK\n" 102 if got != want { 103 t.Fatalf("expected %q, but got:\n%s", want, got) 104 } 105 } 106 107 func 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 } 113 got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal") 114 want := "OK\n" 115 if got != want { 116 t.Fatalf("expected %q, but got:\n%s", want, got) 117 } 118 } 119 120 func TestCgoDLLImports(t *testing.T) { 121 // test issue 9356 122 if runtime.GOOS != "windows" { 123 t.Skip("skipping windows specific test") 124 } 125 got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain") 126 want := "OK\n" 127 if got != want { 128 t.Fatalf("expected %q, but got %v", want, got) 129 } 130 } 131 132 func 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 } 144 145 func TestEnsureDropM(t *testing.T) { 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 // 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 169 // 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)) 175 176 start := time.Now() 177 cmd.Run() 178 d1 := time.Since(start) 179 180 cmd = testEnv(exec.Command(exe, "CgoCheckBytes")) 181 cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i)) 182 183 start = time.Now() 184 cmd.Run() 185 d2 := time.Since(start) 186 187 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 195 } 196 197 t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20) 198 } 199 200 func 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 } 208 209 func 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 } 216 217 func 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 } 228 229 func TestCgoTracebackContext(t *testing.T) { 230 got := runTestProg(t, "testprogcgo", "TracebackContext") 231 want := "OK\n" 232 if got != want { 233 t.Errorf("expected %q got %v", want, got) 234 } 235 } 236 237 func testCgoPprof(t *testing.T, buildArg, runArg string) { 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", buildArg) 244 if err != nil { 245 t.Fatal(err) 246 } 247 248 got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput() 249 if err != nil { 250 t.Fatal(err) 251 } 252 fn := strings.TrimSpace(string(got)) 253 defer os.Remove(fn) 254 255 cmd := testEnv(exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn)) 256 257 found := false 258 for i, e := range cmd.Env { 259 if strings.HasPrefix(e, "PPROF_TMPDIR=") { 260 cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir() 261 found = true 262 break 263 } 264 } 265 if !found { 266 cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir()) 267 } 268 269 top, err := cmd.CombinedOutput() 270 t.Logf("%s", top) 271 if err != nil { 272 t.Fatal(err) 273 } 274 275 if !bytes.Contains(top, []byte("cpuHog")) { 276 t.Error("missing cpuHog in pprof output") 277 } 278 } 279 280 func TestCgoPprof(t *testing.T) { 281 testCgoPprof(t, "", "CgoPprof") 282 } 283 284 func TestCgoPprofPIE(t *testing.T) { 285 testCgoPprof(t, "-ldflags=-extldflags=-pie", "CgoPprof") 286 } 287 288 func TestCgoPprofThread(t *testing.T) { 289 testCgoPprof(t, "", "CgoPprofThread") 290 }