github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/runtime/runtime_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  package runtime_test
     6  
     7  import (
     8  	"io"
     9  	. "runtime"
    10  	"runtime/debug"
    11  	"strings"
    12  	"testing"
    13  	"unsafe"
    14  )
    15  
    16  func init() {
    17  	// We're testing the runtime, so make tracebacks show things
    18  	// in the runtime. This only raises the level, so it won't
    19  	// override GOTRACEBACK=crash from the user.
    20  	SetTracebackEnv("system")
    21  }
    22  
    23  var errf error
    24  
    25  func errfn() error {
    26  	return errf
    27  }
    28  
    29  func errfn1() error {
    30  	return io.EOF
    31  }
    32  
    33  func BenchmarkIfaceCmp100(b *testing.B) {
    34  	for i := 0; i < b.N; i++ {
    35  		for j := 0; j < 100; j++ {
    36  			if errfn() == io.EOF {
    37  				b.Fatal("bad comparison")
    38  			}
    39  		}
    40  	}
    41  }
    42  
    43  func BenchmarkIfaceCmpNil100(b *testing.B) {
    44  	for i := 0; i < b.N; i++ {
    45  		for j := 0; j < 100; j++ {
    46  			if errfn1() == nil {
    47  				b.Fatal("bad comparison")
    48  			}
    49  		}
    50  	}
    51  }
    52  
    53  var efaceCmp1 interface{}
    54  var efaceCmp2 interface{}
    55  
    56  func BenchmarkEfaceCmpDiff(b *testing.B) {
    57  	x := 5
    58  	efaceCmp1 = &x
    59  	y := 6
    60  	efaceCmp2 = &y
    61  	for i := 0; i < b.N; i++ {
    62  		for j := 0; j < 100; j++ {
    63  			if efaceCmp1 == efaceCmp2 {
    64  				b.Fatal("bad comparison")
    65  			}
    66  		}
    67  	}
    68  }
    69  
    70  func BenchmarkDefer(b *testing.B) {
    71  	for i := 0; i < b.N; i++ {
    72  		defer1()
    73  	}
    74  }
    75  
    76  func defer1() {
    77  	defer func(x, y, z int) {
    78  		if recover() != nil || x != 1 || y != 2 || z != 3 {
    79  			panic("bad recover")
    80  		}
    81  	}(1, 2, 3)
    82  }
    83  
    84  func BenchmarkDefer10(b *testing.B) {
    85  	for i := 0; i < b.N/10; i++ {
    86  		defer2()
    87  	}
    88  }
    89  
    90  func defer2() {
    91  	for i := 0; i < 10; i++ {
    92  		defer func(x, y, z int) {
    93  			if recover() != nil || x != 1 || y != 2 || z != 3 {
    94  				panic("bad recover")
    95  			}
    96  		}(1, 2, 3)
    97  	}
    98  }
    99  
   100  func BenchmarkDeferMany(b *testing.B) {
   101  	for i := 0; i < b.N; i++ {
   102  		defer func(x, y, z int) {
   103  			if recover() != nil || x != 1 || y != 2 || z != 3 {
   104  				panic("bad recover")
   105  			}
   106  		}(1, 2, 3)
   107  	}
   108  }
   109  
   110  // golang.org/issue/7063
   111  func TestStopCPUProfilingWithProfilerOff(t *testing.T) {
   112  	SetCPUProfileRate(0)
   113  }
   114  
   115  // Addresses to test for faulting behavior.
   116  // This is less a test of SetPanicOnFault and more a check that
   117  // the operating system and the runtime can process these faults
   118  // correctly. That is, we're indirectly testing that without SetPanicOnFault
   119  // these would manage to turn into ordinary crashes.
   120  // Note that these are truncated on 32-bit systems, so the bottom 32 bits
   121  // of the larger addresses must themselves be invalid addresses.
   122  // We might get unlucky and the OS might have mapped one of these
   123  // addresses, but probably not: they're all in the first page, very high
   124  // addresses that normally an OS would reserve for itself, or malformed
   125  // addresses. Even so, we might have to remove one or two on different
   126  // systems. We will see.
   127  
   128  var faultAddrs = []uint64{
   129  	// low addresses
   130  	0,
   131  	1,
   132  	0xfff,
   133  	// high (kernel) addresses
   134  	// or else malformed.
   135  	0xffffffffffffffff,
   136  	0xfffffffffffff001,
   137  	0xffffffffffff0001,
   138  	0xfffffffffff00001,
   139  	0xffffffffff000001,
   140  	0xfffffffff0000001,
   141  	0xffffffff00000001,
   142  	0xfffffff000000001,
   143  	0xffffff0000000001,
   144  	0xfffff00000000001,
   145  	0xffff000000000001,
   146  	0xfff0000000000001,
   147  	0xff00000000000001,
   148  	0xf000000000000001,
   149  	0x8000000000000001,
   150  }
   151  
   152  func TestSetPanicOnFault(t *testing.T) {
   153  	old := debug.SetPanicOnFault(true)
   154  	defer debug.SetPanicOnFault(old)
   155  
   156  	nfault := 0
   157  	for _, addr := range faultAddrs {
   158  		testSetPanicOnFault(t, uintptr(addr), &nfault)
   159  	}
   160  	if nfault == 0 {
   161  		t.Fatalf("none of the addresses faulted")
   162  	}
   163  }
   164  
   165  func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) {
   166  	if GOOS == "nacl" {
   167  		t.Skip("nacl doesn't seem to fault on high addresses")
   168  	}
   169  
   170  	defer func() {
   171  		if err := recover(); err != nil {
   172  			*nfault++
   173  		}
   174  	}()
   175  
   176  	// The read should fault, except that sometimes we hit
   177  	// addresses that have had C or kernel pages mapped there
   178  	// readable by user code. So just log the content.
   179  	// If no addresses fault, we'll fail the test.
   180  	v := *(*byte)(unsafe.Pointer(addr))
   181  	t.Logf("addr %#x: %#x\n", addr, v)
   182  }
   183  
   184  func eqstring_generic(s1, s2 string) bool {
   185  	if len(s1) != len(s2) {
   186  		return false
   187  	}
   188  	// optimization in assembly versions:
   189  	// if s1.str == s2.str { return true }
   190  	for i := 0; i < len(s1); i++ {
   191  		if s1[i] != s2[i] {
   192  			return false
   193  		}
   194  	}
   195  	return true
   196  }
   197  
   198  func TestEqString(t *testing.T) {
   199  	// This isn't really an exhaustive test of eqstring, it's
   200  	// just a convenient way of documenting (via eqstring_generic)
   201  	// what eqstring does.
   202  	s := []string{
   203  		"",
   204  		"a",
   205  		"c",
   206  		"aaa",
   207  		"ccc",
   208  		"cccc"[:3], // same contents, different string
   209  		"1234567890",
   210  	}
   211  	for _, s1 := range s {
   212  		for _, s2 := range s {
   213  			x := s1 == s2
   214  			y := eqstring_generic(s1, s2)
   215  			if x != y {
   216  				t.Errorf(`eqstring("%s","%s") = %t, want %t`, s1, s2, x, y)
   217  			}
   218  		}
   219  	}
   220  }
   221  
   222  func TestTrailingZero(t *testing.T) {
   223  	// make sure we add padding for structs with trailing zero-sized fields
   224  	type T1 struct {
   225  		n int32
   226  		z [0]byte
   227  	}
   228  	if unsafe.Sizeof(T1{}) != 8 {
   229  		t.Errorf("sizeof(%#v)==%d, want 8", T1{}, unsafe.Sizeof(T1{}))
   230  	}
   231  	type T2 struct {
   232  		n int64
   233  		z struct{}
   234  	}
   235  	if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(Uintreg(0)) {
   236  		t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(Uintreg(0)))
   237  	}
   238  	type T3 struct {
   239  		n byte
   240  		z [4]struct{}
   241  	}
   242  	if unsafe.Sizeof(T3{}) != 2 {
   243  		t.Errorf("sizeof(%#v)==%d, want 2", T3{}, unsafe.Sizeof(T3{}))
   244  	}
   245  	// make sure padding can double for both zerosize and alignment
   246  	type T4 struct {
   247  		a int32
   248  		b int16
   249  		c int8
   250  		z struct{}
   251  	}
   252  	if unsafe.Sizeof(T4{}) != 8 {
   253  		t.Errorf("sizeof(%#v)==%d, want 8", T4{}, unsafe.Sizeof(T4{}))
   254  	}
   255  	// make sure we don't pad a zero-sized thing
   256  	type T5 struct {
   257  	}
   258  	if unsafe.Sizeof(T5{}) != 0 {
   259  		t.Errorf("sizeof(%#v)==%d, want 0", T5{}, unsafe.Sizeof(T5{}))
   260  	}
   261  }
   262  
   263  func TestBadOpen(t *testing.T) {
   264  	if GOOS == "windows" || GOOS == "nacl" {
   265  		t.Skip("skipping OS that doesn't have open/read/write/close")
   266  	}
   267  	// make sure we get the correct error code if open fails. Same for
   268  	// read/write/close on the resulting -1 fd. See issue 10052.
   269  	nonfile := []byte("/notreallyafile")
   270  	fd := Open(&nonfile[0], 0, 0)
   271  	if fd != -1 {
   272  		t.Errorf("open(\"%s\")=%d, want -1", string(nonfile), fd)
   273  	}
   274  	var buf [32]byte
   275  	r := Read(-1, unsafe.Pointer(&buf[0]), int32(len(buf)))
   276  	if r != -1 {
   277  		t.Errorf("read()=%d, want -1", r)
   278  	}
   279  	w := Write(^uintptr(0), unsafe.Pointer(&buf[0]), int32(len(buf)))
   280  	if w != -1 {
   281  		t.Errorf("write()=%d, want -1", w)
   282  	}
   283  	c := Close(-1)
   284  	if c != -1 {
   285  		t.Errorf("close()=%d, want -1", c)
   286  	}
   287  }
   288  
   289  func TestAppendGrowth(t *testing.T) {
   290  	var x []int64
   291  	check := func(want int) {
   292  		if cap(x) != want {
   293  			t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
   294  		}
   295  	}
   296  
   297  	check(0)
   298  	want := 1
   299  	for i := 1; i <= 100; i++ {
   300  		x = append(x, 1)
   301  		check(want)
   302  		if i&(i-1) == 0 {
   303  			want = 2 * i
   304  		}
   305  	}
   306  }
   307  
   308  var One = []int64{1}
   309  
   310  func TestAppendSliceGrowth(t *testing.T) {
   311  	var x []int64
   312  	check := func(want int) {
   313  		if cap(x) != want {
   314  			t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
   315  		}
   316  	}
   317  
   318  	check(0)
   319  	want := 1
   320  	for i := 1; i <= 100; i++ {
   321  		x = append(x, One...)
   322  		check(want)
   323  		if i&(i-1) == 0 {
   324  			want = 2 * i
   325  		}
   326  	}
   327  }
   328  
   329  func TestGoroutineProfileTrivial(t *testing.T) {
   330  	// Calling GoroutineProfile twice in a row should find the same number of goroutines,
   331  	// but it's possible there are goroutines just about to exit, so we might end up
   332  	// with fewer in the second call. Try a few times; it should converge once those
   333  	// zombies are gone.
   334  	for i := 0; ; i++ {
   335  		n1, ok := GoroutineProfile(nil) // should fail, there's at least 1 goroutine
   336  		if n1 < 1 || ok {
   337  			t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok)
   338  		}
   339  		n2, ok := GoroutineProfile(make([]StackRecord, n1))
   340  		if n2 == n1 && ok {
   341  			break
   342  		}
   343  		t.Logf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1)
   344  		if i >= 10 {
   345  			t.Fatalf("GoroutineProfile not converging")
   346  		}
   347  	}
   348  }
   349  
   350  func TestVersion(t *testing.T) {
   351  	// Test that version does not contain \r or \n.
   352  	vers := Version()
   353  	if strings.Contains(vers, "\r") || strings.Contains(vers, "\n") {
   354  		t.Fatalf("cr/nl in version: %q", vers)
   355  	}
   356  }