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  }