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