github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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  	t.Parallel()
    28  	if testing.Short() && runtime.GOOS == "windows" {
    29  		t.Skip("Skipping in short mode") // takes up to 64 seconds
    30  	}
    31  	got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
    32  	want := "OK\n"
    33  	if got != want {
    34  		t.Fatalf("expected %q, but got:\n%s", want, got)
    35  	}
    36  }
    37  
    38  func TestCgoTraceback(t *testing.T) {
    39  	t.Parallel()
    40  	got := runTestProg(t, "testprogcgo", "CgoTraceback")
    41  	want := "OK\n"
    42  	if got != want {
    43  		t.Fatalf("expected %q, but got:\n%s", want, got)
    44  	}
    45  }
    46  
    47  func TestCgoCallbackGC(t *testing.T) {
    48  	t.Parallel()
    49  	switch runtime.GOOS {
    50  	case "plan9", "windows":
    51  		t.Skipf("no pthreads on %s", runtime.GOOS)
    52  	}
    53  	if testing.Short() {
    54  		switch {
    55  		case runtime.GOOS == "dragonfly":
    56  			t.Skip("see golang.org/issue/11990")
    57  		case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
    58  			t.Skip("too slow for arm builders")
    59  		case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le"):
    60  			t.Skip("too slow for mips64x builders")
    61  		}
    62  	}
    63  	got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
    64  	want := "OK\n"
    65  	if got != want {
    66  		t.Fatalf("expected %q, but got:\n%s", want, got)
    67  	}
    68  }
    69  
    70  func TestCgoExternalThreadPanic(t *testing.T) {
    71  	t.Parallel()
    72  	if runtime.GOOS == "plan9" {
    73  		t.Skipf("no pthreads on %s", runtime.GOOS)
    74  	}
    75  	got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
    76  	want := "panic: BOOM"
    77  	if !strings.Contains(got, want) {
    78  		t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
    79  	}
    80  }
    81  
    82  func TestCgoExternalThreadSIGPROF(t *testing.T) {
    83  	t.Parallel()
    84  	// issue 9456.
    85  	switch runtime.GOOS {
    86  	case "plan9", "windows":
    87  		t.Skipf("no pthreads on %s", runtime.GOOS)
    88  	case "darwin":
    89  		if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" {
    90  			// static constructor needs external linking, but we don't support
    91  			// external linking on OS X 10.6.
    92  			out, err := exec.Command("uname", "-r").Output()
    93  			if err != nil {
    94  				t.Fatalf("uname -r failed: %v", err)
    95  			}
    96  			// OS X 10.6 == Darwin 10.x
    97  			if strings.HasPrefix(string(out), "10.") {
    98  				t.Skipf("no external linking on OS X 10.6")
    99  			}
   100  		}
   101  	}
   102  	if runtime.GOARCH == "ppc64" {
   103  		// TODO(austin) External linking not implemented on
   104  		// ppc64 (issue #8912)
   105  		t.Skipf("no external linking on ppc64")
   106  	}
   107  
   108  	exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  
   113  	got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
   114  	if err != nil {
   115  		t.Fatalf("exit status: %v\n%s", err, got)
   116  	}
   117  
   118  	if want := "OK\n"; string(got) != want {
   119  		t.Fatalf("expected %q, but got:\n%s", want, got)
   120  	}
   121  }
   122  
   123  func TestCgoExternalThreadSignal(t *testing.T) {
   124  	t.Parallel()
   125  	// issue 10139
   126  	switch runtime.GOOS {
   127  	case "plan9", "windows":
   128  		t.Skipf("no pthreads on %s", runtime.GOOS)
   129  	}
   130  
   131  	exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
   137  	if err != nil {
   138  		t.Fatalf("exit status: %v\n%s", err, got)
   139  	}
   140  
   141  	want := []byte("OK\n")
   142  	if !bytes.Equal(got, want) {
   143  		t.Fatalf("expected %q, but got:\n%s", want, got)
   144  	}
   145  }
   146  
   147  func TestCgoDLLImports(t *testing.T) {
   148  	// test issue 9356
   149  	if runtime.GOOS != "windows" {
   150  		t.Skip("skipping windows specific test")
   151  	}
   152  	got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
   153  	want := "OK\n"
   154  	if got != want {
   155  		t.Fatalf("expected %q, but got %v", want, got)
   156  	}
   157  }
   158  
   159  func TestCgoExecSignalMask(t *testing.T) {
   160  	t.Parallel()
   161  	// Test issue 13164.
   162  	switch runtime.GOOS {
   163  	case "windows", "plan9":
   164  		t.Skipf("skipping signal mask test on %s", runtime.GOOS)
   165  	}
   166  	got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
   167  	want := "OK\n"
   168  	if got != want {
   169  		t.Errorf("expected %q, got %v", want, got)
   170  	}
   171  }
   172  
   173  func TestEnsureDropM(t *testing.T) {
   174  	t.Parallel()
   175  	// Test for issue 13881.
   176  	switch runtime.GOOS {
   177  	case "windows", "plan9":
   178  		t.Skipf("skipping dropm test on %s", runtime.GOOS)
   179  	}
   180  	got := runTestProg(t, "testprogcgo", "EnsureDropM")
   181  	want := "OK\n"
   182  	if got != want {
   183  		t.Errorf("expected %q, got %v", want, got)
   184  	}
   185  }
   186  
   187  // Test for issue 14387.
   188  // Test that the program that doesn't need any cgo pointer checking
   189  // takes about the same amount of time with it as without it.
   190  func TestCgoCheckBytes(t *testing.T) {
   191  	t.Parallel()
   192  	// Make sure we don't count the build time as part of the run time.
   193  	testenv.MustHaveGoBuild(t)
   194  	exe, err := buildTestProg(t, "testprogcgo")
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  
   199  	// Try it 10 times to avoid flakiness.
   200  	const tries = 10
   201  	var tot1, tot2 time.Duration
   202  	for i := 0; i < tries; i++ {
   203  		cmd := testEnv(exec.Command(exe, "CgoCheckBytes"))
   204  		cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
   205  
   206  		start := time.Now()
   207  		cmd.Run()
   208  		d1 := time.Since(start)
   209  
   210  		cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
   211  		cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
   212  
   213  		start = time.Now()
   214  		cmd.Run()
   215  		d2 := time.Since(start)
   216  
   217  		if d1*20 > d2 {
   218  			// The slow version (d2) was less than 20 times
   219  			// slower than the fast version (d1), so OK.
   220  			return
   221  		}
   222  
   223  		tot1 += d1
   224  		tot2 += d2
   225  	}
   226  
   227  	t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
   228  }
   229  
   230  func TestCgoPanicDeadlock(t *testing.T) {
   231  	t.Parallel()
   232  	// test issue 14432
   233  	got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
   234  	want := "panic: cgo error\n\n"
   235  	if !strings.HasPrefix(got, want) {
   236  		t.Fatalf("output does not start with %q:\n%s", want, got)
   237  	}
   238  }
   239  
   240  func TestCgoCCodeSIGPROF(t *testing.T) {
   241  	t.Parallel()
   242  	got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
   243  	want := "OK\n"
   244  	if got != want {
   245  		t.Errorf("expected %q got %v", want, got)
   246  	}
   247  }
   248  
   249  func TestCgoCrashTraceback(t *testing.T) {
   250  	t.Parallel()
   251  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
   252  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   253  	}
   254  	got := runTestProg(t, "testprogcgo", "CrashTraceback")
   255  	for i := 1; i <= 3; i++ {
   256  		if !strings.Contains(got, fmt.Sprintf("cgo symbolizer:%d", i)) {
   257  			t.Errorf("missing cgo symbolizer:%d", i)
   258  		}
   259  	}
   260  }
   261  
   262  func TestCgoTracebackContext(t *testing.T) {
   263  	t.Parallel()
   264  	got := runTestProg(t, "testprogcgo", "TracebackContext")
   265  	want := "OK\n"
   266  	if got != want {
   267  		t.Errorf("expected %q got %v", want, got)
   268  	}
   269  }
   270  
   271  func testCgoPprof(t *testing.T, buildArg, runArg string) {
   272  	t.Parallel()
   273  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
   274  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   275  	}
   276  	testenv.MustHaveGoRun(t)
   277  
   278  	exe, err := buildTestProg(t, "testprogcgo", buildArg)
   279  	if err != nil {
   280  		t.Fatal(err)
   281  	}
   282  
   283  	got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput()
   284  	if err != nil {
   285  		if testenv.Builder() == "linux-amd64-alpine" {
   286  			// See Issue 18243 and Issue 19938.
   287  			t.Skipf("Skipping failing test on Alpine (golang.org/issue/18243). Ignoring error: %v", err)
   288  		}
   289  		t.Fatal(err)
   290  	}
   291  	fn := strings.TrimSpace(string(got))
   292  	defer os.Remove(fn)
   293  
   294  	for try := 0; try < 2; try++ {
   295  		cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1"))
   296  		// Check that pprof works both with and without explicit executable on command line.
   297  		if try == 0 {
   298  			cmd.Args = append(cmd.Args, exe, fn)
   299  		} else {
   300  			cmd.Args = append(cmd.Args, fn)
   301  		}
   302  
   303  		found := false
   304  		for i, e := range cmd.Env {
   305  			if strings.HasPrefix(e, "PPROF_TMPDIR=") {
   306  				cmd.Env[i] = "PPROF_TMPDIR=" + os.TempDir()
   307  				found = true
   308  				break
   309  			}
   310  		}
   311  		if !found {
   312  			cmd.Env = append(cmd.Env, "PPROF_TMPDIR="+os.TempDir())
   313  		}
   314  
   315  		top, err := cmd.CombinedOutput()
   316  		t.Logf("%s:\n%s", cmd.Args, top)
   317  		if err != nil {
   318  			t.Error(err)
   319  		} else if !bytes.Contains(top, []byte("cpuHog")) {
   320  			t.Error("missing cpuHog in pprof output")
   321  		}
   322  	}
   323  }
   324  
   325  func TestCgoPprof(t *testing.T) {
   326  	testCgoPprof(t, "", "CgoPprof")
   327  }
   328  
   329  func TestCgoPprofPIE(t *testing.T) {
   330  	testCgoPprof(t, "-ldflags=-extldflags=-pie", "CgoPprof")
   331  }
   332  
   333  func TestCgoPprofThread(t *testing.T) {
   334  	testCgoPprof(t, "", "CgoPprofThread")
   335  }
   336  
   337  func TestCgoPprofThreadNoTraceback(t *testing.T) {
   338  	testCgoPprof(t, "", "CgoPprofThreadNoTraceback")
   339  }
   340  
   341  func TestRaceProf(t *testing.T) {
   342  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
   343  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   344  	}
   345  
   346  	testenv.MustHaveGoRun(t)
   347  
   348  	// This test requires building various packages with -race, so
   349  	// it's somewhat slow.
   350  	if testing.Short() {
   351  		t.Skip("skipping test in -short mode")
   352  	}
   353  
   354  	exe, err := buildTestProg(t, "testprogcgo", "-race")
   355  	if err != nil {
   356  		t.Fatal(err)
   357  	}
   358  
   359  	got, err := testEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
   360  	if err != nil {
   361  		t.Fatal(err)
   362  	}
   363  	want := "OK\n"
   364  	if string(got) != want {
   365  		t.Errorf("expected %q got %s", want, got)
   366  	}
   367  }
   368  
   369  func TestRaceSignal(t *testing.T) {
   370  	t.Parallel()
   371  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
   372  		t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
   373  	}
   374  
   375  	testenv.MustHaveGoRun(t)
   376  
   377  	// This test requires building various packages with -race, so
   378  	// it's somewhat slow.
   379  	if testing.Short() {
   380  		t.Skip("skipping test in -short mode")
   381  	}
   382  
   383  	exe, err := buildTestProg(t, "testprogcgo", "-race")
   384  	if err != nil {
   385  		t.Fatal(err)
   386  	}
   387  
   388  	got, err := testEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
   389  	if err != nil {
   390  		t.Logf("%s\n", got)
   391  		t.Fatal(err)
   392  	}
   393  	want := "OK\n"
   394  	if string(got) != want {
   395  		t.Errorf("expected %q got %s", want, got)
   396  	}
   397  }