Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: go/src/infra/monitoring/looper/looper_test.go

Issue 1896213002: Fixed flaky go tests in looper (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Use separate counter in advancing timer for thread safety Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 package looper 1 package looper
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "testing" 5 "testing"
6 "time" 6 "time"
7 7
8 "github.com/luci/luci-go/common/clock"
8 "github.com/luci/luci-go/common/clock/testclock" 9 "github.com/luci/luci-go/common/clock/testclock"
9 "golang.org/x/net/context" 10 "golang.org/x/net/context"
10 ) 11 )
11 12
12 // Run f once, then cancel. 13 // Run f once, then cancel.
13 func TestLoopOnce(t *testing.T) { 14 func TestLoopOnce(t *testing.T) {
14 » ctx := context.Background() 15 » ctx, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
15 » _, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
16 16
17 nCalls := 0 17 nCalls := 0
18 called := make(chan interface{}, 1)
19 f := func(ctx context.Context) error { 18 f := func(ctx context.Context) error {
20 nCalls++ 19 nCalls++
21 called <- nil
22 return nil 20 return nil
23 } 21 }
24 22
25 ctx, cancel := context.WithCancel(ctx) 23 ctx, cancel := context.WithCancel(ctx)
26 » done := make(chan struct{}) 24 » c.SetTimerCallback(func(d time.Duration, t clock.Timer) {
27 » go func() { 25 » » cancel()
28 » » res := Run(ctx, f, 1*time.Second, 1, c) 26 » })
29 » » if !res.Success { 27 » res := Run(ctx, f, 1*time.Second, 1, c)
30 » » » t.Errorf("Should have succeeded.") 28 » if !res.Success {
31 » » } 29 » » t.Errorf("Should have succeeded.")
32 » » if nCalls != 1 { 30 » }
33 » » » t.Errorf("Want %d got %d", 1, nCalls) 31 » if nCalls != 1 {
34 » » } 32 » » t.Errorf("Want %d got %d", 1, nCalls)
35 » » close(done) 33 » }
36 » }()
37
38 » <-called
39 » cancel()
40 » <-done
41 } 34 }
42 35
43 // Run for 5s, every 1s. Should run 5 times before returning Success. 36 // Run for 5s, every 1s. Should run 5 times before returning Success.
44 func TestLoopMultiple(t *testing.T) { 37 func TestLoopMultiple(t *testing.T) {
45 » ctx := context.Background() 38 » ctx, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
46 » _, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
47 39
48 nCalls := 0 40 nCalls := 0
49 called := make(chan interface{}, 1)
50 f := func(ctx context.Context) error { 41 f := func(ctx context.Context) error {
51 nCalls++ 42 nCalls++
52 called <- nil
53 return nil 43 return nil
54 } 44 }
55 45
56 ctx, cancel := context.WithCancel(ctx) 46 ctx, cancel := context.WithCancel(ctx)
57 » done := make(chan struct{}) 47 » i := 0
58 48 » c.SetTimerCallback(func(d time.Duration, t clock.Timer) {
59 » go func() { 49 » » if i++; i >= 5 {
60 » » res := Run(ctx, f, 1*time.Second, 1, c) 50 » » » cancel()
61 » » if !res.Success {
62 » » » t.Errorf("Should have succeeded.")
63 } 51 }
64 » » if nCalls != 5 { 52 » » c.Add(d)
65 » » » t.Errorf("Want %d got %d", 5, nCalls) 53 » })
66 » » } 54 » res := Run(ctx, f, 1*time.Second, 1, c)
67 » » close(done) 55 » if !res.Success {
68 » }() 56 » » t.Errorf("Should have succeeded.")
69
70 » // Read off the rest of the timer ticks.
71 » for i := 0; i < 5; i++ {
72 » » c.Add(1 * time.Second)
73 » » <-called
74 } 57 }
75 58 » if nCalls != 5 {
76 » cancel() 59 » » t.Errorf("Want %d got %d", 5, nCalls)
77 » <-done 60 » }
78 } 61 }
79 62
80 // Run for 10s, every 1s. Every other task takes 1.5s to run. 3 + 3*1.5? 63 // Run for 10s, every 1s. Every other task takes 1.5s to run. 3 + 3*1.5?
81 func TestLoopOverrunSome(t *testing.T) { 64 func TestLoopOverrunSome(t *testing.T) {
82 » // TODO(vadimsh): This test is flaky. Sometimes fails with 65 » ctx, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
83 » // Want 5 Overruns got 6.
84 » ctx := context.Background()
85 » _, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
86 66
87 nCalls := 0 67 nCalls := 0
88 called := make(chan interface{}, 1)
89 f := func(ctx context.Context) error { 68 f := func(ctx context.Context) error {
90 if nCalls%2 == 0 { 69 if nCalls%2 == 0 {
91 c.Add(1500 * time.Millisecond) 70 c.Add(1500 * time.Millisecond)
92 } else { 71 } else {
93 c.Add(500 * time.Millisecond) 72 c.Add(500 * time.Millisecond)
94 } 73 }
95 nCalls++ 74 nCalls++
96 called <- nil
97 return nil 75 return nil
98 } 76 }
99 ctx, cancel := context.WithCancel(ctx) 77 ctx, cancel := context.WithCancel(ctx)
78 i := 0
79 c.SetTimerCallback(func(d time.Duration, t clock.Timer) {
80 if i++; i >= 10 {
81 cancel()
82 }
83 c.Add(d)
84 })
100 85
101 » done := make(chan struct{}) 86 » res := Run(ctx, f, 1*time.Second, 3, c)
102 » go func() { 87 » if !res.Success {
103 » » res := Run(ctx, f, 1*time.Second, 3, c) 88 » » t.Errorf("Should have succeeded.")
104 » » if !res.Success {
105 » » » t.Errorf("Should have succeeded.")
106 » » }
107 » » if nCalls != 10 {
108 » » » t.Errorf("Want %d calls got %d", 10, nCalls)
109 » » }
110 » » if res.Errs != 0 {
111 » » » t.Errorf("Want %d Errs got %d", 0, res.Errs)
112 » » }
113 » » if res.Overruns != 5 {
114 » » » t.Errorf("Want %d Overruns got %d", 5, res.Overruns)
115 » » }
116 » » close(done)
117 » }()
118
119 » for i := 0; i < 10; i++ {
120 » » c.Add(1 * time.Second)
121 » » <-called
122 } 89 }
123 » cancel() 90 » if nCalls != 10 {
124 » <-done 91 » » t.Errorf("Want %d calls got %d", 10, nCalls)
92 » }
93 » if res.Errs != 0 {
94 » » t.Errorf("Want %d Errs got %d", 0, res.Errs)
95 » }
96 » if res.Overruns != 5 {
97 » » t.Errorf("Want %d Overruns got %d", 5, res.Overruns)
98 » }
125 } 99 }
126 100
127 func TestLoopOverrunAll(t *testing.T) { 101 func TestLoopOverrunAll(t *testing.T) {
128 » ctx := context.Background() 102 » ctx, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
129 » _, c := testclock.UseTime(ctx, time.Unix(0, 0))
130 103
131 nCalls := 0 104 nCalls := 0
132 called := make(chan interface{}, 1)
133 f := func(ctx context.Context) error { 105 f := func(ctx context.Context) error {
134 if nCalls < 4 { 106 if nCalls < 4 {
135 c.Add(1001 * time.Millisecond) 107 c.Add(1001 * time.Millisecond)
136 } 108 }
137 nCalls++ 109 nCalls++
138 called <- nil
139 return nil 110 return nil
140 } 111 }
141 112
142 ctx, cancel := context.WithCancel(ctx) 113 ctx, cancel := context.WithCancel(ctx)
143 » done := make(chan struct{}) 114 » i := 0
144 » go func() { 115 » c.SetTimerCallback(func(d time.Duration, t clock.Timer) {
145 » » res := Run(ctx, f, 1*time.Second, 3, c) 116 » » if i++; i >= 5 {
146 » » if !res.Success { 117 » » » cancel()
147 » » » t.Errorf("Should have succeeded.")
148 } 118 }
149 » » if nCalls != 5 { 119 » » c.Add(d)
150 » » » t.Errorf("Want %d calls got %d", 5, nCalls) 120 » })
151 » » } 121 » res := Run(ctx, f, 1*time.Second, 3, c)
152 » » if res.Errs != 0 { 122 » if !res.Success {
153 » » » t.Errorf("Want %d Errs got %d", 0, res.Errs) 123 » » t.Errorf("Should have succeeded.")
154 » » }
155 » » if res.Overruns != 4 {
156 » » » t.Errorf("Want %d Overruns got %d", 4, res.Overruns)
157 » » }
158 » » close(done)
159 » }()
160
161 » for i := 0; i < 5; i++ {
162 » » c.Add(1 * time.Second)
163 » » <-called
164 } 124 }
165 125 » if nCalls != 5 {
166 » cancel() 126 » » t.Errorf("Want %d calls got %d", 5, nCalls)
167 » <-done 127 » }
128 » if res.Errs != 0 {
129 » » t.Errorf("Want %d Errs got %d", 0, res.Errs)
130 » }
131 » if res.Overruns != 4 {
132 » » t.Errorf("Want %d Overruns got %d", 4, res.Overruns)
133 » }
168 } 134 }
169 135
170 // Run for 10s, every 1s. Return errors on 2nd, 4th, 6th, 7th and 8th calls. 136 // Run for 10s, every 1s. Return errors on 2nd, 4th, 6th, 7th and 8th calls.
171 func TestLoopMaxErrors(t *testing.T) { 137 func TestLoopMaxErrors(t *testing.T) {
172 » ctx := context.Background() 138 » ctx, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
173 » _, c := testclock.UseTime(context.Background(), time.Unix(0, 0))
174 139
175 nCalls := 0 140 nCalls := 0
176 called := make(chan interface{}, 1)
177 f := func(ctx context.Context) error { 141 f := func(ctx context.Context) error {
178 nCalls++ 142 nCalls++
179 called <- nil
180 if nCalls%2 == 0 || nCalls > 5 { 143 if nCalls%2 == 0 || nCalls > 5 {
181 return fmt.Errorf("this is an error: %d", nCalls) 144 return fmt.Errorf("this is an error: %d", nCalls)
182 } 145 }
183 return nil 146 return nil
184 } 147 }
185 148
186 ctx, cancel := context.WithCancel(ctx) 149 ctx, cancel := context.WithCancel(ctx)
187 » done := make(chan struct{}) 150 » i := 0
188 » go func() { 151 » c.SetTimerCallback(func(d time.Duration, t clock.Timer) {
189 » » res := Run(ctx, f, 1*time.Second, 3, c) 152 » » if i++; i >= 8 {
190 » » if res.Success { 153 » » » cancel()
191 » » » t.Errorf("Should have failed.")
192 } 154 }
193 » » if nCalls != 8 { 155 » » c.Add(d)
194 » » » t.Errorf("Want %d calls got %d", 6, nCalls) 156 » })
195 » » } 157 » res := Run(ctx, f, 1*time.Second, 3, c)
196 » » if res.Errs != 5 { 158 » if res.Success {
197 » » » t.Errorf("Want %d Errs got %d", 4, res.Errs) 159 » » t.Errorf("Should have failed.")
198 » » }
199 » » close(done)
200 » }()
201
202 » for i := 0; i < 8; i++ {
203 » » c.Add(1 * time.Second)
204 » » <-called
205 } 160 }
206 161 » if nCalls != 8 {
207 » cancel() 162 » » t.Errorf("Want %d calls got %d", 6, nCalls)
208 » <-done 163 » }
164 » if res.Errs != 5 {
165 » » t.Errorf("Want %d Errs got %d", 4, res.Errs)
166 » }
209 } 167 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698