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