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 }