github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/runtime/gc_test.go (about)

     1  // Copyright 2011 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  	"os"
     9  	"runtime"
    10  	"runtime/debug"
    11  	"testing"
    12  )
    13  
    14  func TestGcSys(t *testing.T) {
    15  	if os.Getenv("GOGC") == "off" {
    16  		t.Skip("skipping test; GOGC=off in environment")
    17  	}
    18  	data := struct{ Short bool }{testing.Short()}
    19  	got := executeTest(t, testGCSysSource, &data)
    20  	want := "OK\n"
    21  	if got != want {
    22  		t.Fatalf("expected %q, but got %q", want, got)
    23  	}
    24  }
    25  
    26  const testGCSysSource = `
    27  package main
    28  
    29  import (
    30  	"fmt"
    31  	"runtime"
    32  )
    33  
    34  func main() {
    35  	runtime.GOMAXPROCS(1)
    36  	memstats := new(runtime.MemStats)
    37  	runtime.GC()
    38  	runtime.ReadMemStats(memstats)
    39  	sys := memstats.Sys
    40  
    41  	runtime.MemProfileRate = 0 // disable profiler
    42  
    43  	itercount := 1000000
    44  {{if .Short}}
    45  	itercount = 100000
    46  {{end}}
    47  	for i := 0; i < itercount; i++ {
    48  		workthegc()
    49  	}
    50  
    51  	// Should only be using a few MB.
    52  	// We allocated 100 MB or (if not short) 1 GB.
    53  	runtime.ReadMemStats(memstats)
    54  	if sys > memstats.Sys {
    55  		sys = 0
    56  	} else {
    57  		sys = memstats.Sys - sys
    58  	}
    59  	if sys > 16<<20 {
    60  		fmt.Printf("using too much memory: %d bytes\n", sys)
    61  		return
    62  	}
    63  	fmt.Printf("OK\n")
    64  }
    65  
    66  func workthegc() []byte {
    67  	return make([]byte, 1029)
    68  }
    69  `
    70  
    71  func TestGcDeepNesting(t *testing.T) {
    72  	type T [2][2][2][2][2][2][2][2][2][2]*int
    73  	a := new(T)
    74  
    75  	// Prevent the compiler from applying escape analysis.
    76  	// This makes sure new(T) is allocated on heap, not on the stack.
    77  	t.Logf("%p", a)
    78  
    79  	a[0][0][0][0][0][0][0][0][0][0] = new(int)
    80  	*a[0][0][0][0][0][0][0][0][0][0] = 13
    81  	runtime.GC()
    82  	if *a[0][0][0][0][0][0][0][0][0][0] != 13 {
    83  		t.Fail()
    84  	}
    85  }
    86  
    87  func TestGcHashmapIndirection(t *testing.T) {
    88  	defer debug.SetGCPercent(debug.SetGCPercent(1))
    89  	runtime.GC()
    90  	type T struct {
    91  		a [256]int
    92  	}
    93  	m := make(map[T]T)
    94  	for i := 0; i < 2000; i++ {
    95  		var a T
    96  		a.a[0] = i
    97  		m[a] = T{}
    98  	}
    99  }
   100  
   101  func TestGcArraySlice(t *testing.T) {
   102  	type X struct {
   103  		buf     [1]byte
   104  		nextbuf []byte
   105  		next    *X
   106  	}
   107  	var head *X
   108  	for i := 0; i < 10; i++ {
   109  		p := &X{}
   110  		p.buf[0] = 42
   111  		p.next = head
   112  		if head != nil {
   113  			p.nextbuf = head.buf[:]
   114  		}
   115  		head = p
   116  		runtime.GC()
   117  	}
   118  	for p := head; p != nil; p = p.next {
   119  		if p.buf[0] != 42 {
   120  			t.Fatal("corrupted heap")
   121  		}
   122  	}
   123  }
   124  
   125  func TestGcRescan(t *testing.T) {
   126  	type X struct {
   127  		c     chan error
   128  		nextx *X
   129  	}
   130  	type Y struct {
   131  		X
   132  		nexty *Y
   133  		p     *int
   134  	}
   135  	var head *Y
   136  	for i := 0; i < 10; i++ {
   137  		p := &Y{}
   138  		p.c = make(chan error)
   139  		if head != nil {
   140  			p.nextx = &head.X
   141  		}
   142  		p.nexty = head
   143  		p.p = new(int)
   144  		*p.p = 42
   145  		head = p
   146  		runtime.GC()
   147  	}
   148  	for p := head; p != nil; p = p.nexty {
   149  		if *p.p != 42 {
   150  			t.Fatal("corrupted heap")
   151  		}
   152  	}
   153  }