github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/workers/restart_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package workers_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils/clock" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/state/workers" 17 "github.com/juju/juju/worker" 18 "github.com/juju/juju/worker/workertest" 19 ) 20 21 type RestartWorkersSuite struct { 22 testing.IsolationSuite 23 } 24 25 var _ = gc.Suite(&RestartWorkersSuite{}) 26 27 func (*RestartWorkersSuite) TestValidateSuccess(c *gc.C) { 28 config := workers.RestartConfig{ 29 Factory: struct{ workers.Factory }{}, 30 Logger: loggo.GetLogger("test"), 31 Clock: struct{ clock.Clock }{}, 32 Delay: time.Nanosecond, 33 } 34 err := config.Validate() 35 c.Check(err, jc.ErrorIsNil) 36 } 37 38 func (*RestartWorkersSuite) TestValidateMissingFactory(c *gc.C) { 39 config := validRestartConfig() 40 config.Factory = nil 41 checkInvalidRestartConfig(c, config, "nil Factory not valid") 42 } 43 44 func (*RestartWorkersSuite) TestValidateUninitializedLogger(c *gc.C) { 45 config := validRestartConfig() 46 config.Logger = loggo.Logger{} 47 checkInvalidRestartConfig(c, config, "uninitialized Logger not valid") 48 } 49 50 func (*RestartWorkersSuite) TestValidateMissingClock(c *gc.C) { 51 config := validRestartConfig() 52 config.Clock = nil 53 checkInvalidRestartConfig(c, config, "nil Clock not valid") 54 } 55 56 func (*RestartWorkersSuite) TestValidateMissingDelay(c *gc.C) { 57 config := validRestartConfig() 58 config.Delay = 0 59 checkInvalidRestartConfig(c, config, "non-positive Delay not valid") 60 } 61 62 func (*RestartWorkersSuite) TestValidateNegativeDelay(c *gc.C) { 63 config := validRestartConfig() 64 config.Delay = -time.Second 65 checkInvalidRestartConfig(c, config, "non-positive Delay not valid") 66 } 67 68 func (*RestartWorkersSuite) TestNewLeadershipManagerError(c *gc.C) { 69 fix := Fixture{ 70 LW_errors: []error{ErrFailStart}, 71 } 72 fix.FailRestart(c, "cannot create leadership lease manager: bad start") 73 } 74 75 func (*RestartWorkersSuite) TestNewSingularManagerError(c *gc.C) { 76 fix := Fixture{ 77 LW_errors: []error{nil}, 78 SW_errors: []error{ErrFailStart}, 79 } 80 fix.FailRestart(c, "cannot create singular lease manager: bad start") 81 } 82 83 func (*RestartWorkersSuite) TestNewTxnLogWatcherError(c *gc.C) { 84 fix := Fixture{ 85 LW_errors: []error{nil}, 86 SW_errors: []error{nil}, 87 TLW_errors: []error{ErrFailStart}, 88 } 89 fix.FailRestart(c, "cannot create transaction log watcher: bad start") 90 } 91 92 func (*RestartWorkersSuite) TestNewPresenceWatcherError(c *gc.C) { 93 fix := BasicFixture() 94 fix.PW_errors = []error{ErrFailStart} 95 fix.FailRestart(c, "cannot create presence watcher: bad start") 96 } 97 98 func (*RestartWorkersSuite) TestLeadershipManagerDelay(c *gc.C) { 99 fix := BasicFixture() 100 fix.LW_errors = []error{errors.New("oof")} 101 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 102 w := NextWorker(c, ctx.LWs()) 103 c.Assert(w, gc.NotNil) 104 AssertWorker(c, rw.LeadershipManager(), w) 105 w.Kill() 106 107 clock := ctx.Clock() 108 WaitAlarms(c, clock, 1) 109 clock.Advance(almostFiveSeconds) 110 AssertWorker(c, rw.LeadershipManager(), w) 111 112 err := workertest.CheckKill(c, rw) 113 c.Check(err, gc.ErrorMatches, "error stopping leadership lease manager: oof") 114 }) 115 } 116 117 func (*RestartWorkersSuite) TestSingularManagerDelay(c *gc.C) { 118 fix := BasicFixture() 119 fix.SW_errors = []error{errors.New("oof")} 120 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 121 w := NextWorker(c, ctx.SWs()) 122 c.Assert(w, gc.NotNil) 123 AssertWorker(c, rw.SingularManager(), w) 124 w.Kill() 125 126 clock := ctx.Clock() 127 WaitAlarms(c, clock, 1) 128 clock.Advance(almostFiveSeconds) 129 AssertWorker(c, rw.SingularManager(), w) 130 131 err := workertest.CheckKill(c, rw) 132 c.Check(err, gc.ErrorMatches, "error stopping singular lease manager: oof") 133 }) 134 } 135 136 func (*RestartWorkersSuite) TestTxnLogWatcherDelay(c *gc.C) { 137 fix := BasicFixture() 138 fix.TLW_errors = []error{errors.New("oof")} 139 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 140 w := NextWorker(c, ctx.TLWs()) 141 c.Assert(w, gc.NotNil) 142 AssertWorker(c, rw.TxnLogWatcher(), w) 143 w.Kill() 144 145 clock := ctx.Clock() 146 WaitAlarms(c, clock, 1) 147 clock.Advance(almostFiveSeconds) 148 AssertWorker(c, rw.TxnLogWatcher(), w) 149 150 err := workertest.CheckKill(c, rw) 151 c.Check(err, gc.ErrorMatches, "error stopping transaction log watcher: oof") 152 }) 153 } 154 155 func (*RestartWorkersSuite) TestPresenceWatcherDelay(c *gc.C) { 156 fix := BasicFixture() 157 fix.PW_errors = []error{errors.New("oof")} 158 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 159 w := NextWorker(c, ctx.PWs()) 160 c.Assert(w, gc.NotNil) 161 AssertWorker(c, rw.PresenceWatcher(), w) 162 w.Kill() 163 164 clock := ctx.Clock() 165 WaitAlarms(c, clock, 1) 166 clock.Advance(almostFiveSeconds) 167 AssertWorker(c, rw.PresenceWatcher(), w) 168 169 err := workertest.CheckKill(c, rw) 170 c.Check(err, gc.ErrorMatches, "error stopping presence watcher: oof") 171 }) 172 } 173 174 func (*RestartWorkersSuite) TestLeadershipManagerRestart(c *gc.C) { 175 fix := BasicFixture() 176 fix.LW_errors = []error{errors.New("oof"), nil} 177 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 178 origw := rw.LeadershipManager() 179 w := NextWorker(c, ctx.LWs()) 180 c.Assert(w, gc.NotNil) 181 AssertWorker(c, rw.LeadershipManager(), w) 182 w.Kill() 183 184 clock := ctx.Clock() 185 WaitAlarms(c, clock, 1) 186 clock.Advance(fiveSeconds) 187 w2 := NextWorker(c, ctx.LWs()) 188 c.Assert(w, gc.NotNil) 189 WaitWorker(c, LM_getter(rw), w2) 190 191 // The new worker should underlie the originally 192 // acquired leadership manager, so that restarts 193 // do not require callers to acquire a new manager 194 AssertWorker(c, origw, w2) 195 196 workertest.CleanKill(c, rw) 197 }) 198 } 199 200 func (*RestartWorkersSuite) TestSingularManagerRestart(c *gc.C) { 201 fix := BasicFixture() 202 fix.SW_errors = []error{errors.New("oof"), nil} 203 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 204 origw := rw.SingularManager() 205 w := NextWorker(c, ctx.SWs()) 206 c.Assert(w, gc.NotNil) 207 AssertWorker(c, rw.SingularManager(), w) 208 w.Kill() 209 210 clock := ctx.Clock() 211 WaitAlarms(c, clock, 1) 212 clock.Advance(fiveSeconds) 213 w2 := NextWorker(c, ctx.SWs()) 214 c.Assert(w, gc.NotNil) 215 WaitWorker(c, SM_getter(rw), w2) 216 217 // The new worker should underlie the originally 218 // acquired singular manager, so that restarts 219 // do not require callers to acquire a new manager 220 AssertWorker(c, origw, w2) 221 222 workertest.CleanKill(c, rw) 223 }) 224 } 225 226 func (*RestartWorkersSuite) TestTxnLogWatcherRestart(c *gc.C) { 227 fix := BasicFixture() 228 fix.TLW_errors = []error{errors.New("oof"), nil} 229 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 230 w := NextWorker(c, ctx.TLWs()) 231 c.Assert(w, gc.NotNil) 232 AssertWorker(c, rw.TxnLogWatcher(), w) 233 w.Kill() 234 235 clock := ctx.Clock() 236 WaitAlarms(c, clock, 1) 237 clock.Advance(fiveSeconds) 238 w2 := NextWorker(c, ctx.TLWs()) 239 c.Assert(w, gc.NotNil) 240 WaitWorker(c, TLW_getter(rw), w2) 241 242 workertest.CleanKill(c, rw) 243 }) 244 } 245 246 func (*RestartWorkersSuite) TestPresenceWatcherRestart(c *gc.C) { 247 fix := BasicFixture() 248 fix.PW_errors = []error{errors.New("oof"), nil} 249 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 250 w := NextWorker(c, ctx.PWs()) 251 c.Assert(w, gc.NotNil) 252 AssertWorker(c, rw.PresenceWatcher(), w) 253 w.Kill() 254 255 clock := ctx.Clock() 256 WaitAlarms(c, clock, 1) 257 clock.Advance(fiveSeconds) 258 w2 := NextWorker(c, ctx.PWs()) 259 c.Assert(w, gc.NotNil) 260 WaitWorker(c, PW_getter(rw), w2) 261 262 workertest.CleanKill(c, rw) 263 }) 264 } 265 266 func (*RestartWorkersSuite) TestStopsAllWorkers(c *gc.C) { 267 fix := BasicFixture() 268 fix.RunRestart(c, func(ctx Context, rw *workers.RestartWorkers) { 269 workertest.CleanKill(c, rw) 270 for _, ch := range []<-chan worker.Worker{ 271 ctx.LWs(), ctx.SWs(), ctx.TLWs(), ctx.PWs(), 272 } { 273 w := NextWorker(c, ch) 274 workertest.CheckKilled(c, w) 275 } 276 }) 277 } 278 279 func validRestartConfig() workers.RestartConfig { 280 return workers.RestartConfig{ 281 Factory: struct{ workers.Factory }{}, 282 Logger: loggo.GetLogger("test"), 283 Clock: struct{ clock.Clock }{}, 284 Delay: time.Nanosecond, 285 } 286 } 287 288 func checkInvalidRestartConfig(c *gc.C, config workers.RestartConfig, match string) { 289 check := func(err error) { 290 c.Check(err, jc.Satisfies, errors.IsNotValid) 291 c.Check(err, gc.ErrorMatches, match) 292 } 293 294 err := config.Validate() 295 check(err) 296 297 rw, err := workers.NewRestartWorkers(config) 298 if !c.Check(rw, gc.IsNil) { 299 workertest.DirtyKill(c, rw) 300 } 301 check(err) 302 }