libgo: update to go1.9
[official-gcc.git] / libgo / go / sync / pool_test.go
blobdad2f992e7c7600576c9026bfb36d58ffdf57ec0
1 // Copyright 2013 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.
5 // Pool is no-op under race detector, so all these tests do not work.
6 // +build !race
8 package sync_test
10 import (
11 "runtime"
12 "runtime/debug"
13 . "sync"
14 "sync/atomic"
15 "testing"
16 "time"
19 func TestPool(t *testing.T) {
20 // disable GC so we can control when it happens.
21 defer debug.SetGCPercent(debug.SetGCPercent(-1))
22 var p Pool
23 if p.Get() != nil {
24 t.Fatal("expected empty")
27 // Make sure that the goroutine doesn't migrate to another P
28 // between Put and Get calls.
29 Runtime_procPin()
30 p.Put("a")
31 p.Put("b")
32 if g := p.Get(); g != "a" {
33 t.Fatalf("got %#v; want a", g)
35 if g := p.Get(); g != "b" {
36 t.Fatalf("got %#v; want b", g)
38 if g := p.Get(); g != nil {
39 t.Fatalf("got %#v; want nil", g)
41 Runtime_procUnpin()
43 p.Put("c")
44 debug.SetGCPercent(100) // to allow following GC to actually run
45 runtime.GC()
46 if g := p.Get(); g != nil {
47 t.Fatalf("got %#v; want nil after GC", g)
51 func TestPoolNew(t *testing.T) {
52 // disable GC so we can control when it happens.
53 defer debug.SetGCPercent(debug.SetGCPercent(-1))
55 i := 0
56 p := Pool{
57 New: func() interface{} {
58 i++
59 return i
62 if v := p.Get(); v != 1 {
63 t.Fatalf("got %v; want 1", v)
65 if v := p.Get(); v != 2 {
66 t.Fatalf("got %v; want 2", v)
69 // Make sure that the goroutine doesn't migrate to another P
70 // between Put and Get calls.
71 Runtime_procPin()
72 p.Put(42)
73 if v := p.Get(); v != 42 {
74 t.Fatalf("got %v; want 42", v)
76 Runtime_procUnpin()
78 if v := p.Get(); v != 3 {
79 t.Fatalf("got %v; want 3", v)
83 // Test that Pool does not hold pointers to previously cached resources.
84 func TestPoolGC(t *testing.T) {
85 testPool(t, true)
88 // Test that Pool releases resources on GC.
89 func TestPoolRelease(t *testing.T) {
90 testPool(t, false)
93 func testPool(t *testing.T, drain bool) {
94 t.Skip("gccgo imprecise GC breaks this test")
95 var p Pool
96 const N = 100
97 loop:
98 for try := 0; try < 3; try++ {
99 var fin, fin1 uint32
100 for i := 0; i < N; i++ {
101 v := new(string)
102 runtime.SetFinalizer(v, func(vv *string) {
103 atomic.AddUint32(&fin, 1)
105 p.Put(v)
107 if drain {
108 for i := 0; i < N; i++ {
109 p.Get()
112 for i := 0; i < 5; i++ {
113 runtime.GC()
114 time.Sleep(time.Duration(i*100+10) * time.Millisecond)
115 // 1 pointer can remain on stack or elsewhere
116 if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 {
117 continue loop
120 t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try)
124 func TestPoolStress(t *testing.T) {
125 const P = 10
126 N := int(1e6)
127 if testing.Short() {
128 N /= 100
130 var p Pool
131 done := make(chan bool)
132 for i := 0; i < P; i++ {
133 go func() {
134 var v interface{} = 0
135 for j := 0; j < N; j++ {
136 if v == nil {
137 v = 0
139 p.Put(v)
140 v = p.Get()
141 if v != nil && v.(int) != 0 {
142 t.Errorf("expect 0, got %v", v)
143 break
146 done <- true
149 for i := 0; i < P; i++ {
150 <-done
154 func BenchmarkPool(b *testing.B) {
155 var p Pool
156 b.RunParallel(func(pb *testing.PB) {
157 for pb.Next() {
158 p.Put(1)
159 p.Get()
164 func BenchmarkPoolOverflow(b *testing.B) {
165 var p Pool
166 b.RunParallel(func(pb *testing.PB) {
167 for pb.Next() {
168 for b := 0; b < 100; b++ {
169 p.Put(1)
171 for b := 0; b < 100; b++ {
172 p.Get()