github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/state/lease/store_operation_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package lease_test 5 6 import ( 7 "time" // Only used for time types. 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/core/lease" 13 ) 14 15 // StoreOperationSuite verifies behaviour when claiming, extending, and expiring leases. 16 type StoreOperationSuite struct { 17 FixtureSuite 18 } 19 20 var _ = gc.Suite(&StoreOperationSuite{}) 21 22 func (s *StoreOperationSuite) TestClaimLease(c *gc.C) { 23 fix := s.EasyFixture(c) 24 25 leaseDuration := time.Minute 26 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 27 c.Assert(err, jc.ErrorIsNil) 28 29 // The lease is claimed, for an exact duration. 30 c.Check(key("name"), fix.Holder(), "holder") 31 exactExpiry := fix.Zero.Add(leaseDuration) 32 c.Check(key("name"), fix.Expiry(), exactExpiry) 33 } 34 35 func (s *StoreOperationSuite) TestClaimMultipleLeases(c *gc.C) { 36 fix := s.EasyFixture(c) 37 38 err := fix.Store.ClaimLease(key("short"), lease.Request{"holder", time.Second}) 39 c.Assert(err, jc.ErrorIsNil) 40 err = fix.Store.ClaimLease(key("medium"), lease.Request{"grasper", time.Minute}) 41 c.Assert(err, jc.ErrorIsNil) 42 err = fix.Store.ClaimLease(key("long"), lease.Request{"clutcher", time.Hour}) 43 c.Assert(err, jc.ErrorIsNil) 44 45 check := func(name, holder string, duration time.Duration) { 46 c.Check(key(name), fix.Holder(), holder) 47 expiry := fix.Zero.Add(duration) 48 c.Check(key(name), fix.Expiry(), expiry) 49 } 50 check("short", "holder", time.Second) 51 check("medium", "grasper", time.Minute) 52 check("long", "clutcher", time.Hour) 53 } 54 55 func (s *StoreOperationSuite) TestCannotClaimLeaseTwice(c *gc.C) { 56 fix := s.EasyFixture(c) 57 58 leaseDuration := time.Minute 59 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 60 c.Assert(err, jc.ErrorIsNil) 61 62 // The lease is claimed and cannot be claimed again... 63 err = fix.Store.ClaimLease(key("name"), lease.Request{"other-holder", leaseDuration}) 64 c.Check(err, gc.Equals, lease.ErrInvalid) 65 66 // ...not even for the same holder... 67 err = fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 68 c.Check(err, gc.Equals, lease.ErrInvalid) 69 70 // ...not even when the lease has expired. 71 fix.GlobalClock.Advance(time.Hour) 72 err = fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 73 c.Check(err, gc.Equals, lease.ErrInvalid) 74 } 75 76 func (s *StoreOperationSuite) TestExtendLease(c *gc.C) { 77 fix := s.EasyFixture(c) 78 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", time.Second}) 79 c.Assert(err, jc.ErrorIsNil) 80 81 leaseDuration := time.Minute 82 err = fix.Store.ExtendLease(key("name"), lease.Request{"holder", leaseDuration}) 83 c.Assert(err, jc.ErrorIsNil) 84 85 // The lease is extended, *to* (not by) the exact duration requested. 86 c.Check(key("name"), fix.Holder(), "holder") 87 exactExpiry := fix.Zero.Add(leaseDuration) 88 c.Check(key("name"), fix.Expiry(), exactExpiry) 89 } 90 91 func (s *StoreOperationSuite) TestCanExtendStaleLease(c *gc.C) { 92 fix := s.EasyFixture(c) 93 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", time.Second}) 94 c.Assert(err, jc.ErrorIsNil) 95 96 // Advance the clock past lease expiry time, then extend. 97 fix.LocalClock.Advance(time.Minute) 98 extendTime := fix.LocalClock.Now() 99 leaseDuration := time.Minute 100 err = fix.Store.ExtendLease(key("name"), lease.Request{"holder", leaseDuration}) 101 c.Assert(err, jc.ErrorIsNil) 102 103 // The lease is extended fine, *to* (not by) the exact duration requested. 104 c.Check(key("name"), fix.Holder(), "holder") 105 exactExpiry := extendTime.Add(leaseDuration) 106 c.Check(key("name"), fix.Expiry(), exactExpiry) 107 } 108 109 func (s *StoreOperationSuite) TestExtendLeaseCannotChangeHolder(c *gc.C) { 110 fix := s.EasyFixture(c) 111 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", time.Second}) 112 c.Assert(err, jc.ErrorIsNil) 113 114 leaseDuration := time.Minute 115 err = fix.Store.ExtendLease(key("name"), lease.Request{"other-holder", leaseDuration}) 116 c.Assert(err, gc.Equals, lease.ErrInvalid) 117 } 118 119 func (s *StoreOperationSuite) TestExtendLeaseCannotShortenLease(c *gc.C) { 120 fix := s.EasyFixture(c) 121 leaseDuration := time.Minute 122 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 123 c.Assert(err, jc.ErrorIsNil) 124 125 // A non-extension will succeed -- we can still honour all guarantees 126 // implied by a nil error... 127 err = fix.Store.ExtendLease(key("name"), lease.Request{"holder", time.Second}) 128 c.Assert(err, jc.ErrorIsNil) 129 130 // ...but we can't make it any shorter, lest we fail to honour the 131 // guarantees implied by the original lease. 132 c.Check(key("name"), fix.Holder(), "holder") 133 exactExpiry := fix.Zero.Add(leaseDuration) 134 c.Check(key("name"), fix.Expiry(), exactExpiry) 135 } 136 137 func (s *StoreOperationSuite) TestCannotExpireLeaseBeforeExpiry(c *gc.C) { 138 fix := s.EasyFixture(c) 139 leaseDuration := time.Minute 140 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 141 c.Assert(err, jc.ErrorIsNil) 142 143 // It can't be expired until after the duration has elapsed. 144 fix.GlobalClock.Advance(leaseDuration) 145 err = fix.Store.ExpireLease(key("name")) 146 c.Assert(err, gc.Equals, lease.ErrInvalid) 147 } 148 149 func (s *StoreOperationSuite) TestExpireLeaseAfterExpiry(c *gc.C) { 150 fix := s.EasyFixture(c) 151 leaseDuration := time.Minute 152 err := fix.Store.ClaimLease(key("name"), lease.Request{"holder", leaseDuration}) 153 c.Assert(err, jc.ErrorIsNil) 154 155 // It can be expired as soon as the duration has elapsed 156 // *on the global clock*. The amount of time elapsed on 157 // the local clock is inconsequential. 158 fix.LocalClock.Advance(leaseDuration + time.Nanosecond) 159 err = fix.Store.ExpireLease(key("name")) 160 c.Assert(err, gc.Equals, lease.ErrInvalid) 161 162 fix.GlobalClock.Advance(leaseDuration + time.Nanosecond) 163 err = fix.Store.ExpireLease(key("name")) 164 c.Assert(err, jc.ErrorIsNil) 165 c.Check(key("name"), fix.Holder(), "") 166 } 167 168 func (s *StoreOperationSuite) TestCannotExpireUnheldLease(c *gc.C) { 169 fix := s.EasyFixture(c) 170 err := fix.Store.ExpireLease(key("name")) 171 c.Assert(err, gc.Equals, lease.ErrInvalid) 172 }