github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/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  	t.Parallel()
    23  	testCrashHandler(t, true)
    24  }
    25  
    26  func TestCgoSignalDeadlock(t *testing.T) {
    27  	// 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  
    31  	if testing.Short() && runtime.GOOS == "windows" {
    32  		t.Skip("Skipping in short mode") // takes up to 64 seconds
    33  	}
    34  	got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
    35  	want := "OK\n"
    36  	if got != want {
    37  		t.Fatalf("expected %q, but got:\n%s", want, got)
    38  	}
    39  }
    40  
    41  func TestCgoTraceback(t *testing.T) {
    42  	t.Parallel()
    43  	got := runTestProg(t, "testprogcgo", "CgoTraceback")
    44  	want := "OK\n"
    45  	if got != want {
    46  		t.Fatalf("expected %q, but got:\n%s", want, got)
    47  	}
    48  }
    49  
    50  func TestCgoCallbackGC(t *testing.T) {
    51  	t.Parallel()
    52  	switch runtime.GOOS {
    53  	case "plan9", "windows":
    54  		t.Skipf("no pthreads on %s", runtime.GOOS)
    55  	}
    56  	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")
    62  		case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
    63  			t.Skip("too slow for mips64x builders")
    64  		}
    65  	}
    66  	got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
    67  	want := "OK\n"
    68  	if got != want {
    69  		t.Fatalf("expected %q, but got:\n%s", want, got)
    70  	}
    71  }
    72  
    73  func TestCgoExternalThreadPanic(t *testing.T) {
    74  	t.Parallel()
    75  	if runtime.GOOS == "plan9" {
    76  		t.Skipf("no pthreads on %s", runtime.GOOS)
    77  	}
    78  	got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
    79  	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  
    85  func TestCgoExternalThreadSIGPROF(t *testing.T) {
    86  	t.Parallel()
    87  	// issue 9456.
    88  	switch runtime.GOOS {
    89  	case "plan9", "windows":
    90  		t.Skipf("no pthreads on %s", runtime.GOOS)
    91  	case "darwin":
    92  		if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" {
    93  			// 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  			}
   103  		}
   104  	}
   105  	if runtime.GOARCH == "ppc64" {
   106  		// TODO(austin) External linking not implemented on
   107  		// ppc64 (issue #8912)
   108  		t.Skipf("no external linking on ppc64")
   109  	}
   110  
   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 {
   122  		t.Fatalf("expected %q, but got:\n%s", want, got)
   123  	}
   124  }
   125  
   126  func TestCgoExternalThreadSignal(t *testing.T) {
   127  	t.Parallel()
   128  	// issue 10139
   129  	switch runtime.GOOS {
   130  	case "plan9", "windows":
   131  		t.Skipf("no pthreads on %s", runtime.GOOS)
   132  	}
   133  
   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) {
   146  		t.Fatalf("expected %q, but got:\n%s", want, got)
   147  	}
   148  }
   149  
   150  func TestCgoDLLImports(t *testing.T) {
   151  	// test issue 9356
   152  	if runtime.GOOS != "windows" {
   153  		t.Skip("skipping windows specific test")
   154  	}
   155  	got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
   156  	want := "OK\n"
   157  	if got != want {
   158  		t.Fatalf("expected %q, but got %v", want, got)
   159  	}
   160  }
   161  
   162  func TestCgoExecSignalMask(t *testing.T) {
   163  	t.Parallel()
   164  	// 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  }
   175  
   176  func TestEnsureDropM(t *testing.T) {
   177  	t.Parallel()
   178  	// Test for issue 13881.
   179  	switch runtime.GOOS {
   180  	case "windows", "plan9":
   181  		t.Skipf("skipping dropm test on %s", runtime.GOOS)
   182  	}
   183  	got := runTestProg(t, "testprogcgo", "EnsureDropM")
   184  	want := "OK\n"
   185  	if got != want {
   186  		t.Errorf("expected %q, got %v", want, got)
   187  	}
   188  }
   189  
   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.
   193  func TestCgoCheckBytes(t *testing.T) {
   194  	t.Parallel()
   195  	// 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  
   202  	// 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))
   208  
   209  		start := time.Now()
   210  		cmd.Run()
   211  		d1 := time.Since(start)
   212  
   213  		cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
   214  		cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
   215  
   216  		start = time.Now()
   217  		cmd.Run()
   218  		d2 := time.Since(start)
   219  
   220  		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
   228  	}
   229  
   230  	t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
   231  }
   232  
   233  func TestCgoPanicDeadlock(t *testing.T) {
   234  	t.Parallel()
   235  	// 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  }
   242  
   243  func TestCgoCCodeSIGPROF(t *testing.T) {
   244  	t.Parallel()
   245  	got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
   246  	want := "OK\n"
   247  	if got != want {
   248  		t.Errorf("expected %q got %v", want, got)
   249  	}
   250  }
   251  
   252  func TestCgoCrashTraceback(t *testing.T) {
   253  	t.Parallel()
   254  	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  }
   264  
   265  func TestCgoTracebackContext(t *testing.T) {
   266  	t.Parallel()
   267  	got := runTestProg(t, "testprogcgo", "TracebackContext")
   268  	want := "OK\n"
   269  	if got != want {
   270  		t.Errorf("expected %q got %v", want, got)
   271  	}
   272  }
   273  
   274  func testCgoPprof(t *testing.T, buildArg, runArg string) {
   275  	t.Parallel()
   276  	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  
   281  	exe, err := buildTestProg(t, "testprogcgo", buildArg)
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  
   286  	got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput()
   287  	if err != nil {
   288  		if testenv.Builder() == "linux-amd64-alpine" {
   289  			// See Issue 18243 and Issue 19938.
   290  			t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
   291  		}
   292  		t.Fatal(err)
   293  	}
   294  	fn := strings.TrimSpace(string(got))
   295  	defer os.Remove(fn)
   296  
   297  	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)
   304  		}
   305  
   306  		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  		}
   317  
   318  		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  		}
   325  	}
   326  }
   327  
   328  func TestCgoPprof(t *testing.T) {
   329  	testCgoPprof(t, "", "CgoPprof")
   330  }
   331  
   332  func TestCgoPprofPIE(t *testing.T) {
   333  	testCgoPprof(t, "-ldflags=-extldflags=-pie", "CgoPprof")
   334  }
   335  
   336  func TestCgoPprofThread(t *testing.T) {
   337  	testCgoPprof(t, "", "CgoPprofThread")
   338  }
   339  
   340  func TestCgoPprofThreadNoTraceback(t *testing.T) {
   341  	testCgoPprof(t, "", "CgoPprofThreadNoTraceback")
   342  }
   343  
   344  func 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  }
   371  
   372  func TestRaceSignal(t *testing.T) {
   373  	t.Parallel()
   374  	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  }
   401  
   402  func TestCgoNumGoroutine(t *testing.T) {
   403  	switch runtime.GOOS {
   404  	case "windows", "plan9":
   405  		t.Skipf("skipping numgoroutine test on %s", runtime.GOOS)
   406  	}
   407  	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  }