github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/sync/pool_test.go (about) 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. 4 5 // Pool is no-op under race detector, so all these tests do not work. 6 // +build !race 7 8 package sync_test 9 10 import ( 11 "runtime" 12 "runtime/debug" 13 . "sync" 14 "sync/atomic" 15 "testing" 16 "time" 17 ) 18 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") 25 } 26 p.Put("a") 27 p.Put("b") 28 if g := p.Get(); g != "a" { 29 t.Fatalf("got %#v; want a", g) 30 } 31 if g := p.Get(); g != "b" { 32 t.Fatalf("got %#v; want b", g) 33 } 34 if g := p.Get(); g != nil { 35 t.Fatalf("got %#v; want nil", g) 36 } 37 38 p.Put("c") 39 debug.SetGCPercent(100) // to allow following GC to actually run 40 runtime.GC() 41 if g := p.Get(); g != nil { 42 t.Fatalf("got %#v; want nil after GC", g) 43 } 44 } 45 46 func TestPoolNew(t *testing.T) { 47 // disable GC so we can control when it happens. 48 defer debug.SetGCPercent(debug.SetGCPercent(-1)) 49 50 i := 0 51 p := Pool{ 52 New: func() interface{} { 53 i++ 54 return i 55 }, 56 } 57 if v := p.Get(); v != 1 { 58 t.Fatalf("got %v; want 1", v) 59 } 60 if v := p.Get(); v != 2 { 61 t.Fatalf("got %v; want 2", v) 62 } 63 p.Put(42) 64 if v := p.Get(); v != 42 { 65 t.Fatalf("got %v; want 42", v) 66 } 67 if v := p.Get(); v != 3 { 68 t.Fatalf("got %v; want 3", v) 69 } 70 } 71 72 // Test that Pool does not hold pointers to previously cached resources. 73 func TestPoolGC(t *testing.T) { 74 testPool(t, true) 75 } 76 77 // Test that Pool releases resources on GC. 78 func TestPoolRelease(t *testing.T) { 79 testPool(t, false) 80 } 81 82 func testPool(t *testing.T, drain bool) { 83 var p Pool 84 const N = 100 85 loop: 86 for try := 0; try < 3; try++ { 87 var fin, fin1 uint32 88 for i := 0; i < N; i++ { 89 v := new(string) 90 runtime.SetFinalizer(v, func(vv *string) { 91 atomic.AddUint32(&fin, 1) 92 }) 93 p.Put(v) 94 } 95 if drain { 96 for i := 0; i < N; i++ { 97 p.Get() 98 } 99 } 100 for i := 0; i < 5; i++ { 101 runtime.GC() 102 time.Sleep(time.Duration(i*100+10) * time.Millisecond) 103 // 1 pointer can remain on stack or elsewhere 104 if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 { 105 continue loop 106 } 107 } 108 t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try) 109 } 110 } 111 112 func TestPoolStress(t *testing.T) { 113 const P = 10 114 N := int(1e6) 115 if testing.Short() { 116 N /= 100 117 } 118 var p Pool 119 done := make(chan bool) 120 for i := 0; i < P; i++ { 121 go func() { 122 var v interface{} = 0 123 for j := 0; j < N; j++ { 124 if v == nil { 125 v = 0 126 } 127 p.Put(v) 128 v = p.Get() 129 if v != nil && v.(int) != 0 { 130 t.Fatalf("expect 0, got %v", v) 131 } 132 } 133 done <- true 134 }() 135 } 136 for i := 0; i < P; i++ { 137 <-done 138 } 139 } 140 141 func BenchmarkPool(b *testing.B) { 142 var p Pool 143 b.RunParallel(func(pb *testing.PB) { 144 for pb.Next() { 145 p.Put(1) 146 p.Get() 147 } 148 }) 149 } 150 151 func BenchmarkPoolOverflow(b *testing.B) { 152 var p Pool 153 b.RunParallel(func(pb *testing.PB) { 154 for pb.Next() { 155 for b := 0; b < 100; b++ { 156 p.Put(1) 157 } 158 for b := 0; b < 100; b++ { 159 p.Get() 160 } 161 } 162 }) 163 }