...
Run Format

Source file src/runtime/runtime_test.go

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

View as plain text