Home | History | Annotate | Download | only in runtime
      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 }
    304