Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(483)

Delta Between Two Patch Sets: worker/uniter/filter_test.go

Issue 7425044: uniter, state: handle upgrades better (Closed)
Left Patch Set: Created 12 years, 1 month ago
Right Patch Set: uniter, state: handle upgrades better Created 12 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « worker/uniter/filter.go ('k') | worker/uniter/modes.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 package uniter 1 package uniter
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 . "launchpad.net/gocheck" 5 . "launchpad.net/gocheck"
6 "launchpad.net/juju-core/charm" 6 "launchpad.net/juju-core/charm"
7 "launchpad.net/juju-core/juju/testing" 7 "launchpad.net/juju-core/juju/testing"
8 "launchpad.net/juju-core/state" 8 "launchpad.net/juju-core/state"
9 "launchpad.net/juju-core/worker" 9 "launchpad.net/juju-core/worker"
10 "launchpad.net/tomb"
10 "time" 11 "time"
11 ) 12 )
12 13
13 type FilterSuite struct { 14 type FilterSuite struct {
14 testing.JujuConnSuite 15 testing.JujuConnSuite
15 wordpress *state.Service 16 wordpress *state.Service
16 unit *state.Unit 17 unit *state.Unit
17 mysqlcharm *state.Charm 18 mysqlcharm *state.Charm
19 wpcharm *state.Charm
18 } 20 }
19 21
20 var _ = Suite(&FilterSuite{}) 22 var _ = Suite(&FilterSuite{})
21 23
22 func (s *FilterSuite) SetUpTest(c *C) { 24 func (s *FilterSuite) SetUpTest(c *C) {
23 s.JujuConnSuite.SetUpTest(c) 25 s.JujuConnSuite.SetUpTest(c)
24 var err error 26 var err error
25 » s.wordpress, err = s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) 27 » s.wpcharm = s.AddTestingCharm(c, "wordpress")
28 » s.wordpress, err = s.State.AddService("wordpress", s.wpcharm)
26 c.Assert(err, IsNil) 29 c.Assert(err, IsNil)
27 s.unit, err = s.wordpress.AddUnit() 30 s.unit, err = s.wordpress.AddUnit()
28 c.Assert(err, IsNil) 31 c.Assert(err, IsNil)
29 } 32 }
30 33
31 func (s *FilterSuite) TestUnitDeath(c *C) { 34 func (s *FilterSuite) TestUnitDeath(c *C) {
32 f, err := newFilter(s.State, s.unit.Name()) 35 f, err := newFilter(s.State, s.unit.Name())
33 c.Assert(err, IsNil) 36 c.Assert(err, IsNil)
34 defer f.Stop() 37 defer f.Stop()
35 assertNotClosed := func() { 38 assertNotClosed := func() {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 err = s.unit.ClearResolved() 159 err = s.unit.ClearResolved()
157 c.Assert(err, IsNil) 160 c.Assert(err, IsNil)
158 f.WantResolvedEvent() 161 f.WantResolvedEvent()
159 err = s.unit.SetResolved(state.ResolvedNoHooks) 162 err = s.unit.SetResolved(state.ResolvedNoHooks)
160 c.Assert(err, IsNil) 163 c.Assert(err, IsNil)
161 f.WantResolvedEvent() 164 f.WantResolvedEvent()
162 assertChange(state.ResolvedNoHooks) 165 assertChange(state.ResolvedNoHooks)
163 assertNoChange() 166 assertNoChange()
164 } 167 }
165 168
166 func (s *FilterSuite) TestCharmEvents(c *C) { 169 func (s *FilterSuite) TestCharmUpgradeEvents(c *C) {
167 oldCharm := s.AddTestingCharm(c, "upgrade1") 170 oldCharm := s.AddTestingCharm(c, "upgrade1")
168 svc, err := s.State.AddService("upgradetest", oldCharm) 171 svc, err := s.State.AddService("upgradetest", oldCharm)
169 c.Assert(err, IsNil) 172 c.Assert(err, IsNil)
170 unit, err := svc.AddUnit() 173 unit, err := svc.AddUnit()
171 c.Assert(err, IsNil) 174 c.Assert(err, IsNil)
172 175
173 f, err := newFilter(s.State, unit.Name()) 176 f, err := newFilter(s.State, unit.Name())
174 c.Assert(err, IsNil) 177 c.Assert(err, IsNil)
175 defer f.Stop() 178 defer f.Stop()
176 179
177 // No initial event is sent. 180 // No initial event is sent.
178 assertNoChange := func() { 181 assertNoChange := func() {
179 s.State.StartSync() 182 s.State.StartSync()
180 select { 183 select {
181 case sch := <-f.UpgradeEvents(): 184 case sch := <-f.UpgradeEvents():
182 c.Fatalf("unexpected %#v", sch) 185 c.Fatalf("unexpected %#v", sch)
183 case <-time.After(50 * time.Millisecond): 186 case <-time.After(50 * time.Millisecond):
184 } 187 }
185 } 188 }
186 assertNoChange() 189 assertNoChange()
187 190
188 » // Request an event relative to the existing state; nothing. 191 » // Setting a charm generates no new events if it already matches.
192 » err = f.SetCharm(oldCharm.URL())
193 » c.Assert(err, IsNil)
194 » assertNoChange()
195
196 » // Explicitly request an event relative to the existing state; nothing.
189 f.WantUpgradeEvent(false) 197 f.WantUpgradeEvent(false)
190 // TODO: is this needed here?
TheMue 2013/03/01 10:31:07 See above.
dimitern 2013/03/01 16:42:37 Gone now.
191 f.SetCharm(oldCharm.URL())
192 assertNoChange() 198 assertNoChange()
193 199
194 // Change the service in an irrelevant way; no events. 200 // Change the service in an irrelevant way; no events.
195 err = svc.SetExposed() 201 err = svc.SetExposed()
196 c.Assert(err, IsNil) 202 c.Assert(err, IsNil)
197 assertNoChange() 203 assertNoChange()
198 204
199 // Change the service's charm; new event received. 205 // Change the service's charm; new event received.
200 newCharm := s.AddTestingCharm(c, "upgrade2") 206 newCharm := s.AddTestingCharm(c, "upgrade2")
201 err = svc.SetCharm(newCharm, false) 207 err = svc.SetCharm(newCharm, false)
202 c.Assert(err, IsNil) 208 c.Assert(err, IsNil)
203 assertChange := func(url *charm.URL) { 209 assertChange := func(url *charm.URL) {
204 s.State.Sync() 210 s.State.Sync()
205 select { 211 select {
206 case upgradeCharm := <-f.UpgradeEvents(): 212 case upgradeCharm := <-f.UpgradeEvents():
207 c.Assert(upgradeCharm, DeepEquals, url) 213 c.Assert(upgradeCharm, DeepEquals, url)
208 case <-time.After(50 * time.Millisecond): 214 case <-time.After(50 * time.Millisecond):
209 c.Fatalf("timed out") 215 c.Fatalf("timed out")
210 } 216 }
211 } 217 }
212 assertChange(newCharm.URL()) 218 assertChange(newCharm.URL())
213 assertNoChange() 219 assertNoChange()
214 220
215 » // Request a change relative to the original state, unforced; 221 » // Request a new upgrade *unforced* upgrade event, we should see one.
216 » // same event is sent.
217 f.WantUpgradeEvent(false) 222 f.WantUpgradeEvent(false)
218 // TODO: is this needed here?
219 f.SetCharm(oldCharm.URL())
220 assertChange(newCharm.URL()) 223 assertChange(newCharm.URL())
221 assertNoChange() 224 assertNoChange()
222 225
223 » // Request a forced change relative to the initial state; no change... 226 » // Request only *forced* upgrade events; nothing.
224 f.WantUpgradeEvent(true) 227 f.WantUpgradeEvent(true)
225 » // TODO: is this needed here? 228 » assertNoChange()
226 » f.SetCharm(oldCharm.URL()) 229
227 » assertNoChange() 230 » // But when we have a forced upgrade to the same URL, no new event.
228
229 » // ...and still no change when we have a forced upgrade to that state...
230 err = svc.SetCharm(oldCharm, true) 231 err = svc.SetCharm(oldCharm, true)
231 c.Assert(err, IsNil) 232 c.Assert(err, IsNil)
232 assertNoChange() 233 assertNoChange()
233 234
234 » // ...but a *forced* change to a different charm does generate an event. 235 » // ...but a *forced* change to a different URL should generate an event.
235 err = svc.SetCharm(newCharm, true) 236 err = svc.SetCharm(newCharm, true)
236 assertChange(newCharm.URL()) 237 assertChange(newCharm.URL())
237 assertNoChange() 238 assertNoChange()
238 } 239 }
239 240
240 func (s *FilterSuite) TestConfigEvents(c *C) { 241 func (s *FilterSuite) TestConfigEvents(c *C) {
241 f, err := newFilter(s.State, s.unit.Name()) 242 f, err := newFilter(s.State, s.unit.Name())
242 c.Assert(err, IsNil) 243 c.Assert(err, IsNil)
243 defer f.Stop() 244 defer f.Stop()
244 245
245 » // Initial event. 246 » // Test no changes before the charm URL is set.
247 » assertNoChange := func() {
248 » » s.State.StartSync()
249 » » select {
250 » » case <-f.ConfigEvents():
251 » » » c.Fatalf("unexpected config event")
252 » » case <-time.After(50 * time.Millisecond):
253 » » }
254 » }
255 » assertNoChange()
256
246 assertChange := func() { 257 assertChange := func() {
247 s.State.Sync() 258 s.State.Sync()
248 select { 259 select {
249 case _, ok := <-f.ConfigEvents(): 260 case _, ok := <-f.ConfigEvents():
250 c.Assert(ok, Equals, true) 261 c.Assert(ok, Equals, true)
251 case <-time.After(50 * time.Millisecond): 262 case <-time.After(50 * time.Millisecond):
252 c.Fatalf("timed out") 263 c.Fatalf("timed out")
253 } 264 }
254 » } 265 » » assertNoChange()
266 » }
267
268 » // Set the charm URL to trigger config events.
269 » err = f.SetCharm(s.wpcharm.URL())
270 » c.Assert(err, IsNil)
255 assertChange() 271 assertChange()
256 » assertNoChange := func() { 272
257 » » s.State.StartSync() 273 » // Make sure the charm URL is set now.
258 » » select { 274 » s.unit.Refresh()
259 » » case <-f.ConfigEvents(): 275 » curl, ok := s.unit.CharmURL()
260 » » » c.Fatalf("unexpected config event") 276 » c.Assert(ok, Equals, true)
261 » » case <-time.After(50 * time.Millisecond): 277 » c.Assert(curl, DeepEquals, s.wpcharm.URL())
262 » » }
263 » }
264 » assertNoChange()
265 278
266 // Change the config; new event received. 279 // Change the config; new event received.
267 node, err := s.wordpress.Config() 280 node, err := s.wordpress.Config()
268 c.Assert(err, IsNil) 281 c.Assert(err, IsNil)
269 node.Set("skill-level", 9001) 282 node.Set("skill-level", 9001)
270 _, err = node.Write() 283 _, err = node.Write()
271 c.Assert(err, IsNil) 284 c.Assert(err, IsNil)
272 assertChange() 285 assertChange()
273 assertNoChange()
274 286
275 // Change the config a couple of times, then reset the events. 287 // Change the config a couple of times, then reset the events.
276 node.Set("title", "20,000 leagues in the cloud") 288 node.Set("title", "20,000 leagues in the cloud")
277 _, err = node.Write() 289 _, err = node.Write()
278 c.Assert(err, IsNil) 290 c.Assert(err, IsNil)
279 node.Set("outlook", "precipitous") 291 node.Set("outlook", "precipitous")
280 _, err = node.Write() 292 _, err = node.Write()
281 c.Assert(err, IsNil) 293 c.Assert(err, IsNil)
294 // We make sure the event has come into the filter before we tell it to discard any received.
282 s.State.Sync() 295 s.State.Sync()
283 f.DiscardConfigEvent() 296 f.DiscardConfigEvent()
284 assertNoChange() 297 assertNoChange()
285 298
286 // Check that a filter's initial event works with DiscardConfigEvent 299 // Check that a filter's initial event works with DiscardConfigEvent
287 // as expected. 300 // as expected.
288 f, err = newFilter(s.State, s.unit.Name()) 301 f, err = newFilter(s.State, s.unit.Name())
289 c.Assert(err, IsNil) 302 c.Assert(err, IsNil)
290 defer f.Stop() 303 defer f.Stop()
304 s.State.Sync()
291 f.DiscardConfigEvent() 305 f.DiscardConfigEvent()
292 s.State.Sync()
293 assertNoChange() 306 assertNoChange()
294 307
295 // Further changes are still collapsed as appropriate. 308 // Further changes are still collapsed as appropriate.
296 node.Set("skill-level", 123) 309 node.Set("skill-level", 123)
297 _, err = node.Write() 310 _, err = node.Write()
298 c.Assert(err, IsNil) 311 c.Assert(err, IsNil)
299 node.Set("outlook", "expressive") 312 node.Set("outlook", "expressive")
300 _, err = node.Write() 313 _, err = node.Write()
301 c.Assert(err, IsNil) 314 c.Assert(err, IsNil)
302 assertChange() 315 assertChange()
303 » assertNoChange() 316 }
317
318 func (s *FilterSuite) TestCharmErrorEvents(c *C) {
319 » f, err := newFilter(s.State, s.unit.Name())
320 » c.Assert(err, IsNil)
321 » defer f.Stop()
322
323 » assertNoChange := func() {
324 » » s.State.StartSync()
325 » » select {
326 » » case <-f.ConfigEvents():
327 » » » c.Fatalf("unexpected config event")
328 » » case <-time.After(50 * time.Millisecond):
329 » » }
330 » }
331 » assertDead := func(f *filter) {
332 » » select {
333 » » case <-f.Dead():
334 » » case <-time.After(50 * time.Millisecond):
335 » » » c.Fatalf("filter did not die")
336 » » }
337 » }
338
339 » // Check setting an invalid charm URL does not send events.
340 » err = f.SetCharm(charm.MustParseURL("cs:missing/one-1"))
341 » c.Assert(err, Equals, tomb.ErrDying)
342 » assertNoChange()
343 » assertDead(f)
344
345 » // Filter died after the error, so restart it.
346 » f, err = newFilter(s.State, s.unit.Name())
347 » c.Assert(err, IsNil)
348 » defer f.Stop()
349
350 » // Check with a nil charm URL, again no changes.
351 » err = f.SetCharm(nil)
352 » c.Assert(err, Equals, tomb.ErrDying)
353 » assertNoChange()
354 » assertDead(f)
304 } 355 }
305 356
306 func (s *FilterSuite) TestRelationsEvents(c *C) { 357 func (s *FilterSuite) TestRelationsEvents(c *C) {
307 f, err := newFilter(s.State, s.unit.Name()) 358 f, err := newFilter(s.State, s.unit.Name())
308 c.Assert(err, IsNil) 359 c.Assert(err, IsNil)
309 defer f.Stop() 360 defer f.Stop()
310 361
311 assertNoChange := func() { 362 assertNoChange := func() {
312 s.State.Sync() 363 s.State.Sync()
313 select { 364 select {
314 case ids := <-f.RelationsEvents(): 365 case ids := <-f.RelationsEvents():
315 c.Fatalf("unexpected relations event %#v", ids) 366 c.Fatalf("unexpected relations event %#v", ids)
316 case <-time.After(50 * time.Millisecond): 367 case <-time.After(50 * time.Millisecond):
317 } 368 }
318 } 369 }
319 assertNoChange() 370 assertNoChange()
320 371
321 // Add a couple of relations; check the event. 372 // Add a couple of relations; check the event.
322 rel0 := s.addRelation(c) 373 rel0 := s.addRelation(c)
323 rel1 := s.addRelation(c) 374 rel1 := s.addRelation(c)
324 assertChange := func(expect []int) { 375 assertChange := func(expect []int) {
325 s.State.Sync() 376 s.State.Sync()
326 select { 377 select {
327 case got := <-f.RelationsEvents(): 378 case got := <-f.RelationsEvents():
328 c.Assert(got, DeepEquals, expect) 379 c.Assert(got, DeepEquals, expect)
329 case <-time.After(50 * time.Millisecond): 380 case <-time.After(50 * time.Millisecond):
330 c.Fatalf("timed out") 381 c.Fatalf("timed out")
331 } 382 }
383 assertNoChange()
332 } 384 }
333 assertChange([]int{0, 1}) 385 assertChange([]int{0, 1})
334 assertNoChange()
335
336 // TODO: remove if safe
fwereade 2013/03/01 11:59:56 We definitely need to test this behaviour, as we d
dimitern 2013/03/01 16:42:37 I'll do a separate test.
337 // Request all relations events; no changes should happen
338 //f.WantAllRelationsEvents()
339 //assertChange([]int{0, 1})
340 //assertNoChange()
341 386
342 // Add another relation, and change another's Life (by entering scope be fore 387 // Add another relation, and change another's Life (by entering scope be fore
343 // Destroy, thereby setting the relation to Dying); check event. 388 // Destroy, thereby setting the relation to Dying); check event.
344 s.addRelation(c) 389 s.addRelation(c)
345 ru0, err := rel0.Unit(s.unit) 390 ru0, err := rel0.Unit(s.unit)
346 c.Assert(err, IsNil) 391 c.Assert(err, IsNil)
347 err = ru0.EnterScope(nil) 392 err = ru0.EnterScope(nil)
348 c.Assert(err, IsNil) 393 c.Assert(err, IsNil)
349 err = rel0.Destroy() 394 err = rel0.Destroy()
350 c.Assert(err, IsNil) 395 c.Assert(err, IsNil)
351 assertChange([]int{0, 2}) 396 assertChange([]int{0, 2})
352 assertNoChange()
353 397
354 // Remove a relation completely; check event. 398 // Remove a relation completely; check event.
355 err = rel1.Destroy() 399 err = rel1.Destroy()
356 c.Assert(err, IsNil) 400 c.Assert(err, IsNil)
357 assertChange([]int{1}) 401 assertChange([]int{1})
358 assertNoChange()
359 402
360 // Start a new filter, check initial event. 403 // Start a new filter, check initial event.
361 f, err = newFilter(s.State, s.unit.Name()) 404 f, err = newFilter(s.State, s.unit.Name())
362 c.Assert(err, IsNil) 405 c.Assert(err, IsNil)
363 defer f.Stop() 406 defer f.Stop()
364 assertChange([]int{0, 2}) 407 assertChange([]int{0, 2})
365 » assertNoChange() 408
409 » // Check setting the charm URL generates all new relation events.
410 » err = f.SetCharm(s.wpcharm.URL())
411 » c.Assert(err, IsNil)
412 » assertChange([]int{0, 2})
366 } 413 }
367 414
368 func (s *FilterSuite) addRelation(c *C) *state.Relation { 415 func (s *FilterSuite) addRelation(c *C) *state.Relation {
369 if s.mysqlcharm == nil { 416 if s.mysqlcharm == nil {
370 s.mysqlcharm = s.AddTestingCharm(c, "mysql") 417 s.mysqlcharm = s.AddTestingCharm(c, "mysql")
371 } 418 }
372 rels, err := s.wordpress.Relations() 419 rels, err := s.wordpress.Relations()
373 c.Assert(err, IsNil) 420 c.Assert(err, IsNil)
374 svcName := fmt.Sprintf("mysql%d", len(rels)) 421 svcName := fmt.Sprintf("mysql%d", len(rels))
375 _, err = s.State.AddService(svcName, s.mysqlcharm) 422 _, err = s.State.AddService(svcName, s.mysqlcharm)
376 c.Assert(err, IsNil) 423 c.Assert(err, IsNil)
377 eps, err := s.State.InferEndpoints([]string{svcName, "wordpress"}) 424 eps, err := s.State.InferEndpoints([]string{svcName, "wordpress"})
378 c.Assert(err, IsNil) 425 c.Assert(err, IsNil)
379 rel, err := s.State.AddRelation(eps...) 426 rel, err := s.State.AddRelation(eps...)
380 c.Assert(err, IsNil) 427 c.Assert(err, IsNil)
381 return rel 428 return rel
382 } 429 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b