github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/lease/client_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"
     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  // ClientOperationSuite verifies behaviour when claiming, extending, and expiring leases.
    16  type ClientOperationSuite struct {
    17  	FixtureSuite
    18  }
    19  
    20  var _ = gc.Suite(&ClientOperationSuite{})
    21  
    22  func (s *ClientOperationSuite) TestClaimLease(c *gc.C) {
    23  	fix := s.EasyFixture(c)
    24  
    25  	leaseDuration := time.Minute
    26  	err := fix.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
    27  	c.Assert(err, jc.ErrorIsNil)
    28  
    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)
    33  }
    34  
    35  func (s *ClientOperationSuite) TestClaimMultipleLeases(c *gc.C) {
    36  	fix := s.EasyFixture(c)
    37  
    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)
    44  
    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)
    49  	}
    50  	check("short", "holder", time.Second)
    51  	check("medium", "grasper", time.Minute)
    52  	check("long", "clutcher", time.Hour)
    53  }
    54  
    55  func (s *ClientOperationSuite) TestCannotClaimLeaseTwice(c *gc.C) {
    56  	fix := s.EasyFixture(c)
    57  
    58  	leaseDuration := time.Minute
    59  	err := fix.Client.ClaimLease("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.Client.ClaimLease("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.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
    68  	c.Check(err, gc.Equals, lease.ErrInvalid)
    69  
    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)
    74  }
    75  
    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)
    80  
    81  	leaseDuration := time.Minute
    82  	err = fix.Client.ExtendLease("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("name", fix.Holder(), "holder")
    87  	exactExpiry := fix.Zero.Add(leaseDuration)
    88  	c.Check("name", fix.Expiry(), exactExpiry)
    89  }
    90  
    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)
    95  
    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)
   102  
   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)
   107  }
   108  
   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)
   113  
   114  	leaseDuration := time.Minute
   115  	err = fix.Client.ExtendLease("name", lease.Request{"other-holder", leaseDuration})
   116  	c.Assert(err, gc.Equals, lease.ErrInvalid)
   117  }
   118  
   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)
   124  
   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)
   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("name", fix.Holder(), "holder")
   133  	exactExpiry := fix.Zero.Add(leaseDuration)
   134  	c.Check("name", fix.Expiry(), exactExpiry)
   135  }
   136  
   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)
   142  
   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)
   147  }
   148  
   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)
   154  
   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(), "")
   160  }
   161  
   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)
   166  }