launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/relationunit_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 "sort" 9 "strconv" 10 "time" 11 12 errgo "launchpad.net/errgo/errors" 13 gc "launchpad.net/gocheck" 14 15 "launchpad.net/juju-core/charm" 16 "launchpad.net/juju-core/errors" 17 "launchpad.net/juju-core/state" 18 "launchpad.net/juju-core/state/testing" 19 coretesting "launchpad.net/juju-core/testing" 20 jc "launchpad.net/juju-core/testing/checkers" 21 ) 22 23 type RUs []*state.RelationUnit 24 25 type RelationUnitSuite struct { 26 ConnSuite 27 } 28 29 var _ = gc.Suite(&RelationUnitSuite{}) 30 31 func assertInScope(c *gc.C, ru *state.RelationUnit) { 32 ok, err := ru.InScope() 33 c.Assert(err, gc.IsNil) 34 c.Assert(ok, jc.IsTrue) 35 } 36 37 func assertNotInScope(c *gc.C, ru *state.RelationUnit) { 38 ok, err := ru.InScope() 39 c.Assert(err, gc.IsNil) 40 c.Assert(ok, jc.IsFalse) 41 } 42 43 func (s *RelationUnitSuite) TestReadSettingsErrors(c *gc.C) { 44 riak := s.AddTestingService(c, "riak", s.AddTestingCharm(c, "riak")) 45 u0, err := riak.AddUnit() 46 c.Assert(err, gc.IsNil) 47 riakEP, err := riak.Endpoint("ring") 48 c.Assert(err, gc.IsNil) 49 rel, err := s.State.EndpointsRelation(riakEP) 50 c.Assert(err, gc.IsNil) 51 ru0, err := rel.Unit(u0) 52 c.Assert(err, gc.IsNil) 53 54 _, err = ru0.ReadSettings("nonsense") 55 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "nonsense" in relation "riak:ring": "nonsense" is not a valid unit name`) 56 _, err = ru0.ReadSettings("unknown/0") 57 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "unknown/0" in relation "riak:ring": service "unknown" is not a member of "riak:ring"`) 58 _, err = ru0.ReadSettings("riak/pressure") 59 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/pressure" in relation "riak:ring": "riak/pressure" is not a valid unit name`) 60 _, err = ru0.ReadSettings("riak/1") 61 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/1" in relation "riak:ring": settings not found`) 62 } 63 64 func (s *RelationUnitSuite) TestPeerSettings(c *gc.C) { 65 pr := NewPeerRelation(c, s.State) 66 rus := RUs{pr.ru0, pr.ru1} 67 68 // Check missing settings cannot be read by any RU. 69 for _, ru := range rus { 70 _, err := ru.ReadSettings("riak/0") 71 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/0" in relation "riak:ring": settings not found`) 72 } 73 74 // Add settings for one RU. 75 assertNotInScope(c, pr.ru0) 76 err := pr.ru0.EnterScope(map[string]interface{}{"gene": "kelly"}) 77 c.Assert(err, gc.IsNil) 78 node, err := pr.ru0.Settings() 79 c.Assert(err, gc.IsNil) 80 node.Set("meme", "socially-awkward-penguin") 81 _, err = node.Write() 82 c.Assert(err, gc.IsNil) 83 normal := map[string]interface{}{ 84 "gene": "kelly", 85 "meme": "socially-awkward-penguin", 86 } 87 88 // Check settings can be read by every RU. 89 assertSettings := func(u *state.Unit, expect map[string]interface{}) { 90 for _, ru := range rus { 91 m, err := ru.ReadSettings(u.Name()) 92 c.Assert(err, gc.IsNil) 93 c.Assert(m, gc.DeepEquals, expect) 94 } 95 } 96 assertSettings(pr.u0, normal) 97 assertInScope(c, pr.ru0) 98 99 // Check that EnterScope when scope already entered does not touch 100 // settings at all. 101 changed := map[string]interface{}{"foo": "bar"} 102 err = pr.ru0.EnterScope(changed) 103 c.Assert(err, gc.IsNil) 104 assertSettings(pr.u0, normal) 105 assertInScope(c, pr.ru0) 106 107 // Leave scope, check settings are still as accessible as before. 108 err = pr.ru0.LeaveScope() 109 c.Assert(err, gc.IsNil) 110 assertSettings(pr.u0, normal) 111 assertNotInScope(c, pr.ru0) 112 113 // Re-enter scope wih changed settings, and check they completely overwrite 114 // the old ones. 115 err = pr.ru0.EnterScope(changed) 116 c.Assert(err, gc.IsNil) 117 assertSettings(pr.u0, changed) 118 assertInScope(c, pr.ru0) 119 120 // Leave and re-enter with nil nettings, and check they overwrite to become 121 // an empty map. 122 err = pr.ru0.LeaveScope() 123 c.Assert(err, gc.IsNil) 124 assertNotInScope(c, pr.ru0) 125 err = pr.ru0.EnterScope(nil) 126 c.Assert(err, gc.IsNil) 127 assertSettings(pr.u0, map[string]interface{}{}) 128 assertInScope(c, pr.ru0) 129 130 // Check that entering scope for the first time with nil settings works correctly. 131 assertNotInScope(c, pr.ru1) 132 err = pr.ru1.EnterScope(nil) 133 c.Assert(err, gc.IsNil) 134 assertSettings(pr.u1, map[string]interface{}{}) 135 assertInScope(c, pr.ru1) 136 } 137 138 func (s *RelationUnitSuite) TestProReqSettings(c *gc.C) { 139 prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeGlobal) 140 rus := RUs{prr.pru0, prr.pru1, prr.rru0, prr.rru1} 141 142 // Check missing settings cannot be read by any RU. 143 for _, ru := range rus { 144 _, err := ru.ReadSettings("mysql/0") 145 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "mysql/0" in relation "wordpress:db mysql:server": settings not found`) 146 } 147 148 // Add settings for one RU. 149 assertNotInScope(c, prr.pru0) 150 err := prr.pru0.EnterScope(map[string]interface{}{"gene": "simmons"}) 151 c.Assert(err, gc.IsNil) 152 node, err := prr.pru0.Settings() 153 c.Assert(err, gc.IsNil) 154 node.Set("meme", "foul-bachelor-frog") 155 _, err = node.Write() 156 c.Assert(err, gc.IsNil) 157 assertInScope(c, prr.pru0) 158 159 // Check settings can be read by every RU. 160 for _, ru := range rus { 161 m, err := ru.ReadSettings("mysql/0") 162 c.Assert(err, gc.IsNil) 163 c.Assert(m["gene"], gc.Equals, "simmons") 164 c.Assert(m["meme"], gc.Equals, "foul-bachelor-frog") 165 } 166 } 167 168 func (s *RelationUnitSuite) TestContainerSettings(c *gc.C) { 169 prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeContainer) 170 rus := RUs{prr.pru0, prr.pru1, prr.rru0, prr.rru1} 171 172 // Check missing settings cannot be read by any RU. 173 for _, ru := range rus { 174 _, err := ru.ReadSettings("logging/0") 175 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "logging/0" in relation "logging:info mysql:juju-info": settings not found`) 176 } 177 178 // Add settings for one RU. 179 assertNotInScope(c, prr.pru0) 180 err := prr.pru0.EnterScope(map[string]interface{}{"gene": "hackman"}) 181 c.Assert(err, gc.IsNil) 182 node, err := prr.pru0.Settings() 183 c.Assert(err, gc.IsNil) 184 node.Set("meme", "foul-bachelor-frog") 185 _, err = node.Write() 186 c.Assert(err, gc.IsNil) 187 assertInScope(c, prr.pru0) 188 189 // Check settings can be read by RUs in the same container. 190 rus0 := RUs{prr.pru0, prr.rru0} 191 for _, ru := range rus0 { 192 m, err := ru.ReadSettings("mysql/0") 193 c.Assert(err, gc.IsNil) 194 c.Assert(m["gene"], gc.Equals, "hackman") 195 c.Assert(m["meme"], gc.Equals, "foul-bachelor-frog") 196 } 197 198 // Check settings are still inaccessible to RUs outside that container 199 rus1 := RUs{prr.pru1, prr.rru1} 200 for _, ru := range rus1 { 201 _, err := ru.ReadSettings("mysql/0") 202 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "mysql/0" in relation "logging:info mysql:juju-info": settings not found`) 203 } 204 } 205 206 func (s *RelationUnitSuite) TestContainerCreateSubordinate(c *gc.C) { 207 psvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 208 rsvc := s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 209 eps, err := s.State.InferEndpoints([]string{"mysql", "logging"}) 210 c.Assert(err, gc.IsNil) 211 rel, err := s.State.AddRelation(eps...) 212 c.Assert(err, gc.IsNil) 213 punit, err := psvc.AddUnit() 214 c.Assert(err, gc.IsNil) 215 pru, err := rel.Unit(punit) 216 c.Assert(err, gc.IsNil) 217 218 // Check that no units of the subordinate service exist. 219 assertSubCount := func(expect int) []*state.Unit { 220 runits, err := rsvc.AllUnits() 221 c.Assert(err, gc.IsNil) 222 c.Assert(runits, gc.HasLen, expect) 223 return runits 224 } 225 assertSubCount(0) 226 227 // Enter principal's scope and check a subordinate was created. 228 assertNotInScope(c, pru) 229 err = pru.EnterScope(nil) 230 c.Assert(err, gc.IsNil) 231 assertSubCount(1) 232 assertInScope(c, pru) 233 234 // Enter principal scope again and check no more subordinates created. 235 err = pru.EnterScope(nil) 236 c.Assert(err, gc.IsNil) 237 assertSubCount(1) 238 assertInScope(c, pru) 239 240 // Leave principal scope, then re-enter, and check that still no further 241 // subordinates are created. 242 err = pru.LeaveScope() 243 c.Assert(err, gc.IsNil) 244 assertNotInScope(c, pru) 245 err = pru.EnterScope(nil) 246 c.Assert(err, gc.IsNil) 247 runits := assertSubCount(1) 248 assertInScope(c, pru) 249 250 // Set the subordinate to Dying, and enter scope again; because the scope 251 // is already entered, no error is returned. 252 runit := runits[0] 253 err = runit.Destroy() 254 c.Assert(err, gc.IsNil) 255 err = pru.EnterScope(nil) 256 c.Assert(err, gc.IsNil) 257 assertInScope(c, pru) 258 259 // Leave scope, then try to enter again with the Dying subordinate. 260 err = pru.LeaveScope() 261 c.Assert(err, gc.IsNil) 262 assertNotInScope(c, pru) 263 err = pru.EnterScope(nil) 264 c.Assert(errgo.Cause(err), gc.Equals, state.ErrCannotEnterScopeYet) 265 assertNotInScope(c, pru) 266 267 // Remove the subordinate, and enter scope again; this should work, and 268 // create a new subordinate. 269 err = runit.EnsureDead() 270 c.Assert(err, gc.IsNil) 271 err = runit.Remove() 272 c.Assert(err, gc.IsNil) 273 assertSubCount(0) 274 assertNotInScope(c, pru) 275 err = pru.EnterScope(nil) 276 c.Assert(err, gc.IsNil) 277 assertSubCount(1) 278 assertInScope(c, pru) 279 } 280 281 func (s *RelationUnitSuite) TestDestroyRelationWithUnitsInScope(c *gc.C) { 282 pr := NewPeerRelation(c, s.State) 283 rel := pr.ru0.Relation() 284 285 // Enter two units, and check that Destroying the service sets the 286 // relation to Dying (rather than removing it directly). 287 assertNotInScope(c, pr.ru0) 288 err := pr.ru0.EnterScope(map[string]interface{}{"some": "settings"}) 289 c.Assert(err, gc.IsNil) 290 assertInScope(c, pr.ru0) 291 assertNotInScope(c, pr.ru1) 292 err = pr.ru1.EnterScope(nil) 293 c.Assert(err, gc.IsNil) 294 assertInScope(c, pr.ru1) 295 err = pr.svc.Destroy() 296 c.Assert(err, gc.IsNil) 297 err = rel.Refresh() 298 c.Assert(err, gc.IsNil) 299 c.Assert(rel.Life(), gc.Equals, state.Dying) 300 301 // Check that we can't add a new unit now. 302 assertNotInScope(c, pr.ru2) 303 err = pr.ru2.EnterScope(nil) 304 c.Assert(errgo.Cause(err), gc.Equals, state.ErrCannotEnterScope) 305 assertNotInScope(c, pr.ru2) 306 307 // Check that we created no settings for the unit we failed to add. 308 _, err = pr.ru0.ReadSettings("riak/2") 309 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/2" in relation "riak:ring": settings not found`) 310 311 // ru0 leaves the scope; check that service Destroy is still a no-op. 312 assertInScope(c, pr.ru0) 313 err = pr.ru0.LeaveScope() 314 c.Assert(err, gc.IsNil) 315 assertNotInScope(c, pr.ru0) 316 err = pr.svc.Destroy() 317 c.Assert(err, gc.IsNil) 318 319 // Check that unit settings for the original unit still exist, and have 320 // not yet been marked for deletion. 321 err = s.State.Cleanup() 322 c.Assert(err, gc.IsNil) 323 assertSettings := func() { 324 settings, err := pr.ru1.ReadSettings("riak/0") 325 c.Assert(err, gc.IsNil) 326 c.Assert(settings, gc.DeepEquals, map[string]interface{}{"some": "settings"}) 327 } 328 assertSettings() 329 330 // The final unit leaves the scope, and cleans up after itself. 331 assertInScope(c, pr.ru1) 332 err = pr.ru1.LeaveScope() 333 c.Assert(err, gc.IsNil) 334 assertNotInScope(c, pr.ru1) 335 err = rel.Refresh() 336 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 337 338 // The settings were not themselves actually deleted yet... 339 assertSettings() 340 341 // ...but they were scheduled for deletion. 342 err = s.State.Cleanup() 343 c.Assert(err, gc.IsNil) 344 _, err = pr.ru1.ReadSettings("riak/0") 345 c.Assert(err, gc.ErrorMatches, `cannot read settings for unit "riak/0" in relation "riak:ring": settings not found`) 346 } 347 348 func (s *RelationUnitSuite) TestAliveRelationScope(c *gc.C) { 349 pr := NewPeerRelation(c, s.State) 350 rel := pr.ru0.Relation() 351 352 // Two units enter... 353 assertNotInScope(c, pr.ru0) 354 err := pr.ru0.EnterScope(nil) 355 c.Assert(err, gc.IsNil) 356 assertInScope(c, pr.ru0) 357 assertNotInScope(c, pr.ru1) 358 err = pr.ru1.EnterScope(nil) 359 c.Assert(err, gc.IsNil) 360 assertInScope(c, pr.ru1) 361 362 // One unit becomes Dying, then re-enters the scope; this is not an error, 363 // because the state is already as requested. 364 err = pr.u0.Destroy() 365 c.Assert(err, gc.IsNil) 366 err = pr.ru0.EnterScope(nil) 367 c.Assert(err, gc.IsNil) 368 assertInScope(c, pr.ru0) 369 370 // Two units leave... 371 err = pr.ru0.LeaveScope() 372 c.Assert(err, gc.IsNil) 373 assertNotInScope(c, pr.ru0) 374 err = pr.ru1.LeaveScope() 375 c.Assert(err, gc.IsNil) 376 assertNotInScope(c, pr.ru1) 377 378 // The relation scope is empty, but the relation is still alive... 379 err = rel.Refresh() 380 c.Assert(err, gc.IsNil) 381 c.Assert(rel.Life(), gc.Equals, state.Alive) 382 383 // ...and new units can still join it... 384 assertNotInScope(c, pr.ru2) 385 err = pr.ru2.EnterScope(nil) 386 c.Assert(err, gc.IsNil) 387 assertInScope(c, pr.ru2) 388 389 // ...but Dying units cannot. 390 err = pr.u3.Destroy() 391 c.Assert(err, gc.IsNil) 392 assertNotInScope(c, pr.ru3) 393 err = pr.ru3.EnterScope(nil) 394 c.Assert(errgo.Cause(err), gc.Equals, state.ErrCannotEnterScope) 395 assertNotInScope(c, pr.ru3) 396 } 397 398 func (s *StateSuite) TestWatchWatchScopeDiesOnStateClose(c *gc.C) { 399 testWatcherDiesWhenStateCloses(c, func(c *gc.C, st *state.State) waiter { 400 pr := NewPeerRelation(c, st) 401 w := pr.ru0.WatchScope() 402 <-w.Changes() 403 return w 404 }) 405 } 406 407 func (s *RelationUnitSuite) TestPeerWatchScope(c *gc.C) { 408 pr := NewPeerRelation(c, s.State) 409 410 // Test empty initial event. 411 w0 := pr.ru0.WatchScope() 412 defer testing.AssertStop(c, w0) 413 s.assertScopeChange(c, w0, nil, nil) 414 s.assertNoScopeChange(c, w0) 415 416 // ru0 enters; check no change, but settings written. 417 assertNotInScope(c, pr.ru0) 418 err := pr.ru0.EnterScope(map[string]interface{}{"foo": "bar"}) 419 c.Assert(err, gc.IsNil) 420 s.assertNoScopeChange(c, w0) 421 node, err := pr.ru0.Settings() 422 c.Assert(err, gc.IsNil) 423 c.Assert(node.Map(), gc.DeepEquals, map[string]interface{}{"foo": "bar"}) 424 assertInScope(c, pr.ru0) 425 426 // ru1 enters; check change is observed. 427 assertNotInScope(c, pr.ru1) 428 err = pr.ru1.EnterScope(nil) 429 c.Assert(err, gc.IsNil) 430 s.assertScopeChange(c, w0, []string{"riak/1"}, nil) 431 s.assertNoScopeChange(c, w0) 432 assertInScope(c, pr.ru1) 433 434 // ru1 enters again, check no problems and no changes. 435 err = pr.ru1.EnterScope(nil) 436 c.Assert(err, gc.IsNil) 437 s.assertNoScopeChange(c, w0) 438 assertInScope(c, pr.ru1) 439 440 // Stop watching; ru2 enters. 441 testing.AssertStop(c, w0) 442 assertNotInScope(c, pr.ru2) 443 err = pr.ru2.EnterScope(nil) 444 c.Assert(err, gc.IsNil) 445 assertInScope(c, pr.ru2) 446 447 // Start watch again, check initial event. 448 w0 = pr.ru0.WatchScope() 449 defer testing.AssertStop(c, w0) 450 s.assertScopeChange(c, w0, []string{"riak/1", "riak/2"}, nil) 451 s.assertNoScopeChange(c, w0) 452 453 // ru1 leaves; check event. 454 assertInScope(c, pr.ru1) 455 err = pr.ru1.LeaveScope() 456 c.Assert(err, gc.IsNil) 457 s.assertScopeChange(c, w0, nil, []string{"riak/1"}) 458 s.assertNoScopeChange(c, w0) 459 assertNotInScope(c, pr.ru1) 460 461 // ru1 leaves again; check no problems and no changes. 462 err = pr.ru1.LeaveScope() 463 c.Assert(err, gc.IsNil) 464 s.assertNoScopeChange(c, w0) 465 assertNotInScope(c, pr.ru1) 466 } 467 468 func (s *RelationUnitSuite) TestProReqWatchScope(c *gc.C) { 469 prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeGlobal) 470 471 // Test empty initial events for all RUs. 472 ws := prr.watches() 473 for _, w := range ws { 474 defer testing.AssertStop(c, w) 475 } 476 for _, w := range ws { 477 s.assertScopeChange(c, w, nil, nil) 478 } 479 s.assertNoScopeChange(c, ws...) 480 481 // pru0 enters; check detected only by req RUs. 482 assertNotInScope(c, prr.pru0) 483 err := prr.pru0.EnterScope(nil) 484 c.Assert(err, gc.IsNil) 485 rws := func() []*state.RelationScopeWatcher { 486 return []*state.RelationScopeWatcher{ws[2], ws[3]} 487 } 488 for _, w := range rws() { 489 s.assertScopeChange(c, w, []string{"mysql/0"}, nil) 490 } 491 s.assertNoScopeChange(c, ws...) 492 assertInScope(c, prr.pru0) 493 494 // req0 enters; check detected only by pro RUs. 495 assertNotInScope(c, prr.rru0) 496 err = prr.rru0.EnterScope(nil) 497 c.Assert(err, gc.IsNil) 498 pws := func() []*state.RelationScopeWatcher { 499 return []*state.RelationScopeWatcher{ws[0], ws[1]} 500 } 501 for _, w := range pws() { 502 s.assertScopeChange(c, w, []string{"wordpress/0"}, nil) 503 } 504 s.assertNoScopeChange(c, ws...) 505 assertInScope(c, prr.rru0) 506 507 // Stop watches; remaining RUs enter. 508 for _, w := range ws { 509 testing.AssertStop(c, w) 510 } 511 assertNotInScope(c, prr.pru1) 512 err = prr.pru1.EnterScope(nil) 513 c.Assert(err, gc.IsNil) 514 assertInScope(c, prr.pru1) 515 assertNotInScope(c, prr.rru1) 516 err = prr.rru1.EnterScope(nil) 517 c.Assert(err, gc.IsNil) 518 assertInScope(c, prr.rru0) 519 520 // Start new watches, check initial events. 521 ws = prr.watches() 522 for _, w := range ws { 523 defer testing.AssertStop(c, w) 524 } 525 for _, w := range pws() { 526 s.assertScopeChange(c, w, []string{"wordpress/0", "wordpress/1"}, nil) 527 } 528 for _, w := range rws() { 529 s.assertScopeChange(c, w, []string{"mysql/0", "mysql/1"}, nil) 530 } 531 s.assertNoScopeChange(c, ws...) 532 533 // pru0 leaves; check detected only by req RUs. 534 assertInScope(c, prr.pru0) 535 err = prr.pru0.LeaveScope() 536 c.Assert(err, gc.IsNil) 537 for _, w := range rws() { 538 s.assertScopeChange(c, w, nil, []string{"mysql/0"}) 539 } 540 s.assertNoScopeChange(c, ws...) 541 assertNotInScope(c, prr.pru0) 542 543 // rru0 leaves; check detected only by pro RUs. 544 assertInScope(c, prr.rru0) 545 err = prr.rru0.LeaveScope() 546 c.Assert(err, gc.IsNil) 547 for _, w := range pws() { 548 s.assertScopeChange(c, w, nil, []string{"wordpress/0"}) 549 } 550 s.assertNoScopeChange(c, ws...) 551 assertNotInScope(c, prr.rru0) 552 } 553 554 func (s *RelationUnitSuite) TestContainerWatchScope(c *gc.C) { 555 prr := NewProReqRelation(c, &s.ConnSuite, charm.ScopeContainer) 556 557 // Test empty initial events for all RUs. 558 ws := prr.watches() 559 for _, w := range ws { 560 defer testing.AssertStop(c, w) 561 } 562 for _, w := range ws { 563 s.assertScopeChange(c, w, nil, nil) 564 } 565 s.assertNoScopeChange(c, ws...) 566 567 // pru0 enters; check detected only by same-container req. 568 assertNotInScope(c, prr.pru0) 569 err := prr.pru0.EnterScope(nil) 570 c.Assert(err, gc.IsNil) 571 s.assertScopeChange(c, ws[2], []string{"mysql/0"}, nil) 572 s.assertNoScopeChange(c, ws...) 573 assertInScope(c, prr.pru0) 574 575 // req1 enters; check detected only by same-container pro. 576 assertNotInScope(c, prr.rru1) 577 err = prr.rru1.EnterScope(nil) 578 c.Assert(err, gc.IsNil) 579 s.assertScopeChange(c, ws[1], []string{"logging/1"}, nil) 580 s.assertNoScopeChange(c, ws...) 581 assertInScope(c, prr.rru1) 582 583 // Stop watches; remaining RUs enter scope. 584 for _, w := range ws { 585 testing.AssertStop(c, w) 586 } 587 assertNotInScope(c, prr.pru1) 588 err = prr.pru1.EnterScope(nil) 589 c.Assert(err, gc.IsNil) 590 assertNotInScope(c, prr.rru0) 591 err = prr.rru0.EnterScope(nil) 592 c.Assert(err, gc.IsNil) 593 594 // Start new watches, check initial events. 595 ws = prr.watches() 596 for _, w := range ws { 597 defer testing.AssertStop(c, w) 598 } 599 s.assertScopeChange(c, ws[0], []string{"logging/0"}, nil) 600 s.assertScopeChange(c, ws[1], []string{"logging/1"}, nil) 601 s.assertScopeChange(c, ws[2], []string{"mysql/0"}, nil) 602 s.assertScopeChange(c, ws[3], []string{"mysql/1"}, nil) 603 s.assertNoScopeChange(c, ws...) 604 assertInScope(c, prr.pru1) 605 assertInScope(c, prr.rru0) 606 607 // pru0 leaves; check detected only by same-container req. 608 assertInScope(c, prr.pru0) 609 err = prr.pru0.LeaveScope() 610 c.Assert(err, gc.IsNil) 611 s.assertScopeChange(c, ws[2], nil, []string{"mysql/0"}) 612 s.assertNoScopeChange(c, ws...) 613 assertNotInScope(c, prr.pru0) 614 615 // rru0 leaves; check detected only by same-container pro. 616 assertInScope(c, prr.rru0) 617 err = prr.rru0.LeaveScope() 618 c.Assert(err, gc.IsNil) 619 s.assertScopeChange(c, ws[0], nil, []string{"logging/0"}) 620 s.assertNoScopeChange(c, ws...) 621 assertNotInScope(c, prr.rru0) 622 } 623 624 func (s *RelationUnitSuite) assertScopeChange(c *gc.C, w *state.RelationScopeWatcher, entered, left []string) { 625 s.State.StartSync() 626 select { 627 case ch, ok := <-w.Changes(): 628 c.Assert(ok, gc.Equals, true) 629 sort.Strings(entered) 630 sort.Strings(ch.Entered) 631 c.Assert(ch.Entered, gc.DeepEquals, entered) 632 sort.Strings(left) 633 sort.Strings(ch.Left) 634 c.Assert(ch.Left, gc.DeepEquals, left) 635 case <-time.After(coretesting.LongWait): 636 c.Fatalf("no change") 637 } 638 } 639 640 func (s *RelationUnitSuite) assertNoScopeChange(c *gc.C, ws ...*state.RelationScopeWatcher) { 641 s.State.StartSync() 642 for _, w := range ws { 643 select { 644 case ch, ok := <-w.Changes(): 645 c.Fatalf("got unwanted change: %#v, %t", ch, ok) 646 case <-time.After(coretesting.ShortWait): 647 } 648 } 649 } 650 651 type PeerRelation struct { 652 rel *state.Relation 653 svc *state.Service 654 u0, u1, u2, u3 *state.Unit 655 ru0, ru1, ru2, ru3 *state.RelationUnit 656 } 657 658 func NewPeerRelation(c *gc.C, st *state.State) *PeerRelation { 659 svc := state.AddTestingService(c, st, "riak", state.AddTestingCharm(c, st, "riak")) 660 ep, err := svc.Endpoint("ring") 661 c.Assert(err, gc.IsNil) 662 rel, err := st.EndpointsRelation(ep) 663 c.Assert(err, gc.IsNil) 664 pr := &PeerRelation{rel: rel, svc: svc} 665 pr.u0, pr.ru0 = addRU(c, svc, rel, nil) 666 pr.u1, pr.ru1 = addRU(c, svc, rel, nil) 667 pr.u2, pr.ru2 = addRU(c, svc, rel, nil) 668 pr.u3, pr.ru3 = addRU(c, svc, rel, nil) 669 return pr 670 } 671 672 type ProReqRelation struct { 673 rel *state.Relation 674 psvc, rsvc *state.Service 675 pu0, pu1, ru0, ru1 *state.Unit 676 pru0, pru1, rru0, rru1 *state.RelationUnit 677 } 678 679 func NewProReqRelation(c *gc.C, s *ConnSuite, scope charm.RelationScope) *ProReqRelation { 680 psvc := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 681 var rsvc *state.Service 682 if scope == charm.ScopeGlobal { 683 rsvc = s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 684 } else { 685 rsvc = s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 686 } 687 eps, err := s.State.InferEndpoints([]string{"mysql", rsvc.Name()}) 688 c.Assert(err, gc.IsNil) 689 rel, err := s.State.AddRelation(eps...) 690 c.Assert(err, gc.IsNil) 691 prr := &ProReqRelation{rel: rel, psvc: psvc, rsvc: rsvc} 692 prr.pu0, prr.pru0 = addRU(c, psvc, rel, nil) 693 prr.pu1, prr.pru1 = addRU(c, psvc, rel, nil) 694 if scope == charm.ScopeGlobal { 695 prr.ru0, prr.rru0 = addRU(c, rsvc, rel, nil) 696 prr.ru1, prr.rru1 = addRU(c, rsvc, rel, nil) 697 } else { 698 prr.ru0, prr.rru0 = addRU(c, rsvc, rel, prr.pu0) 699 prr.ru1, prr.rru1 = addRU(c, rsvc, rel, prr.pu1) 700 } 701 return prr 702 } 703 704 func (prr *ProReqRelation) watches() []*state.RelationScopeWatcher { 705 return []*state.RelationScopeWatcher{ 706 prr.pru0.WatchScope(), prr.pru1.WatchScope(), 707 prr.rru0.WatchScope(), prr.rru1.WatchScope(), 708 } 709 } 710 711 func addRU(c *gc.C, svc *state.Service, rel *state.Relation, principal *state.Unit) (*state.Unit, *state.RelationUnit) { 712 // Given the service svc in the relation rel, add a unit of svc and create 713 // a RelationUnit with rel. If principal is supplied, svc is assumed to be 714 // subordinate and the unit will be created by temporarily entering the 715 // relation's scope as the principal. 716 var u *state.Unit 717 if principal == nil { 718 unit, err := svc.AddUnit() 719 c.Assert(err, gc.IsNil) 720 u = unit 721 } else { 722 origUnits, err := svc.AllUnits() 723 c.Assert(err, gc.IsNil) 724 pru, err := rel.Unit(principal) 725 c.Assert(err, gc.IsNil) 726 err = pru.EnterScope(nil) // to create the subordinate 727 c.Assert(err, gc.IsNil) 728 err = pru.LeaveScope() // to reset to initial expected state 729 c.Assert(err, gc.IsNil) 730 newUnits, err := svc.AllUnits() 731 c.Assert(err, gc.IsNil) 732 for _, unit := range newUnits { 733 found := false 734 for _, old := range origUnits { 735 if unit.Name() == old.Name() { 736 found = true 737 break 738 } 739 } 740 if !found { 741 u = unit 742 break 743 } 744 } 745 c.Assert(u, gc.NotNil) 746 } 747 preventUnitDestroyRemove(c, u) 748 ru, err := rel.Unit(u) 749 c.Assert(err, gc.IsNil) 750 return u, ru 751 } 752 753 type WatchScopeSuite struct { 754 ConnSuite 755 } 756 757 var _ = gc.Suite(&WatchScopeSuite{}) 758 759 func (s *WatchScopeSuite) TestPeer(c *gc.C) { 760 // Create a service and get a peer relation. 761 riak := s.AddTestingService(c, "riak", s.AddTestingCharm(c, "riak")) 762 riakEP, err := riak.Endpoint("ring") 763 c.Assert(err, gc.IsNil) 764 rels, err := riak.Relations() 765 c.Assert(err, gc.IsNil) 766 c.Assert(rels, gc.HasLen, 1) 767 rel := rels[0] 768 769 // Add some units to the service and set their private addresses; get 770 // the relevant RelationUnits. 771 // (Private addresses should be set by their unit agents on 772 // startup; this test does not include that, but Join expects 773 // the information to be available, and uses it to populate the 774 // relation settings node.) 775 addUnit := func(i int) *state.RelationUnit { 776 unit, err := riak.AddUnit() 777 c.Assert(err, gc.IsNil) 778 err = unit.SetPrivateAddress(fmt.Sprintf("riak%d.example.com", i)) 779 c.Assert(err, gc.IsNil) 780 ru, err := rel.Unit(unit) 781 c.Assert(err, gc.IsNil) 782 c.Assert(ru.Endpoint(), gc.Equals, riakEP) 783 return ru 784 } 785 ru0 := addUnit(0) 786 ru1 := addUnit(1) 787 ru2 := addUnit(2) 788 789 // ---------- Single unit ---------- 790 791 // Start watching the relation from the perspective of the first unit. 792 w0 := ru0.Watch() 793 defer testing.AssertStop(c, w0) 794 w0c := testing.NewRelationUnitsWatcherC(c, s.State, w0) 795 w0c.AssertChange(nil, nil) 796 w0c.AssertNoChange() 797 798 // Join the first unit to the relation, and change the settings, and 799 // check that nothing apparently happens. 800 err = ru0.EnterScope(nil) 801 c.Assert(err, gc.IsNil) 802 changeSettings(c, ru0) 803 w0c.AssertNoChange() 804 805 // ---------- Two units ---------- 806 807 // Now join another unit to the relation... 808 err = ru1.EnterScope(nil) 809 c.Assert(err, gc.IsNil) 810 811 // ...and check that the first relation unit sees the change. 812 expectChanged := []string{"riak/1"} 813 w0c.AssertChange(expectChanged, nil) 814 w0c.AssertNoChange() 815 816 // Join again, check it's a no-op. 817 err = ru1.EnterScope(nil) 818 c.Assert(err, gc.IsNil) 819 w0c.AssertNoChange() 820 821 // Start watching the relation from the perspective of the second unit, 822 // and check that it sees the right state. 823 w1 := ru1.Watch() 824 defer testing.AssertStop(c, w1) 825 w1c := testing.NewRelationUnitsWatcherC(c, s.State, w1) 826 expectChanged = []string{"riak/0"} 827 w1c.AssertChange(expectChanged, nil) 828 w1c.AssertNoChange() 829 830 // ---------- Three units ---------- 831 832 // Whoa, it works. Ok, check the third unit's opinion of the state. 833 w2 := ru2.Watch() 834 defer testing.AssertStop(c, w2) 835 w2c := testing.NewRelationUnitsWatcherC(c, s.State, w2) 836 expectChanged = []string{"riak/0", "riak/1"} 837 w2c.AssertChange(expectChanged, nil) 838 w2c.AssertNoChange() 839 840 // Join the third unit, and check the first and second units see it. 841 err = ru2.EnterScope(nil) 842 c.Assert(err, gc.IsNil) 843 expectChanged = []string{"riak/2"} 844 w0c.AssertChange(expectChanged, nil) 845 w0c.AssertNoChange() 846 w1c.AssertChange(expectChanged, nil) 847 w1c.AssertNoChange() 848 849 // Change the second unit's settings, and check that only 850 // the first and third see changes. 851 changeSettings(c, ru1) 852 w1c.AssertNoChange() 853 expectChanged = []string{"riak/1"} 854 w0c.AssertChange(expectChanged, nil) 855 w0c.AssertNoChange() 856 w2c.AssertChange(expectChanged, nil) 857 w2c.AssertNoChange() 858 859 // ---------- Two units again ---------- 860 861 // Depart the second unit, and check that the first and third detect it. 862 err = ru1.LeaveScope() 863 c.Assert(err, gc.IsNil) 864 expectDeparted := []string{"riak/1"} 865 w0c.AssertChange(nil, expectDeparted) 866 w0c.AssertNoChange() 867 w2c.AssertChange(nil, expectDeparted) 868 w2c.AssertNoChange() 869 870 // Change its settings, and check the others don't observe anything. 871 changeSettings(c, ru1) 872 w0c.AssertNoChange() 873 w2c.AssertNoChange() 874 875 // Check no spurious events showed up on the second unit's watch, and check 876 // it closes cleanly. 877 w1c.AssertNoChange() 878 testing.AssertStop(c, w1) 879 880 // OK, we're done here. Cleanup, and error detection during same, 881 // will be handled by the deferred kill/stop calls. Phew. 882 } 883 884 func (s *WatchScopeSuite) TestProviderRequirerGlobal(c *gc.C) { 885 // Create a pair of services and a relation between them. 886 mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 887 mysqlEP, err := mysql.Endpoint("server") 888 c.Assert(err, gc.IsNil) 889 wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) 890 wordpressEP, err := wordpress.Endpoint("db") 891 c.Assert(err, gc.IsNil) 892 rel, err := s.State.AddRelation(mysqlEP, wordpressEP) 893 c.Assert(err, gc.IsNil) 894 895 // Add some units to the services and set their private addresses. 896 addUnit := func(srv *state.Service, sub string, ep state.Endpoint) *state.RelationUnit { 897 unit, err := srv.AddUnit() 898 c.Assert(err, gc.IsNil) 899 ru, err := rel.Unit(unit) 900 c.Assert(err, gc.IsNil) 901 c.Assert(ru.Endpoint(), gc.Equals, ep) 902 return ru 903 } 904 msru0 := addUnit(mysql, "ms0", mysqlEP) 905 msru1 := addUnit(mysql, "ms1", mysqlEP) 906 wpru0 := addUnit(wordpress, "wp0", wordpressEP) 907 wpru1 := addUnit(wordpress, "wp1", wordpressEP) 908 909 // ---------- Single role active ---------- 910 911 // Watch the relation from the perspective of the first provider unit and 912 // check initial event. 913 msw0 := msru0.Watch() 914 defer testing.AssertStop(c, msw0) 915 msw0c := testing.NewRelationUnitsWatcherC(c, s.State, msw0) 916 msw0c.AssertChange(nil, nil) 917 msw0c.AssertNoChange() 918 919 // Join the unit to the relation, change its settings, and check that 920 // nothing apparently happens. 921 err = msru0.EnterScope(nil) 922 c.Assert(err, gc.IsNil) 923 changeSettings(c, msru0) 924 msw0c.AssertNoChange() 925 926 // Join the second provider unit, start its watch, and check what it thinks the 927 // state of the relation is. 928 err = msru1.EnterScope(nil) 929 c.Assert(err, gc.IsNil) 930 msw1 := msru1.Watch() 931 defer testing.AssertStop(c, msw1) 932 msw1c := testing.NewRelationUnitsWatcherC(c, s.State, msw1) 933 msw1c.AssertChange(nil, nil) 934 msw1c.AssertNoChange() 935 936 // Change the unit's settings, and check that neither provider unit 937 // observes any change. 938 changeSettings(c, msru1) 939 msw1c.AssertNoChange() 940 msw0c.AssertNoChange() 941 942 // ---------- Two roles active ---------- 943 944 // Start watches from both requirer units' perspectives, and check that 945 // they see the provider units. 946 expectChanged := []string{"mysql/0", "mysql/1"} 947 wpw0 := wpru0.Watch() 948 defer testing.AssertStop(c, wpw0) 949 wpw0c := testing.NewRelationUnitsWatcherC(c, s.State, wpw0) 950 wpw0c.AssertChange(expectChanged, nil) 951 wpw0c.AssertNoChange() 952 wpw1 := wpru1.Watch() 953 defer testing.AssertStop(c, wpw1) 954 wpw1c := testing.NewRelationUnitsWatcherC(c, s.State, wpw1) 955 wpw1c.AssertChange(expectChanged, nil) 956 wpw1c.AssertNoChange() 957 958 // Join the first requirer unit, and check the provider units see it. 959 err = wpru0.EnterScope(nil) 960 c.Assert(err, gc.IsNil) 961 expectChanged = []string{"wordpress/0"} 962 msw0c.AssertChange(expectChanged, nil) 963 msw0c.AssertNoChange() 964 msw1c.AssertChange(expectChanged, nil) 965 msw1c.AssertNoChange() 966 967 // Join again, check no-op. 968 err = wpru0.EnterScope(nil) 969 c.Assert(err, gc.IsNil) 970 msw0c.AssertNoChange() 971 msw1c.AssertNoChange() 972 973 // Join the second requirer, and check the provider units see the change. 974 err = wpru1.EnterScope(nil) 975 c.Assert(err, gc.IsNil) 976 expectChanged = []string{"wordpress/1"} 977 msw0c.AssertChange(expectChanged, nil) 978 msw0c.AssertNoChange() 979 msw1c.AssertChange(expectChanged, nil) 980 msw1c.AssertNoChange() 981 982 // Verify that neither requirer has observed any change to the relation. 983 wpw0c.AssertNoChange() 984 wpw1c.AssertNoChange() 985 986 // Change settings for the first requirer, check providers see it... 987 changeSettings(c, wpru0) 988 expectChanged = []string{"wordpress/0"} 989 msw0c.AssertChange(expectChanged, nil) 990 msw0c.AssertNoChange() 991 msw1c.AssertChange(expectChanged, nil) 992 msw1c.AssertNoChange() 993 994 // ...and requirers don't. 995 wpw0c.AssertNoChange() 996 wpw1c.AssertNoChange() 997 998 // Depart the second requirer and check the providers see it... 999 err = wpru1.LeaveScope() 1000 c.Assert(err, gc.IsNil) 1001 expectDeparted := []string{"wordpress/1"} 1002 msw0c.AssertChange(nil, expectDeparted) 1003 msw0c.AssertNoChange() 1004 msw1c.AssertChange(nil, expectDeparted) 1005 msw1c.AssertNoChange() 1006 1007 // ...and the requirers don't. 1008 wpw0c.AssertNoChange() 1009 wpw1c.AssertNoChange() 1010 1011 // Cleanup handled by defers as before. 1012 } 1013 1014 func (s *WatchScopeSuite) TestProviderRequirerContainer(c *gc.C) { 1015 // Create a pair of services and a relation between them. 1016 mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) 1017 mysqlEP, err := mysql.Endpoint("juju-info") 1018 c.Assert(err, gc.IsNil) 1019 logging := s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) 1020 loggingEP, err := logging.Endpoint("info") 1021 c.Assert(err, gc.IsNil) 1022 rel, err := s.State.AddRelation(mysqlEP, loggingEP) 1023 c.Assert(err, gc.IsNil) 1024 1025 // Change mysqlEP to match the endpoint that will actually be used by the relation. 1026 mysqlEP.Scope = charm.ScopeContainer 1027 1028 // Add some units to the services and set their private addresses. 1029 addUnits := func(i int) (*state.RelationUnit, *state.RelationUnit) { 1030 msu, err := mysql.AddUnit() 1031 c.Assert(err, gc.IsNil) 1032 msru, err := rel.Unit(msu) 1033 c.Assert(err, gc.IsNil) 1034 c.Assert(msru.Endpoint(), gc.Equals, mysqlEP) 1035 err = msru.EnterScope(nil) 1036 c.Assert(err, gc.IsNil) 1037 err = msru.LeaveScope() 1038 c.Assert(err, gc.IsNil) 1039 lgu, err := s.State.Unit("logging/" + strconv.Itoa(i)) 1040 c.Assert(err, gc.IsNil) 1041 lgru, err := rel.Unit(lgu) 1042 c.Assert(err, gc.IsNil) 1043 c.Assert(lgru.Endpoint(), gc.Equals, loggingEP) 1044 return msru, lgru 1045 } 1046 msru0, lgru0 := addUnits(0) 1047 msru1, lgru1 := addUnits(1) 1048 1049 // ---------- Single role active ---------- 1050 1051 // Start watching the relation from the perspective of the first unit, and 1052 // check the initial event. 1053 msw0 := msru0.Watch() 1054 defer testing.AssertStop(c, msw0) 1055 msw0c := testing.NewRelationUnitsWatcherC(c, s.State, msw0) 1056 msw0c.AssertChange(nil, nil) 1057 msw0c.AssertNoChange() 1058 1059 // Join the unit to the relation, change its settings, and check that 1060 // nothing apparently happens. 1061 err = msru0.EnterScope(nil) 1062 c.Assert(err, gc.IsNil) 1063 changeSettings(c, msru0) 1064 msw0c.AssertNoChange() 1065 1066 // Watch the relation from the perspective of the second provider, and 1067 // check initial event. 1068 msw1 := msru1.Watch() 1069 defer testing.AssertStop(c, msw1) 1070 msw1c := testing.NewRelationUnitsWatcherC(c, s.State, msw1) 1071 msw1c.AssertChange(nil, nil) 1072 msw1c.AssertNoChange() 1073 1074 // Join the second provider unit to the relation, and check that neither 1075 // watching unit observes any change. 1076 err = msru1.EnterScope(nil) 1077 c.Assert(err, gc.IsNil) 1078 msw1c.AssertNoChange() 1079 msw0c.AssertNoChange() 1080 1081 // Change the unit's settings, and check that nothing apparently happens. 1082 changeSettings(c, msru1) 1083 msw1c.AssertNoChange() 1084 msw0c.AssertNoChange() 1085 1086 // ---------- Two roles active ---------- 1087 1088 // Start a watch from the first requirer unit's perspective, and check it 1089 // only sees the first provider (with which it shares a container). 1090 lgw0 := lgru0.Watch() 1091 defer testing.AssertStop(c, lgw0) 1092 lgw0c := testing.NewRelationUnitsWatcherC(c, s.State, lgw0) 1093 expectChanged := []string{"mysql/0"} 1094 lgw0c.AssertChange(expectChanged, nil) 1095 lgw0c.AssertNoChange() 1096 1097 // Join the first requirer unit, and check that only the first provider 1098 // observes the change. 1099 err = lgru0.EnterScope(nil) 1100 c.Assert(err, gc.IsNil) 1101 expectChanged = []string{"logging/0"} 1102 msw0c.AssertChange(expectChanged, nil) 1103 msw0c.AssertNoChange() 1104 msw1c.AssertNoChange() 1105 lgw0c.AssertNoChange() 1106 1107 // Watch from the second requirer's perspective, and check it only sees the 1108 // second provider. 1109 lgw1 := lgru1.Watch() 1110 defer testing.AssertStop(c, lgw1) 1111 lgw1c := testing.NewRelationUnitsWatcherC(c, s.State, lgw1) 1112 expectChanged = []string{"mysql/1"} 1113 lgw1c.AssertChange(expectChanged, nil) 1114 lgw1c.AssertNoChange() 1115 1116 // Join the second requirer, and check that the first provider observes it... 1117 err = lgru1.EnterScope(nil) 1118 c.Assert(err, gc.IsNil) 1119 expectChanged = []string{"logging/1"} 1120 msw1c.AssertChange(expectChanged, nil) 1121 msw1c.AssertNoChange() 1122 1123 // ...and that nothing else sees anything. 1124 msw0c.AssertNoChange() 1125 lgw0c.AssertNoChange() 1126 lgw1c.AssertNoChange() 1127 1128 // Change the second provider's settings and check that the second 1129 // requirer notices... 1130 changeSettings(c, msru1) 1131 expectChanged = []string{"mysql/1"} 1132 lgw1c.AssertChange(expectChanged, nil) 1133 lgw1c.AssertNoChange() 1134 1135 // ...but that nothing else does. 1136 msw0c.AssertNoChange() 1137 msw1c.AssertNoChange() 1138 msw0c.AssertNoChange() 1139 1140 // Finally, depart the first provider, and check that only the first 1141 // requirer observes any change. 1142 err = msru0.LeaveScope() 1143 c.Assert(err, gc.IsNil) 1144 expectDeparted := []string{"mysql/0"} 1145 lgw0c.AssertChange(nil, expectDeparted) 1146 lgw0c.AssertNoChange() 1147 lgw1c.AssertNoChange() 1148 msw0c.AssertNoChange() 1149 msw1c.AssertNoChange() 1150 1151 // Again, I think we're done, and can be comfortable that the appropriate 1152 // connections are in place. 1153 } 1154 1155 func changeSettings(c *gc.C, ru *state.RelationUnit) { 1156 node, err := ru.Settings() 1157 c.Assert(err, gc.IsNil) 1158 value, _ := node.Get("value") 1159 v, _ := value.(int) 1160 node.Set("value", v+1) 1161 _, err = node.Write() 1162 c.Assert(err, gc.IsNil) 1163 }