1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
jc "github.com/juju/testing/checkers"
10
gc "gopkg.in/check.v1"
12
"github.com/juju/juju/core/lease"
15
// ClientOperationSuite verifies behaviour when claiming, extending, and expiring leases.
16
type ClientOperationSuite struct {
20
var _ = gc.Suite(&ClientOperationSuite{})
22
func (s *ClientOperationSuite) TestClaimLease(c *gc.C) {
23
fix := s.EasyFixture(c)
25
leaseDuration := time.Minute
26
err := fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
27
c.Assert(err, jc.ErrorIsNil)
29
// The lease is claimed, for an exact duration.
30
c.Check("name", fix.Holder(), "holder")
31
exactExpiry := fix.Zero.Add(leaseDuration)
32
c.Check("name", fix.Expiry(), exactExpiry)
35
func (s *ClientOperationSuite) TestClaimMultipleLeases(c *gc.C) {
36
fix := s.EasyFixture(c)
38
err := fix.Client.ClaimLease("short", lease.Request{"holder", time.Second})
39
c.Assert(err, jc.ErrorIsNil)
40
err = fix.Client.ClaimLease("medium", lease.Request{"grasper", time.Minute})
41
c.Assert(err, jc.ErrorIsNil)
42
err = fix.Client.ClaimLease("long", lease.Request{"clutcher", time.Hour})
43
c.Assert(err, jc.ErrorIsNil)
45
check := func(name, holder string, duration time.Duration) {
46
c.Check(name, fix.Holder(), holder)
47
expiry := fix.Zero.Add(duration)
48
c.Check(name, fix.Expiry(), expiry)
50
check("short", "holder", time.Second)
51
check("medium", "grasper", time.Minute)
52
check("long", "clutcher", time.Hour)
55
func (s *ClientOperationSuite) TestCannotClaimLeaseTwice(c *gc.C) {
56
fix := s.EasyFixture(c)
58
leaseDuration := time.Minute
59
err := fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
60
c.Assert(err, jc.ErrorIsNil)
62
// The lease is claimed and cannot be claimed again...
63
err = fix.Client.ClaimLease("name", lease.Request{"other-holder", leaseDuration})
64
c.Check(err, gc.Equals, lease.ErrInvalid)
66
// ...not even for the same holder...
67
err = fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
68
c.Check(err, gc.Equals, lease.ErrInvalid)
70
// ...not even when the lease has expired.
71
fix.Clock.Advance(time.Hour)
72
err = fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
73
c.Check(err, gc.Equals, lease.ErrInvalid)
76
func (s *ClientOperationSuite) TestExtendLease(c *gc.C) {
77
fix := s.EasyFixture(c)
78
err := fix.Client.ClaimLease("name", lease.Request{"holder", time.Second})
79
c.Assert(err, jc.ErrorIsNil)
81
leaseDuration := time.Minute
82
err = fix.Client.ExtendLease("name", lease.Request{"holder", leaseDuration})
83
c.Assert(err, jc.ErrorIsNil)
85
// The lease is extended, *to* (not by) the exact duration requested.
86
c.Check("name", fix.Holder(), "holder")
87
exactExpiry := fix.Zero.Add(leaseDuration)
88
c.Check("name", fix.Expiry(), exactExpiry)
91
func (s *ClientOperationSuite) TestCanExtendStaleLease(c *gc.C) {
92
fix := s.EasyFixture(c)
93
err := fix.Client.ClaimLease("name", lease.Request{"holder", time.Second})
94
c.Assert(err, jc.ErrorIsNil)
96
// Advance the clock past lease expiry time, then extend.
97
fix.Clock.Advance(time.Minute)
98
extendTime := fix.Clock.Now()
99
leaseDuration := time.Minute
100
err = fix.Client.ExtendLease("name", lease.Request{"holder", leaseDuration})
101
c.Assert(err, jc.ErrorIsNil)
103
// The lease is extended fine, *to* (not by) the exact duration requested.
104
c.Check("name", fix.Holder(), "holder")
105
exactExpiry := extendTime.Add(leaseDuration)
106
c.Check("name", fix.Expiry(), exactExpiry)
109
func (s *ClientOperationSuite) TestExtendLeaseCannotChangeHolder(c *gc.C) {
110
fix := s.EasyFixture(c)
111
err := fix.Client.ClaimLease("name", lease.Request{"holder", time.Second})
112
c.Assert(err, jc.ErrorIsNil)
114
leaseDuration := time.Minute
115
err = fix.Client.ExtendLease("name", lease.Request{"other-holder", leaseDuration})
116
c.Assert(err, gc.Equals, lease.ErrInvalid)
119
func (s *ClientOperationSuite) TestExtendLeaseCannotShortenLease(c *gc.C) {
120
fix := s.EasyFixture(c)
121
leaseDuration := time.Minute
122
err := fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
123
c.Assert(err, jc.ErrorIsNil)
125
// A non-extension will succeed -- we can still honour all guarantees
126
// implied by a nil error...
127
err = fix.Client.ExtendLease("name", lease.Request{"holder", time.Second})
128
c.Assert(err, jc.ErrorIsNil)
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("name", fix.Holder(), "holder")
133
exactExpiry := fix.Zero.Add(leaseDuration)
134
c.Check("name", fix.Expiry(), exactExpiry)
137
func (s *ClientOperationSuite) TestCannotExpireLeaseBeforeExpiry(c *gc.C) {
138
fix := s.EasyFixture(c)
139
leaseDuration := time.Minute
140
err := fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
141
c.Assert(err, jc.ErrorIsNil)
143
// It can't be expired until after the duration has elapsed.
144
fix.Clock.Advance(leaseDuration)
145
err = fix.Client.ExpireLease("name")
146
c.Assert(err, gc.Equals, lease.ErrInvalid)
149
func (s *ClientOperationSuite) TestExpireLeaseAfterExpiry(c *gc.C) {
150
fix := s.EasyFixture(c)
151
leaseDuration := time.Minute
152
err := fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
153
c.Assert(err, jc.ErrorIsNil)
155
// It can be expired as soon as the duration has elapsed.
156
fix.Clock.Advance(leaseDuration + time.Nanosecond)
157
err = fix.Client.ExpireLease("name")
158
c.Assert(err, jc.ErrorIsNil)
159
c.Check("name", fix.Holder(), "")
162
func (s *ClientOperationSuite) TestCannotExpireUnheldLease(c *gc.C) {
163
fix := s.EasyFixture(c)
164
err := fix.Client.ExpireLease("name")
165
c.Assert(err, gc.Equals, lease.ErrInvalid)