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