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  }