// Copyright 2021 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 main import ( "./a" "context" "fmt" "runtime" "sort" "sync" "time" ) func TestReadAll() { c := make(chan int) go func() { c <- 4 c <- 2 c <- 5 close(c) }() got := a.ReadAll(context.Background(), c) want := []int{4, 2, 5} if !a.SliceEqual(got, want) { panic(fmt.Sprintf("ReadAll returned %v, want %v", got, want)) } } func TestMerge() { c1 := make(chan int) c2 := make(chan int) go func() { c1 <- 1 c1 <- 3 c1 <- 5 close(c1) }() go func() { c2 <- 2 c2 <- 4 c2 <- 6 close(c2) }() ctx := context.Background() got := a.ReadAll(ctx, a.Merge(ctx, c1, c2)) sort.Ints(got) want := []int{1, 2, 3, 4, 5, 6} if !a.SliceEqual(got, want) { panic(fmt.Sprintf("Merge returned %v, want %v", got, want)) } } func TestFilter() { c := make(chan int) go func() { c <- 1 c <- 2 c <- 3 close(c) }() even := func(i int) bool { return i%2 == 0 } ctx := context.Background() got := a.ReadAll(ctx, a.Filter(ctx, c, even)) want := []int{2} if !a.SliceEqual(got, want) { panic(fmt.Sprintf("Filter returned %v, want %v", got, want)) } } func TestSink() { c := a.Sink[int](context.Background()) after := time.NewTimer(time.Minute) defer after.Stop() send := func(v int) { select { case c <- v: case <-after.C: panic("timed out sending to Sink") } } send(1) send(2) send(3) close(c) } func TestExclusive() { val := 0 ex := a.MakeExclusive(&val) var wg sync.WaitGroup f := func() { defer wg.Done() for i := 0; i < 10; i++ { p := ex.Acquire() (*p)++ ex.Release(p) } } wg.Add(2) go f() go f() wg.Wait() if val != 20 { panic(fmt.Sprintf("after Acquire/Release loop got %d, want 20", val)) } } func TestExclusiveTry() { s := "" ex := a.MakeExclusive(&s) p, ok := ex.TryAcquire() if !ok { panic("TryAcquire failed") } *p = "a" var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() _, ok := ex.TryAcquire() if ok { panic(fmt.Sprintf("TryAcquire succeeded unexpectedly")) } }() wg.Wait() ex.Release(p) p, ok = ex.TryAcquire() if !ok { panic(fmt.Sprintf("TryAcquire failed")) } } func TestRanger() { s, r := a.Ranger[int]() ctx := context.Background() go func() { // Receive one value then exit. v, ok := r.Next(ctx) if !ok { panic(fmt.Sprintf("did not receive any values")) } else if v != 1 { panic(fmt.Sprintf("received %d, want 1", v)) } }() c1 := make(chan bool) c2 := make(chan bool) go func() { defer close(c2) if !s.Send(ctx, 1) { panic(fmt.Sprintf("Send failed unexpectedly")) } close(c1) if s.Send(ctx, 2) { panic(fmt.Sprintf("Send succeeded unexpectedly")) } }() <-c1 // Force a garbage collection to try to get the finalizers to run. runtime.GC() select { case <-c2: case <-time.After(time.Minute): panic("Ranger Send should have failed, but timed out") } } func main() { TestReadAll() TestMerge() TestFilter() TestSink() TestExclusive() TestExclusiveTry() TestRanger() }