github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/sync/waitgroup_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 sync_test 6 7 import ( 8 . "sync" 9 "sync/atomic" 10 "testing" 11 ) 12 13 func testWaitGroup(t *testing.T, wg1 *WaitGroup, wg2 *WaitGroup) { 14 n := 16 15 wg1.Add(n) 16 wg2.Add(n) 17 exited := make(chan bool, n) 18 for i := 0; i != n; i++ { 19 go func(i int) { 20 wg1.Done() 21 wg2.Wait() 22 exited <- true 23 }(i) 24 } 25 wg1.Wait() 26 for i := 0; i != n; i++ { 27 select { 28 case <-exited: 29 t.Fatal("WaitGroup released group too soon") 30 default: 31 } 32 wg2.Done() 33 } 34 for i := 0; i != n; i++ { 35 <-exited // Will block if barrier fails to unlock someone. 36 } 37 } 38 39 func TestWaitGroup(t *testing.T) { 40 wg1 := &WaitGroup{} 41 wg2 := &WaitGroup{} 42 43 // Run the same test a few times to ensure barrier is in a proper state. 44 for i := 0; i != 8; i++ { 45 testWaitGroup(t, wg1, wg2) 46 } 47 } 48 49 func TestWaitGroupMisuse(t *testing.T) { 50 defer func() { 51 err := recover() 52 if err != "sync: negative WaitGroup counter" { 53 t.Fatalf("Unexpected panic: %#v", err) 54 } 55 }() 56 wg := &WaitGroup{} 57 wg.Add(1) 58 wg.Done() 59 wg.Done() 60 t.Fatal("Should panic") 61 } 62 63 func TestWaitGroupRace(t *testing.T) { 64 // Run this test for about 1ms. 65 for i := 0; i < 1000; i++ { 66 wg := &WaitGroup{} 67 n := new(int32) 68 // spawn goroutine 1 69 wg.Add(1) 70 go func() { 71 atomic.AddInt32(n, 1) 72 wg.Done() 73 }() 74 // spawn goroutine 2 75 wg.Add(1) 76 go func() { 77 atomic.AddInt32(n, 1) 78 wg.Done() 79 }() 80 // Wait for goroutine 1 and 2 81 wg.Wait() 82 if atomic.LoadInt32(n) != 2 { 83 t.Fatal("Spurious wakeup from Wait") 84 } 85 } 86 } 87 88 func BenchmarkWaitGroupUncontended(b *testing.B) { 89 type PaddedWaitGroup struct { 90 WaitGroup 91 pad [128]uint8 92 } 93 b.RunParallel(func(pb *testing.PB) { 94 var wg PaddedWaitGroup 95 for pb.Next() { 96 wg.Add(1) 97 wg.Done() 98 wg.Wait() 99 } 100 }) 101 } 102 103 func benchmarkWaitGroupAddDone(b *testing.B, localWork int) { 104 var wg WaitGroup 105 b.RunParallel(func(pb *testing.PB) { 106 foo := 0 107 for pb.Next() { 108 wg.Add(1) 109 for i := 0; i < localWork; i++ { 110 foo *= 2 111 foo /= 2 112 } 113 wg.Done() 114 } 115 _ = foo 116 }) 117 } 118 119 func BenchmarkWaitGroupAddDone(b *testing.B) { 120 benchmarkWaitGroupAddDone(b, 0) 121 } 122 123 func BenchmarkWaitGroupAddDoneWork(b *testing.B) { 124 benchmarkWaitGroupAddDone(b, 100) 125 } 126 127 func benchmarkWaitGroupWait(b *testing.B, localWork int) { 128 var wg WaitGroup 129 b.RunParallel(func(pb *testing.PB) { 130 foo := 0 131 for pb.Next() { 132 wg.Wait() 133 for i := 0; i < localWork; i++ { 134 foo *= 2 135 foo /= 2 136 } 137 } 138 _ = foo 139 }) 140 } 141 142 func BenchmarkWaitGroupWait(b *testing.B) { 143 benchmarkWaitGroupWait(b, 0) 144 } 145 146 func BenchmarkWaitGroupWaitWork(b *testing.B) { 147 benchmarkWaitGroupWait(b, 100) 148 }