blob: 642a9ca92215f1a5ab7cc8372ae33fda5422d872 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sync
import (
"testing"
"v.io/x/ref/test/testutil"
)
// TestRandom tests Wait after a random sequence of TryAdd's and Done's that
// leaves the counter at 0.
func TestRandom(t *testing.T) {
testutil.InitRandGenerator(t.Logf)
var w WaitGroup
N := 100
count := 0
for n := 0; n < N; n++ {
if count == 0 || testutil.RandomIntn(2) == 0 {
if !w.TryAdd() {
t.Fatal("TryAdd failed")
}
count++
continue
}
w.Done()
count--
}
for d := 0; d < count; d++ {
w.Done()
}
w.Wait()
}
func TestConcurrentWait(t *testing.T) {
for r := 0; r < 100; r++ {
var w WaitGroup
done := make(chan struct{}, 1)
if !w.TryAdd() {
t.Fatal("TryAdd failed")
}
go func() {
w.Wait()
// w.Wait() should not return before w.Done() sets the counter
// to 0.
// This test is not deterministic as we cannot infer the order
// in which Wait() and the last Done() return. Hopefully, bugs
// will revealed by repeating the test.
select {
case <-done:
default:
t.Fatal("Wait returned before Done.")
}
}()
for w.TryAdd() {
w.Done()
}
close(done)
w.Done()
}
}
func TestTryAddFailsAfterWait(t *testing.T) {
var w WaitGroup
if !w.TryAdd() {
t.Fatal("TryAdd failed")
}
go w.Wait()
// At some point, another goroutine will be in w.Wait() and w.TryAdd()
// should fail. If this doesn't happen, the test will never terminate.
for w.TryAdd() {
w.Done()
}
w.Done()
}
func TestIdempotentWait(t *testing.T) {
var w WaitGroup
done := make(chan struct{}, 1)
if !w.TryAdd() {
t.Fatal("TryAdd failed")
}
// w.Wait() should be idempotent.
for i := 0; i < 2; i++ {
go func() {
w.Wait()
select {
case <-done:
default:
t.Fatal("Wait returned before Done.")
}
}()
}
for w.TryAdd() {
w.Done()
}
close(done)
w.Done()
}
func TestDoneFailsBeforeAdd(t *testing.T) {
var w WaitGroup
defer func() {
if r := recover(); r == nil {
t.Fatal("Done succeeded before Add.")
}
}()
w.Done()
}