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  }