OLD | NEW |
1 // Copyright 2012, 2013 Canonical Ltd. | 1 // Copyright 2012, 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package worker_test | 4 package worker_test |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 "sync" | 8 "sync" |
9 "time" | 9 "time" |
10 | 10 |
11 gc "launchpad.net/gocheck" | 11 gc "launchpad.net/gocheck" |
12 "launchpad.net/tomb" | 12 "launchpad.net/tomb" |
13 | 13 |
14 "launchpad.net/juju-core/state/api" | 14 "launchpad.net/juju-core/state/api" |
15 "launchpad.net/juju-core/state/watcher" | 15 "launchpad.net/juju-core/state/watcher" |
16 coretesting "launchpad.net/juju-core/testing" | 16 coretesting "launchpad.net/juju-core/testing" |
17 jc "launchpad.net/juju-core/testing/checkers" | 17 jc "launchpad.net/juju-core/testing/checkers" |
18 "launchpad.net/juju-core/worker" | 18 "launchpad.net/juju-core/worker" |
19 ) | 19 ) |
20 | 20 |
21 type notifyWorkerSuite struct { | 21 type notifyWorkerSuite struct { |
22 coretesting.LoggingSuite | 22 coretesting.LoggingSuite |
23 worker worker.NotifyWorker | 23 worker worker.NotifyWorker |
24 » actor *actionsHandler | 24 » actor *notifyHandler |
25 } | 25 } |
26 | 26 |
27 var _ = gc.Suite(¬ifyWorkerSuite{}) | 27 var _ = gc.Suite(¬ifyWorkerSuite{}) |
28 | 28 |
29 func (s *notifyWorkerSuite) SetUpTest(c *gc.C) { | 29 func (s *notifyWorkerSuite) SetUpTest(c *gc.C) { |
30 s.LoggingSuite.SetUpTest(c) | 30 s.LoggingSuite.SetUpTest(c) |
31 » s.actor = &actionsHandler{ | 31 » s.actor = ¬ifyHandler{ |
32 actions: nil, | 32 actions: nil, |
33 handled: make(chan struct{}, 1), | 33 handled: make(chan struct{}, 1), |
34 » » description: "test action handler", | 34 » » description: "test notify handler", |
35 » » watcher: &TestWatcher{ | 35 » » watcher: &testNotifyWatcher{ |
36 changes: make(chan struct{}), | 36 changes: make(chan struct{}), |
37 }, | 37 }, |
38 } | 38 } |
39 s.worker = worker.NewNotifyWorker(s.actor) | 39 s.worker = worker.NewNotifyWorker(s.actor) |
40 } | 40 } |
41 | 41 |
42 func (s *notifyWorkerSuite) TearDownTest(c *gc.C) { | 42 func (s *notifyWorkerSuite) TearDownTest(c *gc.C) { |
43 s.stopWorker(c) | 43 s.stopWorker(c) |
44 s.LoggingSuite.TearDownTest(c) | 44 s.LoggingSuite.TearDownTest(c) |
45 } | 45 } |
46 | 46 |
47 type actionsHandler struct { | 47 type notifyHandler struct { |
48 actions []string | 48 actions []string |
49 mu sync.Mutex | 49 mu sync.Mutex |
50 // Signal handled when we get a handle() call | 50 // Signal handled when we get a handle() call |
51 handled chan struct{} | 51 handled chan struct{} |
52 setupError error | 52 setupError error |
53 teardownError error | 53 teardownError error |
54 handlerError error | 54 handlerError error |
55 » watcher *TestWatcher | 55 » watcher *testNotifyWatcher |
56 description string | 56 description string |
57 } | 57 } |
58 | 58 |
59 func (a *actionsHandler) SetUp() (api.NotifyWatcher, error) { | 59 var _ worker.NotifyWatchHandler = (*notifyHandler)(nil) |
60 » a.mu.Lock() | 60 |
61 » defer a.mu.Unlock() | 61 func (nh *notifyHandler) SetUp() (api.NotifyWatcher, error) { |
62 » a.actions = append(a.actions, "setup") | 62 » nh.mu.Lock() |
63 » if a.watcher == nil { | 63 » defer nh.mu.Unlock() |
64 » » return nil, a.setupError | 64 » nh.actions = append(nh.actions, "setup") |
| 65 » if nh.watcher == nil { |
| 66 » » return nil, nh.setupError |
65 } | 67 } |
66 » return a.watcher, a.setupError | 68 » return nh.watcher, nh.setupError |
67 } | 69 } |
68 | 70 |
69 func (a *actionsHandler) TearDown() error { | 71 func (nh *notifyHandler) TearDown() error { |
70 » a.mu.Lock() | 72 » nh.mu.Lock() |
71 » defer a.mu.Unlock() | 73 » defer nh.mu.Unlock() |
72 » a.actions = append(a.actions, "teardown") | 74 » nh.actions = append(nh.actions, "teardown") |
73 » if a.handled != nil { | 75 » if nh.handled != nil { |
74 » » close(a.handled) | 76 » » close(nh.handled) |
75 } | 77 } |
76 » return a.teardownError | 78 » return nh.teardownError |
77 } | 79 } |
78 | 80 |
79 func (a *actionsHandler) Handle() error { | 81 func (nh *notifyHandler) Handle() error { |
80 » a.mu.Lock() | 82 » nh.mu.Lock() |
81 » defer a.mu.Unlock() | 83 » defer nh.mu.Unlock() |
82 » a.actions = append(a.actions, "handler") | 84 » nh.actions = append(nh.actions, "handler") |
83 » if a.handled != nil { | 85 » if nh.handled != nil { |
84 // Unlock while we are waiting for the send | 86 // Unlock while we are waiting for the send |
85 » » a.mu.Unlock() | 87 » » nh.mu.Unlock() |
86 » » a.handled <- struct{}{} | 88 » » nh.handled <- struct{}{} |
87 » » a.mu.Lock() | 89 » » nh.mu.Lock() |
88 } | 90 } |
89 » return a.handlerError | 91 » return nh.handlerError |
90 } | 92 } |
91 | 93 |
92 func (a *actionsHandler) String() string { | 94 func (nh *notifyHandler) String() string { |
93 » return a.description | 95 » return nh.description |
94 } | 96 } |
95 | 97 |
96 func (a *actionsHandler) CheckActions(c *gc.C, actions ...string) { | 98 func (nh *notifyHandler) CheckActions(c *gc.C, actions ...string) { |
97 » a.mu.Lock() | 99 » nh.mu.Lock() |
98 » defer a.mu.Unlock() | 100 » defer nh.mu.Unlock() |
99 » c.Check(a.actions, gc.DeepEquals, actions) | 101 » c.Check(nh.actions, gc.DeepEquals, actions) |
100 } | 102 } |
101 | 103 |
102 // During teardown we try to stop the worker, but don't hang the test suite if | 104 // During teardown we try to stop the worker, but don't hang the test suite if |
103 // Stop never returns | 105 // Stop never returns |
104 func (s *notifyWorkerSuite) stopWorker(c *gc.C) { | 106 func (s *notifyWorkerSuite) stopWorker(c *gc.C) { |
105 if s.worker == nil { | 107 if s.worker == nil { |
106 return | 108 return |
107 } | 109 } |
108 done := make(chan error) | 110 done := make(chan error) |
109 go func() { | 111 go func() { |
110 done <- s.worker.Stop() | 112 done <- s.worker.Stop() |
111 }() | 113 }() |
112 err := waitForTimeout(c, done, coretesting.LongWait) | 114 err := waitForTimeout(c, done, coretesting.LongWait) |
113 c.Check(err, gc.IsNil) | 115 c.Check(err, gc.IsNil) |
114 s.actor = nil | 116 s.actor = nil |
115 s.worker = nil | 117 s.worker = nil |
116 } | 118 } |
117 | 119 |
118 type TestWatcher struct { | 120 type testNotifyWatcher struct { |
119 mu sync.Mutex | 121 mu sync.Mutex |
120 changes chan struct{} | 122 changes chan struct{} |
121 action chan struct{} | |
122 stopped bool | 123 stopped bool |
123 stopError error | 124 stopError error |
124 } | 125 } |
125 | 126 |
126 func (tw *TestWatcher) Changes() <-chan struct{} { | 127 var _ api.NotifyWatcher = (*testNotifyWatcher)(nil) |
127 » return tw.changes | 128 |
| 129 func (tnw *testNotifyWatcher) Changes() <-chan struct{} { |
| 130 » return tnw.changes |
128 } | 131 } |
129 | 132 |
130 func (tw *TestWatcher) Err() error { | 133 func (tnw *testNotifyWatcher) Err() error { |
131 » return tw.stopError | 134 » return tnw.stopError |
132 } | 135 } |
133 | 136 |
134 func (tw *TestWatcher) Stop() error { | 137 func (tnw *testNotifyWatcher) Stop() error { |
135 » tw.mu.Lock() | 138 » tnw.mu.Lock() |
136 » defer tw.mu.Unlock() | 139 » defer tnw.mu.Unlock() |
137 » if !tw.stopped { | 140 » if !tnw.stopped { |
138 » » close(tw.changes) | 141 » » close(tnw.changes) |
139 } | 142 } |
140 » tw.stopped = true | 143 » tnw.stopped = true |
141 » return tw.stopError | 144 » return tnw.stopError |
142 } | 145 } |
143 | 146 |
144 func (tw *TestWatcher) SetStopError(err error) { | 147 func (tnw *testNotifyWatcher) SetStopError(err error) { |
145 » tw.mu.Lock() | 148 » tnw.mu.Lock() |
146 » tw.stopError = err | 149 » tnw.stopError = err |
147 » tw.mu.Unlock() | 150 » tnw.mu.Unlock() |
148 } | 151 } |
149 | 152 |
150 func (tw *TestWatcher) TriggerChange(c *gc.C) { | 153 func (tnw *testNotifyWatcher) TriggerChange(c *gc.C) { |
151 select { | 154 select { |
152 » case tw.changes <- struct{}{}: | 155 » case tnw.changes <- struct{}{}: |
153 case <-time.After(coretesting.LongWait): | 156 case <-time.After(coretesting.LongWait): |
154 c.Errorf("Timeout changes triggering change after %s", coretesti
ng.LongWait) | 157 c.Errorf("Timeout changes triggering change after %s", coretesti
ng.LongWait) |
155 } | 158 } |
156 } | 159 } |
157 | 160 |
158 func waitForTimeout(c *gc.C, ch <-chan error, timeout time.Duration) error { | 161 func waitForTimeout(c *gc.C, ch <-chan error, timeout time.Duration) error { |
159 select { | 162 select { |
160 case err := <-ch: | 163 case err := <-ch: |
161 return err | 164 return err |
162 case <-time.After(timeout): | 165 case <-time.After(timeout): |
163 c.Errorf("failed to receive value after %s", timeout) | 166 c.Errorf("failed to receive value after %s", timeout) |
164 } | 167 } |
165 return nil | 168 return nil |
166 } | 169 } |
167 | 170 |
168 func WaitShort(c *gc.C, w worker.NotifyWorker) error { | 171 func waitShort(c *gc.C, w worker.CommonWorker) error { |
169 done := make(chan error) | 172 done := make(chan error) |
170 go func() { | 173 go func() { |
171 done <- w.Wait() | 174 done <- w.Wait() |
172 }() | 175 }() |
173 return waitForTimeout(c, done, coretesting.ShortWait) | 176 return waitForTimeout(c, done, coretesting.ShortWait) |
174 } | 177 } |
175 | 178 |
176 func WaitForHandled(c *gc.C, handled chan struct{}) { | 179 func waitForHandledNotify(c *gc.C, handled chan struct{}) { |
177 select { | 180 select { |
178 case <-handled: | 181 case <-handled: |
179 return | 182 return |
180 case <-time.After(coretesting.LongWait): | 183 case <-time.After(coretesting.LongWait): |
181 c.Errorf("handled failed to signal after %s", coretesting.LongWa
it) | 184 c.Errorf("handled failed to signal after %s", coretesting.LongWa
it) |
182 } | 185 } |
183 } | 186 } |
184 | 187 |
185 func (s *notifyWorkerSuite) TestKill(c *gc.C) { | 188 func (s *notifyWorkerSuite) TestKill(c *gc.C) { |
186 s.worker.Kill() | 189 s.worker.Kill() |
187 » err := WaitShort(c, s.worker) | 190 » err := waitShort(c, s.worker) |
188 c.Assert(err, gc.IsNil) | 191 c.Assert(err, gc.IsNil) |
189 } | 192 } |
190 | 193 |
191 func (s *notifyWorkerSuite) TestStop(c *gc.C) { | 194 func (s *notifyWorkerSuite) TestStop(c *gc.C) { |
192 err := s.worker.Stop() | 195 err := s.worker.Stop() |
193 c.Assert(err, gc.IsNil) | 196 c.Assert(err, gc.IsNil) |
194 // After stop, Wait should return right away | 197 // After stop, Wait should return right away |
195 » err = WaitShort(c, s.worker) | 198 » err = waitShort(c, s.worker) |
196 c.Assert(err, gc.IsNil) | 199 c.Assert(err, gc.IsNil) |
197 } | 200 } |
198 | 201 |
199 func (s *notifyWorkerSuite) TestWait(c *gc.C) { | 202 func (s *notifyWorkerSuite) TestWait(c *gc.C) { |
200 done := make(chan error) | 203 done := make(chan error) |
201 go func() { | 204 go func() { |
202 done <- s.worker.Wait() | 205 done <- s.worker.Wait() |
203 }() | 206 }() |
204 // Wait should not return until we've killed the worker | 207 // Wait should not return until we've killed the worker |
205 select { | 208 select { |
206 case err := <-done: | 209 case err := <-done: |
207 c.Errorf("Wait() didn't wait until we stopped it: %v", err) | 210 c.Errorf("Wait() didn't wait until we stopped it: %v", err) |
208 case <-time.After(coretesting.ShortWait): | 211 case <-time.After(coretesting.ShortWait): |
209 } | 212 } |
210 s.worker.Kill() | 213 s.worker.Kill() |
211 err := waitForTimeout(c, done, coretesting.LongWait) | 214 err := waitForTimeout(c, done, coretesting.LongWait) |
212 c.Assert(err, gc.IsNil) | 215 c.Assert(err, gc.IsNil) |
213 } | 216 } |
214 | 217 |
215 func (s *notifyWorkerSuite) TestStringForwardsHandlerString(c *gc.C) { | 218 func (s *notifyWorkerSuite) TestStringForwardsHandlerString(c *gc.C) { |
216 » c.Check(fmt.Sprint(s.worker), gc.Equals, "test action handler") | 219 » c.Check(fmt.Sprint(s.worker), gc.Equals, "test notify handler") |
217 } | 220 } |
218 | 221 |
219 func (s *notifyWorkerSuite) TestCallSetUpAndTearDown(c *gc.C) { | 222 func (s *notifyWorkerSuite) TestCallSetUpAndTearDown(c *gc.C) { |
220 // After calling NewNotifyWorker, we should have called setup | 223 // After calling NewNotifyWorker, we should have called setup |
221 s.actor.CheckActions(c, "setup") | 224 s.actor.CheckActions(c, "setup") |
222 // If we kill the worker, it should notice, and call teardown | 225 // If we kill the worker, it should notice, and call teardown |
223 s.worker.Kill() | 226 s.worker.Kill() |
224 » err := WaitShort(c, s.worker) | 227 » err := waitShort(c, s.worker) |
225 c.Check(err, gc.IsNil) | 228 c.Check(err, gc.IsNil) |
226 s.actor.CheckActions(c, "setup", "teardown") | 229 s.actor.CheckActions(c, "setup", "teardown") |
227 c.Check(s.actor.watcher.stopped, jc.IsTrue) | 230 c.Check(s.actor.watcher.stopped, jc.IsTrue) |
228 } | 231 } |
229 | 232 |
230 func (s *notifyWorkerSuite) TestChangesTriggerHandler(c *gc.C) { | 233 func (s *notifyWorkerSuite) TestChangesTriggerHandler(c *gc.C) { |
231 s.actor.CheckActions(c, "setup") | 234 s.actor.CheckActions(c, "setup") |
232 s.actor.watcher.TriggerChange(c) | 235 s.actor.watcher.TriggerChange(c) |
233 » WaitForHandled(c, s.actor.handled) | 236 » waitForHandledNotify(c, s.actor.handled) |
234 s.actor.CheckActions(c, "setup", "handler") | 237 s.actor.CheckActions(c, "setup", "handler") |
235 s.actor.watcher.TriggerChange(c) | 238 s.actor.watcher.TriggerChange(c) |
236 » WaitForHandled(c, s.actor.handled) | 239 » waitForHandledNotify(c, s.actor.handled) |
237 s.actor.watcher.TriggerChange(c) | 240 s.actor.watcher.TriggerChange(c) |
238 » WaitForHandled(c, s.actor.handled) | 241 » waitForHandledNotify(c, s.actor.handled) |
239 s.actor.CheckActions(c, "setup", "handler", "handler", "handler") | 242 s.actor.CheckActions(c, "setup", "handler", "handler", "handler") |
240 c.Assert(s.worker.Stop(), gc.IsNil) | 243 c.Assert(s.worker.Stop(), gc.IsNil) |
241 s.actor.CheckActions(c, "setup", "handler", "handler", "handler", "teard
own") | 244 s.actor.CheckActions(c, "setup", "handler", "handler", "handler", "teard
own") |
242 } | 245 } |
243 | 246 |
244 func (s *notifyWorkerSuite) TestSetUpFailureStopsWithTearDown(c *gc.C) { | 247 func (s *notifyWorkerSuite) TestSetUpFailureStopsWithTearDown(c *gc.C) { |
245 // Stop the worker and SetUp again, this time with an error | 248 // Stop the worker and SetUp again, this time with an error |
246 s.stopWorker(c) | 249 s.stopWorker(c) |
247 » actor := &actionsHandler{ | 250 » actor := ¬ifyHandler{ |
248 actions: nil, | 251 actions: nil, |
249 handled: make(chan struct{}, 1), | 252 handled: make(chan struct{}, 1), |
250 setupError: fmt.Errorf("my special error"), | 253 setupError: fmt.Errorf("my special error"), |
251 » » watcher: &TestWatcher{ | 254 » » watcher: &testNotifyWatcher{ |
252 changes: make(chan struct{}), | 255 changes: make(chan struct{}), |
253 }, | 256 }, |
254 } | 257 } |
255 w := worker.NewNotifyWorker(actor) | 258 w := worker.NewNotifyWorker(actor) |
256 » err := WaitShort(c, w) | 259 » err := waitShort(c, w) |
257 c.Check(err, gc.ErrorMatches, "my special error") | 260 c.Check(err, gc.ErrorMatches, "my special error") |
258 actor.CheckActions(c, "setup", "teardown") | 261 actor.CheckActions(c, "setup", "teardown") |
259 c.Check(actor.watcher.stopped, jc.IsTrue) | 262 c.Check(actor.watcher.stopped, jc.IsTrue) |
260 } | 263 } |
261 | 264 |
262 func (s *notifyWorkerSuite) TestWatcherStopFailurePropagates(c *gc.C) { | 265 func (s *notifyWorkerSuite) TestWatcherStopFailurePropagates(c *gc.C) { |
263 s.actor.watcher.SetStopError(fmt.Errorf("error while stopping watcher")) | 266 s.actor.watcher.SetStopError(fmt.Errorf("error while stopping watcher")) |
264 s.worker.Kill() | 267 s.worker.Kill() |
265 c.Assert(s.worker.Wait(), gc.ErrorMatches, "error while stopping watcher
") | 268 c.Assert(s.worker.Wait(), gc.ErrorMatches, "error while stopping watcher
") |
266 // We've already stopped the worker, don't let teardown notice the | 269 // We've already stopped the worker, don't let teardown notice the |
267 // worker is in an error state | 270 // worker is in an error state |
268 s.worker = nil | 271 s.worker = nil |
269 } | 272 } |
270 | 273 |
271 func (s *notifyWorkerSuite) TestCleanRunNoticesTearDownError(c *gc.C) { | 274 func (s *notifyWorkerSuite) TestCleanRunNoticesTearDownError(c *gc.C) { |
272 s.actor.teardownError = fmt.Errorf("failed to tear down watcher") | 275 s.actor.teardownError = fmt.Errorf("failed to tear down watcher") |
273 s.worker.Kill() | 276 s.worker.Kill() |
274 c.Assert(s.worker.Wait(), gc.ErrorMatches, "failed to tear down watcher"
) | 277 c.Assert(s.worker.Wait(), gc.ErrorMatches, "failed to tear down watcher"
) |
275 s.worker = nil | 278 s.worker = nil |
276 } | 279 } |
277 | 280 |
278 func (s *notifyWorkerSuite) TestHandleErrorStopsWorkerAndWatcher(c *gc.C) { | 281 func (s *notifyWorkerSuite) TestHandleErrorStopsWorkerAndWatcher(c *gc.C) { |
279 s.stopWorker(c) | 282 s.stopWorker(c) |
280 » actor := &actionsHandler{ | 283 » actor := ¬ifyHandler{ |
281 actions: nil, | 284 actions: nil, |
282 handled: make(chan struct{}, 1), | 285 handled: make(chan struct{}, 1), |
283 handlerError: fmt.Errorf("my handling error"), | 286 handlerError: fmt.Errorf("my handling error"), |
284 » » watcher: &TestWatcher{ | 287 » » watcher: &testNotifyWatcher{ |
285 changes: make(chan struct{}), | 288 changes: make(chan struct{}), |
286 }, | 289 }, |
287 } | 290 } |
288 w := worker.NewNotifyWorker(actor) | 291 w := worker.NewNotifyWorker(actor) |
289 actor.watcher.TriggerChange(c) | 292 actor.watcher.TriggerChange(c) |
290 » WaitForHandled(c, actor.handled) | 293 » waitForHandledNotify(c, actor.handled) |
291 » err := WaitShort(c, w) | 294 » err := waitShort(c, w) |
292 c.Check(err, gc.ErrorMatches, "my handling error") | 295 c.Check(err, gc.ErrorMatches, "my handling error") |
293 actor.CheckActions(c, "setup", "handler", "teardown") | 296 actor.CheckActions(c, "setup", "handler", "teardown") |
294 c.Check(actor.watcher.stopped, jc.IsTrue) | 297 c.Check(actor.watcher.stopped, jc.IsTrue) |
295 } | 298 } |
296 | 299 |
297 func (s *notifyWorkerSuite) TestNoticesStoppedWatcher(c *gc.C) { | 300 func (s *notifyWorkerSuite) TestNoticesStoppedWatcher(c *gc.C) { |
298 // The default closedHandler doesn't panic if you have a genuine error | 301 // The default closedHandler doesn't panic if you have a genuine error |
299 // (because it assumes you want to propagate a real error and then | 302 // (because it assumes you want to propagate a real error and then |
300 // restart | 303 // restart |
301 s.actor.watcher.SetStopError(fmt.Errorf("Stopped Watcher")) | 304 s.actor.watcher.SetStopError(fmt.Errorf("Stopped Watcher")) |
302 s.actor.watcher.Stop() | 305 s.actor.watcher.Stop() |
303 » err := WaitShort(c, s.worker) | 306 » err := waitShort(c, s.worker) |
304 c.Check(err, gc.ErrorMatches, "Stopped Watcher") | 307 c.Check(err, gc.ErrorMatches, "Stopped Watcher") |
305 s.actor.CheckActions(c, "setup", "teardown") | 308 s.actor.CheckActions(c, "setup", "teardown") |
306 // Worker is stopped, don't fail TearDownTest | 309 // Worker is stopped, don't fail TearDownTest |
307 s.worker = nil | 310 s.worker = nil |
308 } | 311 } |
309 | 312 |
310 func noopHandler(watcher.Errer) error { | 313 func noopHandler(watcher.Errer) error { |
311 return nil | 314 return nil |
312 } | 315 } |
313 | 316 |
(...skipping 26 matching lines...) Expand all Loading... |
340 | 343 |
341 func (s *notifyWorkerSuite) TestErrorsOnStillAliveButClosedChannel(c *gc.C) { | 344 func (s *notifyWorkerSuite) TestErrorsOnStillAliveButClosedChannel(c *gc.C) { |
342 foundErr := fmt.Errorf("did not get an error") | 345 foundErr := fmt.Errorf("did not get an error") |
343 triggeredHandler := func(errer watcher.Errer) error { | 346 triggeredHandler := func(errer watcher.Errer) error { |
344 foundErr = errer.Err() | 347 foundErr = errer.Err() |
345 return foundErr | 348 return foundErr |
346 } | 349 } |
347 s.worker.(closerHandler).SetClosedHandler(triggeredHandler) | 350 s.worker.(closerHandler).SetClosedHandler(triggeredHandler) |
348 s.actor.watcher.SetStopError(tomb.ErrStillAlive) | 351 s.actor.watcher.SetStopError(tomb.ErrStillAlive) |
349 s.actor.watcher.Stop() | 352 s.actor.watcher.Stop() |
350 » err := WaitShort(c, s.worker) | 353 » err := waitShort(c, s.worker) |
351 c.Check(foundErr, gc.Equals, tomb.ErrStillAlive) | 354 c.Check(foundErr, gc.Equals, tomb.ErrStillAlive) |
352 // ErrStillAlive is trapped by the Stop logic and gets turned into a | 355 // ErrStillAlive is trapped by the Stop logic and gets turned into a |
353 // 'nil' when stopping. However TestDefaultClosedHandler can assert | 356 // 'nil' when stopping. However TestDefaultClosedHandler can assert |
354 // that it would have triggered a panic. | 357 // that it would have triggered a panic. |
355 c.Check(err, gc.IsNil) | 358 c.Check(err, gc.IsNil) |
356 s.actor.CheckActions(c, "setup", "teardown") | 359 s.actor.CheckActions(c, "setup", "teardown") |
357 // Worker is stopped, don't fail TearDownTest | 360 // Worker is stopped, don't fail TearDownTest |
358 s.worker = nil | 361 s.worker = nil |
359 } | 362 } |
360 | 363 |
361 func (s *notifyWorkerSuite) TestErrorsOnClosedChannel(c *gc.C) { | 364 func (s *notifyWorkerSuite) TestErrorsOnClosedChannel(c *gc.C) { |
362 foundErr := fmt.Errorf("did not get an error") | 365 foundErr := fmt.Errorf("did not get an error") |
363 triggeredHandler := func(errer watcher.Errer) error { | 366 triggeredHandler := func(errer watcher.Errer) error { |
364 foundErr = errer.Err() | 367 foundErr = errer.Err() |
365 return foundErr | 368 return foundErr |
366 } | 369 } |
367 s.worker.(closerHandler).SetClosedHandler(triggeredHandler) | 370 s.worker.(closerHandler).SetClosedHandler(triggeredHandler) |
368 s.actor.watcher.Stop() | 371 s.actor.watcher.Stop() |
369 » err := WaitShort(c, s.worker) | 372 » err := waitShort(c, s.worker) |
370 // If the foundErr is nil, we would have panic-ed (see TestDefaultClosed
Handler) | 373 // If the foundErr is nil, we would have panic-ed (see TestDefaultClosed
Handler) |
371 c.Check(foundErr, gc.IsNil) | 374 c.Check(foundErr, gc.IsNil) |
372 c.Check(err, gc.IsNil) | 375 c.Check(err, gc.IsNil) |
373 s.actor.CheckActions(c, "setup", "teardown") | 376 s.actor.CheckActions(c, "setup", "teardown") |
374 } | 377 } |
OLD | NEW |