github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/go/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 t.Skip("gccgo imprecise GC breaks this test") 84 var p Pool 85 const N = 100 86 loop: 87 for try := 0; try < 3; try++ { 88 var fin, fin1 uint32 89 for i := 0; i < N; i++ { 90 v := new(string) 91 runtime.SetFinalizer(v, func(vv *string) { 92 atomic.AddUint32(&fin, 1) 93 }) 94 p.Put(v) 95 } 96 if drain { 97 for i := 0; i < N; i++ { 98 p.Get() 99 } 100 } 101 for i := 0; i < 5; i++ { 102 runtime.GC() 103 time.Sleep(time.Duration(i*100+10) * time.Millisecond) 104 // 1 pointer can remain on stack or elsewhere 105 if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 { 106 continue loop 107 } 108 } 109 t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try) 110 } 111 } 112 113 func TestPoolStress(t *testing.T) { 114 const P = 10 115 N := int(1e6) 116 if testing.Short() { 117 N /= 100 118 } 119 var p Pool 120 done := make(chan bool) 121 for i := 0; i < P; i++ { 122 go func() { 123 var v interface{} = 0 124 for j := 0; j < N; j++ { 125 if v == nil { 126 v = 0 127 } 128 p.Put(v) 129 v = p.Get() 130 if v != nil && v.(int) != 0 { 131 t.Fatalf("expect 0, got %v", v) 132 } 133 } 134 done <- true 135 }() 136 } 137 for i := 0; i < P; i++ { 138 <-done 139 } 140 } 141 142 func BenchmarkPool(b *testing.B) { 143 var p Pool 144 b.RunParallel(func(pb *testing.PB) { 145 for pb.Next() { 146 p.Put(1) 147 p.Get() 148 } 149 }) 150 } 151 152 func BenchmarkPoolOverflow(b *testing.B) { 153 var p Pool 154 b.RunParallel(func(pb *testing.PB) { 155 for pb.Next() { 156 for b := 0; b < 100; b++ { 157 p.Put(1) 158 } 159 for b := 0; b < 100; b++ { 160 p.Get() 161 } 162 } 163 }) 164 }