1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
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"
14
corelease "github.com/juju/juju/core/lease"
15
"github.com/juju/juju/state/lease"
18
// ClientPersistenceSuite checks that the operations really affect the DB in
20
type ClientPersistenceSuite struct {
24
var _ = gc.Suite(&ClientPersistenceSuite{})
26
func (s *ClientPersistenceSuite) TestNewClientInvalidClockDoc(c *gc.C) {
27
config := lease.ClientConfig{
29
Namespace: "namespace",
30
Collection: "collection",
31
Mongo: NewMongo(s.db),
32
Clock: clock.WallClock,
34
dbKey := "clock#namespace#"
35
err := s.db.C("collection").Insert(bson.M{"_id": dbKey})
36
c.Assert(err, jc.ErrorIsNil)
38
client, err := lease.NewClient(config)
39
c.Check(client, gc.IsNil)
40
c.Check(err, gc.ErrorMatches, `corrupt clock document: invalid type ""`)
43
func (s *ClientPersistenceSuite) TestNewClientInvalidLeaseDoc(c *gc.C) {
44
config := lease.ClientConfig{
46
Namespace: "namespace",
47
Collection: "collection",
48
Mongo: NewMongo(s.db),
49
Clock: clock.WallClock,
51
err := s.db.C("collection").Insert(bson.M{
54
"namespace": "namespace",
56
c.Assert(err, jc.ErrorIsNil)
58
client, err := lease.NewClient(config)
59
c.Check(client, gc.IsNil)
60
c.Check(err, gc.ErrorMatches, `corrupt lease document "snagglepuss": inconsistent _id`)
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.
69
func (s *ClientPersistenceSuite) TestNewClientExtantClockDoc(c *gc.C) {
70
// Empty database: new Client creates clock doc.
73
// Clock doc exists; new Client created successfully.
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)
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)
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)
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)
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)
114
// Same client id, same clock, new instance: sees no lease.
115
fix2 := s.EasyFixture(c)
116
c.Check("name", fix2.Holder(), "")
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)
125
// Same client id, same clock, different namespace: sees no lease.
126
fix2 := s.NewFixture(c, FixtureParams{
127
Namespace: "different-namespace",
129
c.Check("name", fix2.Holder(), "")
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)
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)),
142
c.Check("name", fix2.Holder(), "holder")
143
exactExpiry := fix2.Zero.Add(leaseDuration)
144
c.Check("name", fix2.Expiry(), exactExpiry)
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)
153
// Different client *and* different timezone; but clock agrees perfectly,
154
// so we still see no skew.
155
fix2 := s.NewFixture(c, FixtureParams{
157
ClockStart: fix1.Zero.UTC(),
159
c.Check("name", fix2.Holder(), "holder")
160
exactExpiry := fix1.Zero.Add(leaseDuration).UTC()
161
c.Check("name", fix2.Expiry(), exactExpiry)