blob: 7410f51692eb64975e0f12b83cd33e17c6fbcf22 [file] [log] [blame]
// Copyright 2020 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 chans
import (
"context"
"runtime"
"sort"
"sync"
"testing"
"time"
"slices"
)
func TestReadAll(t *testing.T) {
c := make(chan int)
go func() {
c <- 4
c <- 2
c <- 5
close(c)
}()
got := ReadAll(context.Background(), c)
want := []int{4, 2, 5}
if !slices.Equal(got, want) {
t.Errorf("ReadAll returned %v, want %v", got, want)
}
}
func TestMerge(t *testing.T) {
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 := ReadAll(ctx, Merge(ctx, c1, c2))
sort.Ints(got)
want := []int{1, 2, 3, 4, 5, 6}
if !slices.Equal(got, want) {
t.Errorf("Merge returned %v, want %v", got, want)
}
}
func TestFilter(t *testing.T) {
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 := ReadAll(ctx, Filter(ctx, c, even))
want := []int{2}
if !slices.Equal(got, want) {
t.Errorf("Filter returned %v, want %v", got, want)
}
}
func TestSink(t *testing.T) {
c := Sink[int](context.Background())
after := time.NewTimer(time.Minute)
defer after.Stop()
send := func(v int) {
select {
case c <- v:
case <-after.C:
t.Error("timed out sending to Sink")
}
}
send(1)
send(2)
send(3)
close(c)
}
func TestExclusive(t *testing.T) {
val := 0
ex := 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 {
t.Errorf("after Acquire/Release loop got %d, want 20", val)
}
}
func TestExclusiveTry(t *testing.T) {
s := ""
ex := MakeExclusive(&s)
p, ok := ex.TryAcquire()
if !ok {
t.Fatalf("TryAcquire failed")
}
*p = "a"
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
_, ok := ex.TryAcquire()
if ok {
t.Errorf("TryAcquire succeeded unexpectedly")
}
}()
wg.Wait()
ex.Release(p)
p, ok = ex.TryAcquire()
if !ok {
t.Errorf("TryAcquire failed")
}
}
func TestRanger(t *testing.T) {
s, r := Ranger[int]()
ctx := context.Background()
go func() {
// Receive one value then exit.
v, ok := r.Next(ctx)
if !ok {
t.Errorf("did not receive any values")
} else if v != 1 {
t.Errorf("received %d, want 1", v)
}
}()
c1 := make(chan bool)
c2 := make(chan bool)
go func() {
defer close(c2)
if !s.Send(ctx, 1) {
t.Errorf("Send failed unexpectedly")
}
close(c1)
if s.Send(ctx, 2) {
t.Errorf("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):
t.Error("Ranger Send should have failed, but timed out")
}
}