github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/state_leader_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/utils/clock" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/mgo.v2/txn" 14 15 "github.com/juju/juju/core/leadership" 16 "github.com/juju/juju/state" 17 coretesting "github.com/juju/juju/testing" 18 ) 19 20 type LeadershipSuite struct { 21 ConnSuite 22 clock *coretesting.Clock 23 checker leadership.Checker 24 claimer leadership.Claimer 25 } 26 27 var _ = gc.Suite(&LeadershipSuite{}) 28 29 func (s *LeadershipSuite) SetUpSuite(c *gc.C) { 30 s.ConnSuite.SetUpSuite(c) 31 s.PatchValue(&state.GetClock, func() clock.Clock { 32 return s.clock 33 }) 34 } 35 36 func (s *LeadershipSuite) SetUpTest(c *gc.C) { 37 s.clock = coretesting.NewClock(time.Now()) 38 s.ConnSuite.SetUpTest(c) 39 s.checker = s.State.LeadershipChecker() 40 s.claimer = s.State.LeadershipClaimer() 41 } 42 43 func (s *LeadershipSuite) TestClaimValidatesServiceName(c *gc.C) { 44 err := s.claimer.ClaimLeadership("not/a/service", "u/0", time.Minute) 45 c.Check(err, gc.ErrorMatches, `cannot claim lease "not/a/service": not a service name`) 46 c.Check(err, jc.Satisfies, errors.IsNotValid) 47 } 48 49 func (s *LeadershipSuite) TestClaimValidatesUnitName(c *gc.C) { 50 err := s.claimer.ClaimLeadership("service", "not/a/unit", time.Minute) 51 c.Check(err, gc.ErrorMatches, `cannot claim lease for holder "not/a/unit": not a unit name`) 52 c.Check(err, jc.Satisfies, errors.IsNotValid) 53 } 54 55 func (s *LeadershipSuite) TestClaimValidateDuration(c *gc.C) { 56 err := s.claimer.ClaimLeadership("service", "u/0", 0) 57 c.Check(err, gc.ErrorMatches, `cannot claim lease for 0: non-positive`) 58 c.Check(err, jc.Satisfies, errors.IsNotValid) 59 } 60 61 func (s *LeadershipSuite) TestCheckValidatesServiceName(c *gc.C) { 62 token := s.checker.LeadershipCheck("not/a/service", "u/0") 63 err := token.Check(nil) 64 c.Check(err, gc.ErrorMatches, `cannot check lease "not/a/service": not a service name`) 65 c.Check(err, jc.Satisfies, errors.IsNotValid) 66 } 67 68 func (s *LeadershipSuite) TestCheckValidatesUnitName(c *gc.C) { 69 token := s.checker.LeadershipCheck("service", "not/a/unit") 70 err := token.Check(nil) 71 c.Check(err, gc.ErrorMatches, `cannot check holder "not/a/unit": not a unit name`) 72 c.Check(err, jc.Satisfies, errors.IsNotValid) 73 } 74 75 func (s *LeadershipSuite) TestBlockValidatesServiceName(c *gc.C) { 76 err := s.claimer.BlockUntilLeadershipReleased("not/a/service") 77 c.Check(err, gc.ErrorMatches, `cannot wait for lease "not/a/service" expiry: not a service name`) 78 c.Check(err, jc.Satisfies, errors.IsNotValid) 79 } 80 81 func (s *LeadershipSuite) TestClaimExpire(c *gc.C) { 82 83 // Claim on behalf of one unit. 84 err := s.claimer.ClaimLeadership("service", "service/0", time.Minute) 85 c.Assert(err, jc.ErrorIsNil) 86 87 // Claim on behalf of another. 88 err = s.claimer.ClaimLeadership("service", "service/1", time.Minute) 89 c.Check(err, gc.Equals, leadership.ErrClaimDenied) 90 91 // Allow the first claim to expire. 92 s.expire(c, "service") 93 94 // Reclaim on behalf of another. 95 err = s.claimer.ClaimLeadership("service", "service/1", time.Minute) 96 c.Assert(err, jc.ErrorIsNil) 97 } 98 99 func (s *LeadershipSuite) TestCheck(c *gc.C) { 100 101 // Create a single token for use by the whole test. 102 token := s.checker.LeadershipCheck("service", "service/0") 103 104 // Claim leadership. 105 err := s.claimer.ClaimLeadership("service", "service/0", time.Minute) 106 c.Assert(err, jc.ErrorIsNil) 107 108 // Check token reports current leadership state. 109 var ops []txn.Op 110 err = token.Check(&ops) 111 c.Check(err, jc.ErrorIsNil) 112 c.Check(ops, gc.HasLen, 1) 113 114 // Allow leadership to expire. 115 s.expire(c, "service") 116 117 // Check leadership still reported accurately. 118 var ops2 []txn.Op 119 err = token.Check(&ops2) 120 c.Check(err, gc.ErrorMatches, `"service/0" is not leader of "service"`) 121 c.Check(ops2, gc.IsNil) 122 } 123 124 func (s *LeadershipSuite) TestHackLeadershipUnblocksClaimer(c *gc.C) { 125 err := s.claimer.ClaimLeadership("blah", "blah/0", time.Minute) 126 c.Assert(err, jc.ErrorIsNil) 127 128 s.State.HackLeadership() 129 select { 130 case err := <-s.expiryChan("blah"): 131 c.Check(err, gc.ErrorMatches, "lease manager stopped") 132 case <-time.After(coretesting.LongWait): 133 c.Fatalf("timed out while waiting for unblock") 134 } 135 } 136 137 func (s *LeadershipSuite) expire(c *gc.C, serviceName string) { 138 s.clock.Advance(time.Hour) 139 select { 140 case err := <-s.expiryChan(serviceName): 141 c.Assert(err, jc.ErrorIsNil) 142 case <-time.After(coretesting.LongWait): 143 c.Fatalf("never unblocked") 144 } 145 } 146 147 func (s *LeadershipSuite) expiryChan(serviceName string) <-chan error { 148 expired := make(chan error, 1) 149 go func() { 150 expired <- s.claimer.BlockUntilLeadershipReleased("blah") 151 }() 152 return expired 153 }