github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/state/lease/client_persistence_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  	"github.com/juju/utils/clock"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/mgo.v2/bson"
    13  
    14  	"github.com/juju/juju/state/lease"
    15  )
    16  
    17  // ClientPersistenceSuite checks that the operations really affect the DB in
    18  // the expected way.
    19  type ClientPersistenceSuite struct {
    20  	FixtureSuite
    21  }
    22  
    23  var _ = gc.Suite(&ClientPersistenceSuite{})
    24  
    25  func (s *ClientPersistenceSuite) TestNewClientInvalidClockDoc(c *gc.C) {
    26  	config := lease.ClientConfig{
    27  		Id:         "client",
    28  		Namespace:  "namespace",
    29  		Collection: "collection",
    30  		Mongo:      NewMongo(s.db),
    31  		Clock:      clock.WallClock,
    32  	}
    33  	dbKey := "clock#namespace#"
    34  	err := s.db.C("collection").Insert(bson.M{"_id": dbKey})
    35  	c.Assert(err, jc.ErrorIsNil)
    36  
    37  	client, err := lease.NewClient(config)
    38  	c.Check(client, gc.IsNil)
    39  	c.Check(err, gc.ErrorMatches, `corrupt clock document: invalid type ""`)
    40  }
    41  
    42  func (s *ClientPersistenceSuite) TestNewClientInvalidLeaseDoc(c *gc.C) {
    43  	config := lease.ClientConfig{
    44  		Id:         "client",
    45  		Namespace:  "namespace",
    46  		Collection: "collection",
    47  		Mongo:      NewMongo(s.db),
    48  		Clock:      clock.WallClock,
    49  	}
    50  	err := s.db.C("collection").Insert(bson.M{
    51  		"_id":       "snagglepuss",
    52  		"type":      "lease",
    53  		"namespace": "namespace",
    54  	})
    55  	c.Assert(err, jc.ErrorIsNil)
    56  
    57  	client, err := lease.NewClient(config)
    58  	c.Check(client, gc.IsNil)
    59  	c.Check(err, gc.ErrorMatches, `corrupt lease document "snagglepuss": inconsistent _id`)
    60  }
    61  
    62  func (s *ClientPersistenceSuite) TestNewClientMissingClockDoc(c *gc.C) {
    63  	// The database starts out empty, so just creating the fixture is enough
    64  	// to test this code path.
    65  	s.EasyFixture(c)
    66  }
    67  
    68  func (s *ClientPersistenceSuite) TestNewClientExtantClockDoc(c *gc.C) {
    69  	// Empty database: new Client creates clock doc.
    70  	s.EasyFixture(c)
    71  
    72  	// Clock doc exists; new Client created successfully.
    73  	s.EasyFixture(c)
    74  }
    75  
    76  func (s *ClientPersistenceSuite) TestClaimLease(c *gc.C) {
    77  	fix1 := s.EasyFixture(c)
    78  	leaseDuration := time.Minute
    79  	err := fix1.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
    80  	c.Assert(err, jc.ErrorIsNil)
    81  
    82  	// Same client id, same clock, new instance: sees exact same lease.
    83  	fix2 := s.EasyFixture(c)
    84  	c.Check("name", fix2.Holder(), "holder")
    85  	exactExpiry := fix1.Zero.Add(leaseDuration)
    86  	c.Check("name", fix2.Expiry(), exactExpiry)
    87  }
    88  
    89  func (s *ClientPersistenceSuite) TestExtendLease(c *gc.C) {
    90  	fix1 := s.EasyFixture(c)
    91  	err := fix1.Client.ClaimLease("name", lease.Request{"holder", time.Second})
    92  	c.Assert(err, jc.ErrorIsNil)
    93  	leaseDuration := time.Minute
    94  	err = fix1.Client.ExtendLease("name", lease.Request{"holder", leaseDuration})
    95  	c.Assert(err, jc.ErrorIsNil)
    96  
    97  	// Same client id, same clock, new instance: sees exact same lease.
    98  	fix2 := s.EasyFixture(c)
    99  	c.Check("name", fix2.Holder(), "holder")
   100  	exactExpiry := fix1.Zero.Add(leaseDuration)
   101  	c.Check("name", fix2.Expiry(), exactExpiry)
   102  }
   103  
   104  func (s *ClientPersistenceSuite) TestExpireLease(c *gc.C) {
   105  	fix1 := s.EasyFixture(c)
   106  	leaseDuration := time.Minute
   107  	err := fix1.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
   108  	c.Assert(err, jc.ErrorIsNil)
   109  	fix1.Clock.Advance(leaseDuration + time.Nanosecond)
   110  	err = fix1.Client.ExpireLease("name")
   111  	c.Assert(err, jc.ErrorIsNil)
   112  
   113  	// Same client id, same clock, new instance: sees no lease.
   114  	fix2 := s.EasyFixture(c)
   115  	c.Check("name", fix2.Holder(), "")
   116  }
   117  
   118  func (s *ClientPersistenceSuite) TestNamespaceIsolation(c *gc.C) {
   119  	fix1 := s.EasyFixture(c)
   120  	leaseDuration := time.Minute
   121  	err := fix1.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
   122  	c.Assert(err, jc.ErrorIsNil)
   123  
   124  	// Same client id, same clock, different namespace: sees no lease.
   125  	fix2 := s.NewFixture(c, FixtureParams{
   126  		Namespace: "different-namespace",
   127  	})
   128  	c.Check("name", fix2.Holder(), "")
   129  }
   130  
   131  func (s *ClientPersistenceSuite) TestTimezoneChanges(c *gc.C) {
   132  	fix1 := s.EasyFixture(c)
   133  	leaseDuration := time.Minute
   134  	err := fix1.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
   135  	c.Assert(err, jc.ErrorIsNil)
   136  
   137  	// Same client can come up in a different timezone and still work correctly.
   138  	fix2 := s.NewFixture(c, FixtureParams{
   139  		ClockStart: fix1.Zero.In(time.FixedZone("somewhere", -1234)),
   140  	})
   141  	c.Check("name", fix2.Holder(), "holder")
   142  	exactExpiry := fix2.Zero.Add(leaseDuration)
   143  	c.Check("name", fix2.Expiry(), exactExpiry)
   144  }
   145  
   146  func (s *ClientPersistenceSuite) TestTimezoneIsolation(c *gc.C) {
   147  	fix1 := s.EasyFixture(c)
   148  	leaseDuration := time.Minute
   149  	err := fix1.Client.ClaimLease("name", lease.Request{"holder", leaseDuration})
   150  	c.Assert(err, jc.ErrorIsNil)
   151  
   152  	// Different client *and* different timezone; but clock agrees perfectly,
   153  	// so we still see no skew.
   154  	fix2 := s.NewFixture(c, FixtureParams{
   155  		Id:         "remote-client",
   156  		ClockStart: fix1.Zero.UTC(),
   157  	})
   158  	c.Check("name", fix2.Holder(), "holder")
   159  	exactExpiry := fix1.Zero.Add(leaseDuration).UTC()
   160  	c.Check("name", fix2.Expiry(), exactExpiry)
   161  }