github.com/andy2046/gopie@v0.7.0/pkg/barrier/barrier_test.go (about) 1 package barrier 2 3 import ( 4 "context" 5 "sync" 6 "sync/atomic" 7 "testing" 8 "time" 9 ) 10 11 func TestNew(t *testing.T) { 12 num := 10 13 b := New(num) 14 n, nWaiting := b.N(), b.NWaiting() 15 isBroken := b.IsBroken() 16 17 if n != num { 18 t.Error("number of barrier members, expected", num, ", got", n) 19 } 20 if nWaiting != 0 { 21 t.Error("number of barrier members waiting, expected", 0, ", got", nWaiting) 22 } 23 if isBroken != false { 24 t.Error("barrier isBroken, expected", false, ", got", isBroken) 25 } 26 27 defer func() { 28 if recover() == nil { 29 t.Error("panic expected") 30 } 31 }() 32 _ = New(0) 33 _ = New(-1) 34 } 35 36 func TestAwaitOnce(t *testing.T) { 37 num := 100 38 b := New(num) 39 ctx := context.Background() 40 41 wg := sync.WaitGroup{} 42 for i := 0; i < num; i++ { 43 wg.Add(1) 44 go func() { 45 err := b.Await(ctx) 46 if err != nil { 47 panic(err) 48 } 49 wg.Done() 50 }() 51 } 52 53 wg.Wait() 54 55 n, nWaiting := b.N(), b.NWaiting() 56 isBroken := b.IsBroken() 57 58 if n != num { 59 t.Error("number of barrier members, expected", num, ", got", n) 60 } 61 if nWaiting != 0 { 62 t.Error("number of barrier members waiting, expected", 0, ", got", nWaiting) 63 } 64 if isBroken != false { 65 t.Error("barrier isBroken, expected", false, ", got", isBroken) 66 } 67 } 68 69 func TestAwaitMany(t *testing.T) { 70 num := 100 71 m := 1000 72 b := New(num) 73 ctx := context.Background() 74 wg := sync.WaitGroup{} 75 76 for i := 0; i < num; i++ { 77 wg.Add(1) 78 go func() { 79 for j := 0; j < m; j++ { 80 err := b.Await(ctx) 81 if err != nil { 82 panic(err) 83 } 84 } 85 wg.Done() 86 }() 87 } 88 89 wg.Wait() 90 91 n, nWaiting := b.N(), b.NWaiting() 92 isBroken := b.IsBroken() 93 94 if n != num { 95 t.Error("number of barrier members, expected", num, ", got", n) 96 } 97 if nWaiting != 0 { 98 t.Error("number of barrier members waiting, expected", 0, ", got", nWaiting) 99 } 100 if isBroken != false { 101 t.Error("barrier isBroken, expected", false, ", got", isBroken) 102 } 103 } 104 105 func TestAwaitTooMany(t *testing.T) { 106 num := 100 107 m := 1000 108 b := New(1) 109 ctx := context.Background() 110 wg := sync.WaitGroup{} 111 112 for i := 0; i < num; i++ { 113 wg.Add(1) 114 go func() { 115 for j := 0; j < m; j++ { 116 err := b.Await(ctx) 117 if err != nil { 118 panic(err) 119 } 120 } 121 wg.Done() 122 }() 123 } 124 125 wg.Wait() 126 127 n, nWaiting := b.N(), b.NWaiting() 128 isBroken := b.IsBroken() 129 130 if n != 1 { 131 t.Error("number of barrier members, expected", num, ", got", n) 132 } 133 if nWaiting != 0 { 134 t.Error("number of barrier members waiting, expected", 0, ", got", nWaiting) 135 } 136 if isBroken != false { 137 t.Error("barrier isBroken, expected", false, ", got", isBroken) 138 } 139 } 140 141 func TestReset(t *testing.T) { 142 num := 100 143 b := New(num + 1) // members are more than goroutines so all goroutines will wait 144 ctx := context.Background() 145 146 go func() { 147 time.Sleep(30 * time.Millisecond) 148 b.Reset() 149 }() 150 151 wg := sync.WaitGroup{} 152 for i := 0; i < num; i++ { 153 wg.Add(1) 154 go func() { 155 err := b.Await(ctx) 156 if err != ErrBroken { 157 panic(err) 158 } 159 wg.Done() 160 }() 161 } 162 163 wg.Wait() 164 165 n, nWaiting := b.N(), b.NWaiting() 166 isBroken := b.IsBroken() 167 168 if n != num+1 { 169 t.Error("number of barrier members, expected", num+1, ", got", n) 170 } 171 if nWaiting != 0 { 172 t.Error("number of barrier members waiting, expected", 0, ", got", nWaiting) 173 } 174 if isBroken != false { 175 t.Error("barrier isBroken, expected", false, ", got", isBroken) 176 } 177 } 178 179 func TestAwaitOnceCtxDone(t *testing.T) { 180 num := 100 181 b := New(num + 1) // members are more than goroutines so all goroutines will wait 182 ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) 183 defer cancel() 184 var deadlineCount, brokenBarrierCount int32 185 wg := sync.WaitGroup{} 186 187 for i := 0; i < num; i++ { 188 wg.Add(1) 189 go func() { 190 err := b.Await(ctx) 191 if err == context.DeadlineExceeded { 192 atomic.AddInt32(&deadlineCount, 1) 193 } else if err == ErrBroken { 194 atomic.AddInt32(&brokenBarrierCount, 1) 195 } else { 196 panic("must be either context.DeadlineExceeded or ErrBroken error") 197 } 198 wg.Done() 199 }() 200 } 201 202 wg.Wait() 203 204 n, nWaiting := b.N(), b.NWaiting() 205 isBroken := b.IsBroken() 206 207 if n != num+1 { 208 t.Error("number of barrier members, expected", num+1, ", got", n) 209 } 210 if nWaiting != 100 { 211 t.Error("number of barrier members waiting, expected", 100, ", got", nWaiting) 212 } 213 if isBroken != true { 214 t.Error("barrier isBroken, expected", true, ", got", isBroken) 215 } 216 217 if deadlineCount == 0 { 218 t.Error("number of context.DeadlineExceeded errors must be more than 0, got", deadlineCount) 219 } 220 if deadlineCount+brokenBarrierCount != int32(num) { 221 t.Error("number of context.DeadlineExceeded and ErrBroken errors, expected", num, ", got", deadlineCount+brokenBarrierCount) 222 } 223 } 224 225 func TestAwaitManyCtxDone(t *testing.T) { 226 num := 100 227 b := New(num) 228 ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) 229 defer cancel() 230 wg := sync.WaitGroup{} 231 232 for i := 0; i < num; i++ { 233 wg.Add(1) 234 go func() { 235 for { 236 err := b.Await(ctx) 237 if err != nil { 238 if err != context.DeadlineExceeded && err != ErrBroken { 239 panic("must be either context.DeadlineExceeded or ErrBroken error") 240 } 241 break 242 } 243 } 244 wg.Done() 245 }() 246 } 247 248 wg.Wait() 249 250 n := b.N() 251 isBroken := b.IsBroken() 252 253 if n != num { 254 t.Error("number of barrier members, expected", num, ", got", n) 255 } 256 if isBroken != true { 257 t.Error("barrier isBroken, expected", true, ", got", isBroken) 258 } 259 }