func (s *RelationerSuite) assertHook(c *gc.C, expect hook.Info) { s.BackingState.StartSync() // We must ensure the local state dir exists first. c.Assert(s.dir.Ensure(), gc.IsNil) select { case hi, ok := <-s.hooks: c.Assert(ok, gc.Equals, true) expect.ChangeVersion = hi.ChangeVersion c.Assert(hi, gc.DeepEquals, expect) c.Assert(s.dir.Write(hi), gc.Equals, nil) case <-time.After(coretesting.LongWait): c.Fatalf("timed out waiting for %#v", expect) } }
func (s *RelationerSuite) TestPrepareCommitHooks(c *gc.C) { r := uniter.NewRelationer(s.apiRelUnit, s.dir, s.hooks) err := r.Join() c.Assert(err, gc.IsNil) ctx := r.Context() c.Assert(ctx.UnitNames(), gc.HasLen, 0) // Check preparing an invalid hook changes nothing. changed := hook.Info{ Kind: hooks.RelationChanged, RemoteUnit: "u/1", ChangeVersion: 7, } _, err = r.PrepareHook(changed) c.Assert(err, gc.ErrorMatches, `inappropriate "relation-changed" for "u/1": unit has not joined`) c.Assert(ctx.UnitNames(), gc.HasLen, 0) c.Assert(s.dir.State().Members, gc.HasLen, 0) // Check preparing a valid hook updates the context, but not persistent // relation state. joined := hook.Info{ Kind: hooks.RelationJoined, RemoteUnit: "u/1", } name, err := r.PrepareHook(joined) c.Assert(err, gc.IsNil) c.Assert(s.dir.State().Members, gc.HasLen, 0) c.Assert(name, gc.Equals, "ring-relation-joined") c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1"}) // Check that preparing the following hook fails as before... _, err = r.PrepareHook(changed) c.Assert(err, gc.ErrorMatches, `inappropriate "relation-changed" for "u/1": unit has not joined`) c.Assert(s.dir.State().Members, gc.HasLen, 0) c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1"}) // ...but that committing the previous hook updates the persistent // relation state... err = r.CommitHook(joined) c.Assert(err, gc.IsNil) c.Assert(s.dir.State().Members, gc.DeepEquals, map[string]int64{"u/1": 0}) c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1"}) // ...and allows us to prepare the next hook... name, err = r.PrepareHook(changed) c.Assert(err, gc.IsNil) c.Assert(name, gc.Equals, "ring-relation-changed") c.Assert(s.dir.State().Members, gc.DeepEquals, map[string]int64{"u/1": 0}) c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1"}) // ...and commit it. err = r.CommitHook(changed) c.Assert(err, gc.IsNil) c.Assert(s.dir.State().Members, gc.DeepEquals, map[string]int64{"u/1": 7}) c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1"}) // To verify implied behaviour above, prepare a new joined hook with // missing membership information, and check relation context // membership is updated appropriately... joined.RemoteUnit = "u/2" joined.ChangeVersion = 3 name, err = r.PrepareHook(joined) c.Assert(err, gc.IsNil) c.Assert(s.dir.State().Members, gc.HasLen, 1) c.Assert(name, gc.Equals, "ring-relation-joined") c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1", "u/2"}) // ...and so is relation state on commit. err = r.CommitHook(joined) c.Assert(err, gc.IsNil) c.Assert(s.dir.State().Members, gc.DeepEquals, map[string]int64{"u/1": 7, "u/2": 3}) c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1", "u/2"}) }
func (s *RelationerSuite) TestPrepareCommitHooks(c *gc.C) { r := uniter.NewRelationer(s.apiRelUnit, s.dir, s.hooks) err := r.Join() c.Assert(err, jc.ErrorIsNil) assertMembers := func(expect map[string]int64) { c.Assert(s.dir.State().Members, jc.DeepEquals, expect) expectNames := make([]string, 0, len(expect)) for name := range expect { expectNames = append(expectNames, name) } c.Assert(r.ContextInfo().MemberNames, jc.SameContents, expectNames) } assertMembers(map[string]int64{}) // Check preparing an invalid hook changes nothing. changed := hook.Info{ Kind: hooks.RelationChanged, RemoteUnit: "u/1", ChangeVersion: 7, } _, err = r.PrepareHook(changed) c.Assert(err, gc.ErrorMatches, `inappropriate "relation-changed" for "u/1": unit has not joined`) assertMembers(map[string]int64{}) // Check preparing a valid hook updates neither the context nor persistent // relation state. joined := hook.Info{ Kind: hooks.RelationJoined, RemoteUnit: "u/1", } name, err := r.PrepareHook(joined) c.Assert(err, jc.ErrorIsNil) c.Assert(name, gc.Equals, "ring-relation-joined") assertMembers(map[string]int64{}) // Check that preparing the following hook fails as before... _, err = r.PrepareHook(changed) c.Assert(err, gc.ErrorMatches, `inappropriate "relation-changed" for "u/1": unit has not joined`) assertMembers(map[string]int64{}) // ...but that committing the previous hook updates the persistent // relation state... err = r.CommitHook(joined) c.Assert(err, jc.ErrorIsNil) assertMembers(map[string]int64{"u/1": 0}) // ...and allows us to prepare the next hook... name, err = r.PrepareHook(changed) c.Assert(err, jc.ErrorIsNil) c.Assert(name, gc.Equals, "ring-relation-changed") assertMembers(map[string]int64{"u/1": 0}) // ...and commit it. err = r.CommitHook(changed) c.Assert(err, jc.ErrorIsNil) assertMembers(map[string]int64{"u/1": 7}) // To verify implied behaviour above, prepare a new joined hook with // missing membership information, and check relation context // membership is stil not updated... joined.RemoteUnit = "u/2" joined.ChangeVersion = 3 name, err = r.PrepareHook(joined) c.Assert(err, jc.ErrorIsNil) c.Assert(name, gc.Equals, "ring-relation-joined") assertMembers(map[string]int64{"u/1": 7}) // ...until commit, at which point so is relation state. err = r.CommitHook(joined) c.Assert(err, jc.ErrorIsNil) assertMembers(map[string]int64{"u/1": 7, "u/2": 3}) }