Skip to content

Commit e69260f

Browse files
committed
Test com.CopyFirst()
1 parent 53ae704 commit e69260f

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

com/com_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com
22

33
import (
4+
"context"
45
"github.com/stretchr/testify/require"
56
"io"
67
"testing"
@@ -48,3 +49,107 @@ func TestWaitAsync(t *testing.T) {
4849
})
4950
}
5051
}
52+
53+
func TestCopyFirst(t *testing.T) {
54+
subtests := []struct {
55+
name string
56+
io []string
57+
error bool
58+
}{
59+
{"empty", nil, true},
60+
{"one", []string{"a"}, false},
61+
{"two", []string{"a", "b"}, false},
62+
{"three", []string{"a", "b", "c"}, false},
63+
}
64+
65+
latencies := []struct {
66+
name string
67+
latency time.Duration
68+
}{
69+
{"instantly", 0},
70+
{"1us", time.Microsecond},
71+
{"20ms", 20 * time.Millisecond},
72+
}
73+
74+
for _, st := range subtests {
75+
t.Run(st.name, func(t *testing.T) {
76+
for _, l := range latencies {
77+
t.Run(l.name, func(t *testing.T) {
78+
ctx, cancel := context.WithCancel(context.Background())
79+
defer cancel()
80+
81+
ch := make(chan string)
82+
go func() {
83+
defer close(ch)
84+
85+
for _, v := range st.io {
86+
if l.latency > 0 {
87+
select {
88+
case <-time.After(l.latency):
89+
case <-ctx.Done():
90+
return
91+
}
92+
}
93+
94+
select {
95+
case ch <- v:
96+
case <-ctx.Done():
97+
return
98+
}
99+
}
100+
}()
101+
102+
first, forward, err := CopyFirst(ctx, ch)
103+
if st.error {
104+
require.Error(t, err)
105+
require.Nil(t, forward, "forward should be nil")
106+
return
107+
}
108+
109+
require.NoError(t, err)
110+
require.NotNil(t, forward, "forward should not be nil")
111+
112+
expected := ""
113+
if len(st.io) > 0 {
114+
expected = st.io[0]
115+
}
116+
117+
require.Equal(t, expected, first, "first should be the first element")
118+
119+
for _, expected := range st.io {
120+
select {
121+
case actual, ok := <-forward:
122+
if !ok {
123+
require.Fail(t, "channel should not be closed")
124+
}
125+
126+
require.Equal(t, expected, actual, "forwarded element should match")
127+
case <-time.After(time.Second):
128+
require.Fail(t, "channel should not block")
129+
}
130+
}
131+
132+
select {
133+
case _, ok := <-forward:
134+
if ok {
135+
require.Fail(t, "channel should be closed")
136+
}
137+
case <-time.After(time.Second):
138+
require.Fail(t, "channel should not block")
139+
}
140+
})
141+
}
142+
})
143+
}
144+
145+
t.Run("cancel-ctx", func(t *testing.T) {
146+
ctx, cancel := context.WithCancel(context.Background())
147+
cancel()
148+
149+
first, forward, err := CopyFirst(ctx, make(chan int))
150+
151+
require.Error(t, err)
152+
require.Nil(t, forward)
153+
require.Empty(t, first)
154+
})
155+
}

0 commit comments

Comments
 (0)