Skip to content
File

Blob: util/promise/promise_test.go

go128 lines
1package promise
2 
3import (
4 "context"
5 "fmt"
6 "testing"
7 "time"
8 
9 "github.com/stretchr/testify/require"
10 "go.uber.org/goleak"
11)
12 
13func TestMain(m *testing.M) {
14 goleak.VerifyTestMain(m)
15}
16 
17func TestConcurrent(t *testing.T) {
18 as := require.New(t)
19 
20 wait := []time.Duration{
21 time.Millisecond * 500,
22 time.Millisecond * 1000,
23 time.Millisecond * 1500,
24 }
25 
26 jobs := make([]func(context.Context) (time.Duration, error), 0)
27 for _, d := range wait {
28 jobs = append(jobs, func(ctx context.Context) (time.Duration, error) {
29 time.Sleep(d)
30 return d, nil
31 })
32 }
33 
34 jobCtx, jobCancel := context.WithTimeout(context.Background(), time.Second*3)
35 defer jobCancel()
36 
37 start := time.Now()
38 results, errors := All(jobCtx, jobs...)
39 end := time.Now()
40 
41 for i, err := range errors {
42 as.NoError(err)
43 as.Equal(results[i], wait[i])
44 }
45 
46 as.Less(end.Sub(start), wait[0]+wait[1]+wait[2])
47}
48 
49func TestConcurrentError(t *testing.T) {
50 as := require.New(t)
51 
52 wait := []time.Duration{
53 time.Millisecond * 500,
54 time.Millisecond * 1000,
55 time.Millisecond * 1500,
56 }
57 
58 jobs := make([]func(context.Context) (time.Duration, error), 0)
59 for i, d := range wait {
60 jobs = append(jobs, func(ctx context.Context) (time.Duration, error) {
61 time.Sleep(d)
62 if i == 1 {
63 return d, fmt.Errorf("error")
64 }
65 return d, nil
66 })
67 }
68 
69 jobCtx, jobCancel := context.WithTimeout(context.Background(), time.Second*3)
70 defer jobCancel()
71 
72 start := time.Now()
73 results, errors := All(jobCtx, jobs...)
74 end := time.Now()
75 
76 for i, err := range errors {
77 if i == 1 {
78 as.Error(err)
79 as.Equal(results[i], time.Duration(0))
80 } else {
81 as.NoError(err)
82 as.Equal(results[i], wait[i])
83 }
84 }
85 
86 as.Less(end.Sub(start), wait[0]+wait[1]+wait[2])
87}
88 
89func TestWaitReturn(t *testing.T) {
90 as := require.New(t)
91 
92 wait := []time.Duration{
93 time.Millisecond * 500,
94 time.Millisecond * 1000,
95 time.Millisecond * 1500,
96 }
97 
98 jobs := make([]func(context.Context) (time.Duration, error), 0)
99 for _, d := range wait {
100 jobs = append(jobs, func(ctx context.Context) (time.Duration, error) {
101 select {
102 case <-ctx.Done():
103 return time.Duration(0), ctx.Err()
104 case <-time.After(d):
105 return d, nil
106 }
107 })
108 }
109 
110 jobCtx, jobCancel := context.WithTimeout(context.Background(), time.Millisecond*750) // note that we are intentionally time out fast
111 defer jobCancel()
112 
113 start := time.Now()
114 results, errors := All(jobCtx, jobs...)
115 end := time.Now()
116 
117 for i, err := range errors {
118 if results[i] == time.Duration(0) {
119 as.ErrorIs(err, context.DeadlineExceeded)
120 } else {
121 as.NoError(err)
122 as.Equal(results[i], wait[i])
123 }
124 }
125 
126 as.Less(end.Sub(start), wait[0]+wait[1]+wait[2])
127}