// Copyright 2011 The Go 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_test import ( . "sync" "testing" ) func TestCondSignal(t *testing.T) { var m Mutex c := NewCond(&m) n := 2 running := make(chan bool, n) awake := make(chan bool, n) for i := 0; i < n; i++ { go func() { m.Lock() running <- true c.Wait() awake <- true m.Unlock() }() } for i := 0; i < n; i++ { <-running // Wait for everyone to run. } for n > 0 { select { case <-awake: t.Fatal("goroutine not asleep") default: } m.Lock() c.Signal() m.Unlock() <-awake // Will deadlock if no goroutine wakes up select { case <-awake: t.Fatal("too many goroutines awake") default: } n-- } c.Signal() } func TestCondBroadcast(t *testing.T) { var m Mutex c := NewCond(&m) n := 200 running := make(chan int, n) awake := make(chan int, n) exit := false for i := 0; i < n; i++ { go func(g int) { m.Lock() for !exit { running <- g c.Wait() awake <- g } m.Unlock() }(i) } for i := 0; i < n; i++ { for i := 0; i < n; i++ { <-running // Will deadlock unless n are running. } if i == n-1 { m.Lock() exit = true m.Unlock() } select { case <-awake: t.Fatal("goroutine not asleep") default: } m.Lock() c.Broadcast() m.Unlock() seen := make([]bool, n) for i := 0; i < n; i++ { g := <-awake if seen[g] { t.Fatal("goroutine woke up twice") } seen[g] = true } } select { case <-running: t.Fatal("goroutine did not exit") default: } c.Broadcast() }