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