func BenchmarkSleeperWaitOnSingleSelect(b *testing.B) {
	s := Sleeper{}
	w := Waker{}
	s.AddWaker(&w, 0)
	for i := 0; i < b.N; i++ {
		go func() {
			w.Assert()
		}()
		s.Fetch(true)
	}
}
BenchmarkSleeperWaitOnSingleSelect measures how long it takes to wait on one
waker channel while another goroutine wakes up the sleeper. This assumes that
a new goroutine doesn't run immediately (i.e., the creator of a new goroutine
is allowed to go to sleep before the new goroutine has a chance to run).
package sleep
import (
	"math/rand"
	"runtime"
	"testing"
	"time"
)
func ZeroWakerNotAsserted(t *testing.T) {
	var w Waker
	if w.IsAsserted() {
		t.Fatalf("Zero waker is asserted")
	}
	if w.Clear() {
		t.Fatalf("Zero waker is asserted")
	}
}
func AssertedWakerAfterAssert(t *testing.T) {
	var w Waker
	w.Assert()
	if !w.IsAsserted() {
		t.Fatalf("Asserted waker is not reported as such")
	}
	if !w.Clear() {
		t.Fatalf("Asserted waker is not reported as such")
	}
}
func AssertedWakerAfterTwoAsserts(t *testing.T) {
	var w Waker
	w.Assert()
	w.Assert()
	if !w.IsAsserted() {
		t.Fatalf("Asserted waker is not reported as such")
	}
	if !w.Clear() {
		t.Fatalf("Asserted waker is not reported as such")
	}
}
func NotAssertedWakerWithSleeper(t *testing.T) {
	var w Waker
	var s Sleeper
	s.AddWaker(&w, 0)
	if w.IsAsserted() {
		t.Fatalf("Non-asserted waker is reported as asserted")
	}
	if w.Clear() {
		t.Fatalf("Non-asserted waker is reported as asserted")
	}
}
func NotAssertedWakerAfterWake(t *testing.T) {
	var w Waker
	var s Sleeper
	s.AddWaker(&w, 0)
	w.Assert()
	s.Fetch(true)
	if w.IsAsserted() {
		t.Fatalf("Consumed waker is reported as asserted")
	}
	if w.Clear() {
		t.Fatalf("Consumed waker is reported as asserted")
	}
}
func AssertedWakerBeforeAdd(t *testing.T) {
	var w Waker
	var s Sleeper
	w.Assert()
	s.AddWaker(&w, 0)
	if _, ok := s.Fetch(false); !ok {
		t.Fatalf("Fetch failed even though asserted waker was added")
	}
}
func ClearedWaker(t *testing.T) {
	var w Waker
	w.Assert()
	w.Clear()
	if w.IsAsserted() {
		t.Fatalf("Cleared waker is reported as asserted")
	}
	if w.Clear() {
		t.Fatalf("Cleared waker is reported as asserted")
	}
}
func ClearedWakerWithSleeper(t *testing.T) {
	var w Waker
	var s Sleeper
	s.AddWaker(&w, 0)
	w.Clear()
	if w.IsAsserted() {
		t.Fatalf("Cleared waker is reported as asserted")
	}
	if w.Clear() {
		t.Fatalf("Cleared waker is reported as asserted")
	}
}
func ClearedWakerAssertedWithSleeper(t *testing.T) {
	var w Waker
	var s Sleeper
	s.AddWaker(&w, 0)
	w.Assert()
	w.Clear()
	if w.IsAsserted() {
		t.Fatalf("Cleared waker is reported as asserted")
	}
	if w.Clear() {
		t.Fatalf("Cleared waker is reported as asserted")
	}
}
func TestBlock(t *testing.T) {
	var w Waker
	var s Sleeper
	s.AddWaker(&w, 0)
	before := time.Now()
	go func() {
		time.Sleep(1 * time.Second)
		w.Assert()
	}()
	if _, ok := s.Fetch(true); !ok {
		t.Fatalf("Fetch failed unexpectedly")
	}
	if d := time.Now().Sub(before); d < 500*time.Millisecond {
		t.Fatalf("Duration was too short: %v", d)
	}
	w.Assert()
	if _, ok := s.Fetch(true); !ok {
		t.Fatalf("Fetch failed unexpectedly")
	}
	w.Assert()
	w.Clear()
	before = time.Now()
	go func() {
		time.Sleep(1 * time.Second)
		w.Assert()
	}()
	if _, ok := s.Fetch(true); !ok {
		t.Fatalf("Fetch failed unexpectedly")
	}
	if d := time.Now().Sub(before); d < 500*time.Millisecond {
		t.Fatalf("Duration was too short: %v", d)
	}
}
func TestNonBlock(t *testing.T) {
	var w Waker
	var s Sleeper
	if _, ok := s.Fetch(false); ok {
		t.Fatalf("Fetch succeeded when there is no waker")
	}
	s.AddWaker(&w, 0)
	if _, ok := s.Fetch(false); ok {
		t.Fatalf("Fetch succeeded when waker was not asserted")
	}
	w.Assert()
	w.Clear()
	if _, ok := s.Fetch(false); ok {
		t.Fatalf("Fetch succeeded when waker was not asserted anymore")
	}
	w.Assert()
	if _, ok := s.Fetch(false); !ok {
		t.Fatalf("Fetch failed even though waker was asserted")
	}
	if _, ok := s.Fetch(false); ok {
		t.Fatalf("Fetch succeeded when waker had been consumed")
	}
}
func TestMultiple(t *testing.T) {
	s := Sleeper{}
	w1 := Waker{}
	w2 := Waker{}
	s.AddWaker(&w1, 0)
	s.AddWaker(&w2, 1)
	w1.Assert()
	w2.Assert()
	v, ok := s.Fetch(false)
	if !ok {
		t.Fatalf("Fetch failed when there are asserted wakers")
	}
	if v != 0 && v != 1 {
		t.Fatalf("Unexpected waker id: %v", v)
	}
	want := 1 - v
	v, ok = s.Fetch(false)
	if !ok {
		t.Fatalf("Fetch failed when there is an asserted waker")
	}
	if v != want {
		t.Fatalf("Unexpected waker id, got %v, want %v", v, want)
	}
}
func TestDoneFunction(t *testing.T) {
	s := Sleeper{}
	s.Done()
	for n := 1; n < 20; n++ {
		s := Sleeper{}
		w := make([]Waker, n)
		for j := 0; j < n; j++ {
			s.AddWaker(&w[j], j)
		}
		s.Done()
	}
	for n := 1; n < 20; n++ {
		for i := 0; i < n; i++ {
			s := Sleeper{}
			w := make([]Waker, n)
			for j := 0; j < n; j++ {
				s.AddWaker(&w[j], j)
			}
			w[i].Assert()
			s.Done()
		}
	}
	for n := 1; n < 20; n++ {
		for i := 0; i < n; i++ {
			s := Sleeper{}
			w := make([]Waker, n)
			for j := 0; j < n; j++ {
				s.AddWaker(&w[j], j)
			}
			w[i].Assert()
			w[i].Clear()
			s.Done()
		}
	}
	for n := 1; n < 20; n++ {
		for iters := 0; iters < 1000; iters++ {
			s := Sleeper{}
			w := make([]Waker, n)
			for j := 0; j < n; j++ {
				s.AddWaker(&w[j], j)
			}
			asserted := rand.Int() % (n + 1)
			for j := 0; j < asserted; j++ {
				w[rand.Int()%n].Assert()
			}
			s.Done()
		}
	}
}
func TestRace(t *testing.T) {
	const wakers = 100
	const wakeRequests = 10000
	counts := make([]int, wakers)
	w := make([]Waker, wakers)
	s := Sleeper{}
	for i := range w {
		s.AddWaker(&w[i], i)
		go func(w *Waker) {
			n := 0
			for n < wakeRequests {
				if !w.IsAsserted() {
					w.Assert()
					n++
				} else {
					runtime.Gosched()
				}
			}
		}(&w[i])
	}
	for i := 0; i < wakers*wakeRequests; i++ {
		v, _ := s.Fetch(true)
		counts[v]++
	}
	for i, v := range counts {
		if v != wakeRequests {
			t.Errorf("Waker %v only got %v wakes", i, v)
		}
	}
}
func BenchmarkSleeperMultiSelect(b *testing.B) {
	const count = 4
	s := Sleeper{}
	w := make([]Waker, count)
	for i := range w {
		s.AddWaker(&w[i], i)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		w[count-1].Assert()
		s.Fetch(true)
	}
}
func BenchmarkGoMultiSelect(b *testing.B) {
	const count = 4
	ch := make([]chan struct{}, count)
	for i := range ch {
		ch[i] = make(chan struct{}, 1)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ch[count-1] <- struct{}{}
		select {
		case <-ch[0]:
		case <-ch[1]:
		case <-ch[2]:
		case <-ch[3]:
		}
	}
}
func BenchmarkSleeperSingleSelect(b *testing.B) {
	s := Sleeper{}
	w := Waker{}
	s.AddWaker(&w, 0)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		w.Assert()
		s.Fetch(true)
	}
}
func BenchmarkGoSingleSelect(b *testing.B) {
	ch := make(chan struct{}, 1)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ch <- struct{}{}
		<-ch
	}
}
func BenchmarkSleeperAssertNonWaiting(b *testing.B) {
	w := Waker{}
	w.Assert()
	for i := 0; i < b.N; i++ {
		w.Assert()
	}
}
func BenchmarkGoAssertNonWaiting(b *testing.B) {
	ch := make(chan struct{}, 1)
	ch <- struct{}{}
	for i := 0; i < b.N; i++ {
		select {
		case ch <- struct{}{}:
		default:
		}
	}
}