github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/lease/manager_expire_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 "github.com/juju/errors" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 corelease "github.com/juju/juju/core/lease" 15 "github.com/juju/juju/worker/lease" 16 ) 17 18 type ExpireSuite struct { 19 testing.IsolationSuite 20 } 21 22 var _ = gc.Suite(&ExpireSuite{}) 23 24 func (s *ExpireSuite) TestStartup_ExpiryInPast(c *gc.C) { 25 fix := &Fixture{ 26 leases: map[string]corelease.Info{ 27 "redis": corelease.Info{Expiry: offset(-time.Second)}, 28 }, 29 expectCalls: []call{{ 30 method: "Refresh", 31 }, { 32 method: "ExpireLease", 33 args: []interface{}{"redis"}, 34 callback: func(leases map[string]corelease.Info) { 35 delete(leases, "redis") 36 }, 37 }}, 38 } 39 fix.RunTest(c, func(_ *lease.Manager, _ *testing.Clock) {}) 40 } 41 42 func (s *ExpireSuite) TestStartup_ExpiryInFuture(c *gc.C) { 43 fix := &Fixture{ 44 leases: map[string]corelease.Info{ 45 "redis": corelease.Info{Expiry: offset(time.Second)}, 46 }, 47 } 48 fix.RunTest(c, func(_ *lease.Manager, clock *testing.Clock) { 49 clock.Advance(almostSeconds(1)) 50 }) 51 } 52 53 func (s *ExpireSuite) TestStartup_ExpiryInFuture_TimePasses(c *gc.C) { 54 fix := &Fixture{ 55 leases: map[string]corelease.Info{ 56 "redis": corelease.Info{Expiry: offset(time.Second)}, 57 }, 58 expectCalls: []call{{ 59 method: "Refresh", 60 }, { 61 method: "ExpireLease", 62 args: []interface{}{"redis"}, 63 callback: func(leases map[string]corelease.Info) { 64 delete(leases, "redis") 65 }, 66 }}, 67 } 68 fix.RunTest(c, func(_ *lease.Manager, clock *testing.Clock) { 69 clock.Advance(time.Second) 70 }) 71 } 72 73 func (s *ExpireSuite) TestStartup_NoExpiry_NotLongEnough(c *gc.C) { 74 fix := &Fixture{} 75 fix.RunTest(c, func(_ *lease.Manager, clock *testing.Clock) { 76 clock.Advance(almostSeconds(3600)) 77 }) 78 } 79 80 func (s *ExpireSuite) TestStartup_NoExpiry_LongEnough(c *gc.C) { 81 fix := &Fixture{ 82 leases: map[string]corelease.Info{ 83 "goose": corelease.Info{Expiry: offset(3 * time.Hour)}, 84 }, 85 expectCalls: []call{{ 86 method: "Refresh", 87 callback: func(leases map[string]corelease.Info) { 88 leases["redis"] = corelease.Info{ 89 Expiry: offset(time.Minute), 90 } 91 }, 92 }, { 93 method: "ExpireLease", 94 args: []interface{}{"redis"}, 95 callback: func(leases map[string]corelease.Info) { 96 delete(leases, "redis") 97 }, 98 }}, 99 } 100 fix.RunTest(c, func(_ *lease.Manager, clock *testing.Clock) { 101 clock.Advance(time.Hour) 102 }) 103 } 104 105 func (s *ExpireSuite) TestExpire_ErrInvalid_Expired(c *gc.C) { 106 fix := &Fixture{ 107 leases: map[string]corelease.Info{ 108 "redis": corelease.Info{Expiry: offset(time.Second)}, 109 }, 110 expectCalls: []call{{ 111 method: "Refresh", 112 }, { 113 method: "ExpireLease", 114 args: []interface{}{"redis"}, 115 err: corelease.ErrInvalid, 116 callback: func(leases map[string]corelease.Info) { 117 delete(leases, "redis") 118 }, 119 }}, 120 } 121 fix.RunTest(c, func(_ *lease.Manager, clock *testing.Clock) { 122 clock.Advance(time.Second) 123 }) 124 } 125 126 func (s *ExpireSuite) TestExpire_ErrInvalid_Updated(c *gc.C) { 127 fix := &Fixture{ 128 leases: map[string]corelease.Info{ 129 "redis": corelease.Info{Expiry: offset(time.Second)}, 130 }, 131 expectCalls: []call{{ 132 method: "Refresh", 133 }, { 134 method: "ExpireLease", 135 args: []interface{}{"redis"}, 136 err: corelease.ErrInvalid, 137 callback: func(leases map[string]corelease.Info) { 138 leases["redis"] = corelease.Info{Expiry: offset(time.Minute)} 139 }, 140 }}, 141 } 142 fix.RunTest(c, func(_ *lease.Manager, clock *testing.Clock) { 143 clock.Advance(time.Second) 144 }) 145 } 146 147 func (s *ExpireSuite) TestExpire_OtherError(c *gc.C) { 148 fix := &Fixture{ 149 leases: map[string]corelease.Info{ 150 "redis": corelease.Info{Expiry: offset(time.Second)}, 151 }, 152 expectCalls: []call{{ 153 method: "Refresh", 154 }, { 155 method: "ExpireLease", 156 args: []interface{}{"redis"}, 157 err: errors.New("snarfblat hobalob"), 158 }}, 159 expectDirty: true, 160 } 161 fix.RunTest(c, func(manager *lease.Manager, clock *testing.Clock) { 162 clock.Advance(time.Second) 163 err := manager.Wait() 164 c.Check(err, gc.ErrorMatches, "snarfblat hobalob") 165 }) 166 } 167 168 func (s *ExpireSuite) TestClaim_ExpiryInFuture(c *gc.C) { 169 fix := &Fixture{ 170 expectCalls: []call{{ 171 method: "ClaimLease", 172 args: []interface{}{"redis", corelease.Request{"redis/0", time.Minute}}, 173 callback: func(leases map[string]corelease.Info) { 174 leases["redis"] = corelease.Info{ 175 Holder: "redis/0", 176 Expiry: offset(63 * time.Second), 177 } 178 }, 179 }}, 180 } 181 fix.RunTest(c, func(manager *lease.Manager, clock *testing.Clock) { 182 // Ask for a minute, actually get 63s. Don't expire early. 183 err := manager.Claim("redis", "redis/0", time.Minute) 184 c.Assert(err, jc.ErrorIsNil) 185 clock.Advance(almostSeconds(63)) 186 }) 187 } 188 189 func (s *ExpireSuite) TestClaim_ExpiryInFuture_TimePasses(c *gc.C) { 190 fix := &Fixture{ 191 expectCalls: []call{{ 192 method: "ClaimLease", 193 args: []interface{}{"redis", corelease.Request{"redis/0", time.Minute}}, 194 callback: func(leases map[string]corelease.Info) { 195 leases["redis"] = corelease.Info{ 196 Holder: "redis/0", 197 Expiry: offset(63 * time.Second), 198 } 199 }, 200 }, { 201 method: "Refresh", 202 }, { 203 method: "ExpireLease", 204 args: []interface{}{"redis"}, 205 callback: func(leases map[string]corelease.Info) { 206 delete(leases, "redis") 207 }, 208 }}, 209 } 210 fix.RunTest(c, func(manager *lease.Manager, clock *testing.Clock) { 211 // Ask for a minute, actually get 63s. Expire on time. 212 err := manager.Claim("redis", "redis/0", time.Minute) 213 c.Assert(err, jc.ErrorIsNil) 214 clock.Advance(63 * time.Second) 215 }) 216 } 217 218 func (s *ExpireSuite) TestExtend_ExpiryInFuture(c *gc.C) { 219 fix := &Fixture{ 220 leases: map[string]corelease.Info{ 221 "redis": corelease.Info{ 222 Holder: "redis/0", 223 Expiry: offset(time.Second), 224 }, 225 }, 226 expectCalls: []call{{ 227 method: "ExtendLease", 228 args: []interface{}{"redis", corelease.Request{"redis/0", time.Minute}}, 229 callback: func(leases map[string]corelease.Info) { 230 leases["redis"] = corelease.Info{ 231 Holder: "redis/0", 232 Expiry: offset(63 * time.Second), 233 } 234 }, 235 }}, 236 } 237 fix.RunTest(c, func(manager *lease.Manager, clock *testing.Clock) { 238 // Ask for a minute, actually get 63s. Don't expire early. 239 err := manager.Claim("redis", "redis/0", time.Minute) 240 c.Assert(err, jc.ErrorIsNil) 241 clock.Advance(almostSeconds(63)) 242 }) 243 } 244 245 func (s *ExpireSuite) TestExtend_ExpiryInFuture_TimePasses(c *gc.C) { 246 fix := &Fixture{ 247 leases: map[string]corelease.Info{ 248 "redis": corelease.Info{ 249 Holder: "redis/0", 250 Expiry: offset(time.Second), 251 }, 252 }, 253 expectCalls: []call{{ 254 method: "ExtendLease", 255 args: []interface{}{"redis", corelease.Request{"redis/0", time.Minute}}, 256 callback: func(leases map[string]corelease.Info) { 257 leases["redis"] = corelease.Info{ 258 Holder: "redis/0", 259 Expiry: offset(63 * time.Second), 260 } 261 }, 262 }, { 263 method: "Refresh", 264 }, { 265 method: "ExpireLease", 266 args: []interface{}{"redis"}, 267 callback: func(leases map[string]corelease.Info) { 268 delete(leases, "redis") 269 }, 270 }}, 271 } 272 fix.RunTest(c, func(manager *lease.Manager, clock *testing.Clock) { 273 // Ask for a minute, actually get 63s. Expire on time. 274 err := manager.Claim("redis", "redis/0", time.Minute) 275 c.Assert(err, jc.ErrorIsNil) 276 clock.Advance(63 * time.Second) 277 }) 278 } 279 280 func (s *ExpireSuite) TestExpire_Multiple(c *gc.C) { 281 fix := &Fixture{ 282 leases: map[string]corelease.Info{ 283 "redis": corelease.Info{ 284 Holder: "redis/0", 285 Expiry: offset(time.Second), 286 }, 287 "store": corelease.Info{ 288 Holder: "store/3", 289 Expiry: offset(5 * time.Second), 290 }, 291 "tokumx": corelease.Info{ 292 Holder: "tokumx/5", 293 Expiry: offset(10 * time.Second), // will not expire. 294 }, 295 "ultron": corelease.Info{ 296 Holder: "ultron/7", 297 Expiry: offset(5 * time.Second), 298 }, 299 "vvvvvv": corelease.Info{ 300 Holder: "vvvvvv/2", 301 Expiry: offset(time.Second), // would expire, but errors first. 302 }, 303 }, 304 expectCalls: []call{{ 305 method: "Refresh", 306 }, { 307 method: "ExpireLease", 308 args: []interface{}{"redis"}, 309 callback: func(leases map[string]corelease.Info) { 310 delete(leases, "redis") 311 }, 312 }, { 313 method: "ExpireLease", 314 args: []interface{}{"store"}, 315 err: corelease.ErrInvalid, 316 callback: func(leases map[string]corelease.Info) { 317 delete(leases, "store") 318 }, 319 }, { 320 method: "ExpireLease", 321 args: []interface{}{"ultron"}, 322 err: errors.New("what is this?"), 323 }}, 324 expectDirty: true, 325 } 326 fix.RunTest(c, func(manager *lease.Manager, clock *testing.Clock) { 327 clock.Advance(5 * time.Second) 328 err := manager.Wait() 329 c.Check(err, gc.ErrorMatches, "what is this\\?") 330 }) 331 }