github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/uniter/operation/runhook_test.go (about) 1 // Copyright 2014-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package operation_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 "gopkg.in/juju/charm.v4/hooks" 14 15 "github.com/juju/juju/worker/uniter/hook" 16 "github.com/juju/juju/worker/uniter/operation" 17 "github.com/juju/juju/worker/uniter/runner" 18 ) 19 20 type RunHookSuite struct { 21 testing.IsolationSuite 22 } 23 24 var _ = gc.Suite(&RunHookSuite{}) 25 26 type newHook func(operation.Factory, hook.Info) (operation.Operation, error) 27 28 func (s *RunHookSuite) testClearResolvedFlagError(c *gc.C, newHook newHook) { 29 callbacks := &PrepareHookCallbacks{ 30 MockClearResolvedFlag: &MockNoArgs{err: errors.New("biff")}, 31 } 32 factory := operation.NewFactory(nil, nil, callbacks, nil) 33 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 34 c.Assert(err, jc.ErrorIsNil) 35 36 newState, err := op.Prepare(operation.State{}) 37 c.Check(newState, gc.IsNil) 38 c.Check(callbacks.MockClearResolvedFlag.called, jc.IsTrue) 39 c.Check(err, gc.ErrorMatches, "biff") 40 } 41 42 func (s *RunHookSuite) TestClearResolvedFlagError_Retry(c *gc.C) { 43 s.testClearResolvedFlagError(c, (operation.Factory).NewRetryHook) 44 } 45 46 func (s *RunHookSuite) TestClearResolvedFlagError_Skip(c *gc.C) { 47 s.testClearResolvedFlagError(c, (operation.Factory).NewSkipHook) 48 } 49 50 func (s *RunHookSuite) testPrepareHookError( 51 c *gc.C, newHook newHook, expectClearResolvedFlag, expectSkip bool, 52 ) { 53 callbacks := &PrepareHookCallbacks{ 54 MockPrepareHook: &MockPrepareHook{err: errors.New("pow")}, 55 MockClearResolvedFlag: &MockNoArgs{}, 56 } 57 factory := operation.NewFactory(nil, nil, callbacks, nil) 58 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 59 c.Assert(err, jc.ErrorIsNil) 60 61 newState, err := op.Prepare(operation.State{}) 62 c.Check(newState, gc.IsNil) 63 c.Check(callbacks.MockClearResolvedFlag.called, gc.Equals, expectClearResolvedFlag) 64 if expectSkip { 65 c.Check(err, gc.Equals, operation.ErrSkipExecute) 66 c.Check(callbacks.MockPrepareHook.gotHook, gc.IsNil) 67 return 68 } 69 c.Check(err, gc.ErrorMatches, "pow") 70 c.Check(callbacks.MockPrepareHook.gotHook, gc.DeepEquals, &hook.Info{ 71 Kind: hooks.ConfigChanged, 72 }) 73 } 74 75 func (s *RunHookSuite) TestPrepareHookError_Run(c *gc.C) { 76 s.testPrepareHookError(c, (operation.Factory).NewRunHook, false, false) 77 } 78 79 func (s *RunHookSuite) TestPrepareHookError_Retry(c *gc.C) { 80 s.testPrepareHookError(c, (operation.Factory).NewRetryHook, true, false) 81 } 82 83 func (s *RunHookSuite) TestPrepareHookError_Skip(c *gc.C) { 84 s.testPrepareHookError(c, (operation.Factory).NewSkipHook, true, true) 85 } 86 87 func (s *RunHookSuite) testPrepareRunnerError(c *gc.C, newHook newHook) { 88 callbacks := NewPrepareHookCallbacks() 89 runnerFactory := &MockRunnerFactory{ 90 MockNewHookRunner: &MockNewHookRunner{err: errors.New("splat")}, 91 } 92 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 93 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 94 c.Assert(err, jc.ErrorIsNil) 95 96 newState, err := op.Prepare(operation.State{}) 97 c.Check(newState, gc.IsNil) 98 c.Check(err, gc.ErrorMatches, "splat") 99 c.Check(runnerFactory.MockNewHookRunner.gotHook, gc.DeepEquals, &hook.Info{ 100 Kind: hooks.ConfigChanged, 101 }) 102 } 103 104 func (s *RunHookSuite) TestPrepareRunnerError_Run(c *gc.C) { 105 s.testPrepareRunnerError(c, (operation.Factory).NewRunHook) 106 } 107 108 func (s *RunHookSuite) TestPrepareRunnerError_Retry(c *gc.C) { 109 s.testPrepareRunnerError(c, (operation.Factory).NewRetryHook) 110 } 111 112 func (s *RunHookSuite) testPrepareSuccess( 113 c *gc.C, newHook newHook, before, after operation.State, 114 ) { 115 runnerFactory := NewRunHookRunnerFactory(errors.New("should not call")) 116 callbacks := NewPrepareHookCallbacks() 117 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 118 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 119 c.Assert(err, jc.ErrorIsNil) 120 121 newState, err := op.Prepare(before) 122 c.Check(err, jc.ErrorIsNil) 123 c.Check(newState, gc.DeepEquals, &after) 124 } 125 126 func (s *RunHookSuite) TestPrepareSuccess_BlankSlate(c *gc.C) { 127 for i, newHook := range []newHook{ 128 (operation.Factory).NewRunHook, 129 (operation.Factory).NewRetryHook, 130 } { 131 c.Logf("variant %d", i) 132 s.testPrepareSuccess(c, 133 newHook, 134 operation.State{}, 135 operation.State{ 136 Kind: operation.RunHook, 137 Step: operation.Pending, 138 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 139 }, 140 ) 141 } 142 } 143 144 func (s *RunHookSuite) TestPrepareSuccess_Preserve(c *gc.C) { 145 for i, newHook := range []newHook{ 146 (operation.Factory).NewRunHook, 147 (operation.Factory).NewRetryHook, 148 } { 149 c.Logf("variant %d", i) 150 s.testPrepareSuccess(c, 151 newHook, 152 overwriteState, 153 operation.State{ 154 Started: true, 155 CollectMetricsTime: 1234567, 156 Kind: operation.RunHook, 157 Step: operation.Pending, 158 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 159 }, 160 ) 161 } 162 } 163 164 func (s *RunHookSuite) testExecuteLockError(c *gc.C, newHook newHook) { 165 runnerFactory := NewRunHookRunnerFactory(errors.New("should not call")) 166 callbacks := &ExecuteHookCallbacks{ 167 PrepareHookCallbacks: NewPrepareHookCallbacks(), 168 MockAcquireExecutionLock: &MockAcquireExecutionLock{err: errors.New("blart")}, 169 } 170 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 171 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 172 c.Assert(err, jc.ErrorIsNil) 173 _, err = op.Prepare(operation.State{}) 174 c.Assert(err, jc.ErrorIsNil) 175 176 newState, err := op.Execute(operation.State{}) 177 c.Assert(newState, gc.IsNil) 178 c.Assert(err, gc.ErrorMatches, "blart") 179 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running hook some-hook-name") 180 } 181 182 func (s *RunHookSuite) TestExecuteLockError_Run(c *gc.C) { 183 s.testExecuteLockError(c, (operation.Factory).NewRunHook) 184 } 185 186 func (s *RunHookSuite) TestExecuteLockError_Retry(c *gc.C) { 187 s.testExecuteLockError(c, (operation.Factory).NewRetryHook) 188 } 189 190 func (s *RunHookSuite) getExecuteRunnerTest(c *gc.C, newHook newHook, runErr error) (operation.Operation, *ExecuteHookCallbacks, *MockRunnerFactory) { 191 runnerFactory := NewRunHookRunnerFactory(runErr) 192 callbacks := &ExecuteHookCallbacks{ 193 PrepareHookCallbacks: NewPrepareHookCallbacks(), 194 MockAcquireExecutionLock: &MockAcquireExecutionLock{}, 195 MockNotifyHookCompleted: &MockNotify{}, 196 MockNotifyHookFailed: &MockNotify{}, 197 } 198 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 199 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 200 c.Assert(err, jc.ErrorIsNil) 201 return op, callbacks, runnerFactory 202 } 203 204 func (s *RunHookSuite) testExecuteMissingHookError(c *gc.C, newHook newHook) { 205 runErr := runner.NewMissingHookError("blah-blah") 206 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, newHook, runErr) 207 _, err := op.Prepare(operation.State{}) 208 c.Assert(err, jc.ErrorIsNil) 209 210 newState, err := op.Execute(operation.State{}) 211 c.Assert(err, jc.ErrorIsNil) 212 c.Assert(newState, gc.DeepEquals, &operation.State{ 213 Kind: operation.RunHook, 214 Step: operation.Done, 215 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 216 }) 217 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running hook some-hook-name") 218 c.Assert(callbacks.MockAcquireExecutionLock.didUnlock, jc.IsTrue) 219 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 220 c.Assert(callbacks.MockNotifyHookCompleted.gotName, gc.IsNil) 221 c.Assert(callbacks.MockNotifyHookFailed.gotName, gc.IsNil) 222 } 223 224 func (s *RunHookSuite) TestExecuteMissingHookError_Run(c *gc.C) { 225 s.testExecuteMissingHookError(c, (operation.Factory).NewRunHook) 226 } 227 228 func (s *RunHookSuite) TestExecuteMissingHookError_Retry(c *gc.C) { 229 s.testExecuteMissingHookError(c, (operation.Factory).NewRetryHook) 230 } 231 232 func (s *RunHookSuite) testExecuteRequeueRebootError(c *gc.C, newHook newHook) { 233 runErr := runner.ErrRequeueAndReboot 234 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, newHook, runErr) 235 _, err := op.Prepare(operation.State{}) 236 c.Assert(err, jc.ErrorIsNil) 237 238 newState, err := op.Execute(operation.State{}) 239 c.Assert(err, gc.Equals, operation.ErrNeedsReboot) 240 c.Assert(newState, gc.DeepEquals, &operation.State{ 241 Kind: operation.RunHook, 242 Step: operation.Queued, 243 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 244 }) 245 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running hook some-hook-name") 246 c.Assert(callbacks.MockAcquireExecutionLock.didUnlock, jc.IsTrue) 247 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 248 c.Assert(*callbacks.MockNotifyHookCompleted.gotName, gc.Equals, "some-hook-name") 249 c.Assert(*callbacks.MockNotifyHookCompleted.gotContext, gc.Equals, runnerFactory.MockNewHookRunner.runner.context) 250 c.Assert(callbacks.MockNotifyHookFailed.gotName, gc.IsNil) 251 } 252 253 func (s *RunHookSuite) TestExecuteRequeueRebootError_Run(c *gc.C) { 254 s.testExecuteRequeueRebootError(c, (operation.Factory).NewRunHook) 255 } 256 257 func (s *RunHookSuite) TestExecuteRequeueRebootError_Retry(c *gc.C) { 258 s.testExecuteRequeueRebootError(c, (operation.Factory).NewRetryHook) 259 } 260 261 func (s *RunHookSuite) testExecuteRebootError(c *gc.C, newHook newHook) { 262 runErr := runner.ErrReboot 263 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, newHook, runErr) 264 _, err := op.Prepare(operation.State{}) 265 c.Assert(err, jc.ErrorIsNil) 266 267 newState, err := op.Execute(operation.State{}) 268 c.Assert(err, gc.Equals, operation.ErrNeedsReboot) 269 c.Assert(newState, gc.DeepEquals, &operation.State{ 270 Kind: operation.RunHook, 271 Step: operation.Done, 272 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 273 }) 274 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running hook some-hook-name") 275 c.Assert(callbacks.MockAcquireExecutionLock.didUnlock, jc.IsTrue) 276 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 277 c.Assert(*callbacks.MockNotifyHookCompleted.gotName, gc.Equals, "some-hook-name") 278 c.Assert(*callbacks.MockNotifyHookCompleted.gotContext, gc.Equals, runnerFactory.MockNewHookRunner.runner.context) 279 c.Assert(callbacks.MockNotifyHookFailed.gotName, gc.IsNil) 280 } 281 282 func (s *RunHookSuite) TestExecuteRebootError_Run(c *gc.C) { 283 s.testExecuteRebootError(c, (operation.Factory).NewRunHook) 284 } 285 286 func (s *RunHookSuite) TestExecuteRebootError_Retry(c *gc.C) { 287 s.testExecuteRebootError(c, (operation.Factory).NewRetryHook) 288 } 289 290 func (s *RunHookSuite) testExecuteOtherError(c *gc.C, newHook newHook) { 291 runErr := errors.New("graaargh") 292 op, callbacks, runnerFactory := s.getExecuteRunnerTest(c, newHook, runErr) 293 _, err := op.Prepare(operation.State{}) 294 c.Assert(err, jc.ErrorIsNil) 295 296 newState, err := op.Execute(operation.State{}) 297 c.Assert(err, gc.Equals, operation.ErrHookFailed) 298 c.Assert(newState, gc.IsNil) 299 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running hook some-hook-name") 300 c.Assert(callbacks.MockAcquireExecutionLock.didUnlock, jc.IsTrue) 301 c.Assert(*runnerFactory.MockNewHookRunner.runner.MockRunHook.gotName, gc.Equals, "some-hook-name") 302 c.Assert(*callbacks.MockNotifyHookFailed.gotName, gc.Equals, "some-hook-name") 303 c.Assert(*callbacks.MockNotifyHookFailed.gotContext, gc.Equals, runnerFactory.MockNewHookRunner.runner.context) 304 c.Assert(callbacks.MockNotifyHookCompleted.gotName, gc.IsNil) 305 } 306 307 func (s *RunHookSuite) TestExecuteOtherError_Run(c *gc.C) { 308 s.testExecuteOtherError(c, (operation.Factory).NewRunHook) 309 } 310 311 func (s *RunHookSuite) TestExecuteOtherError_Retry(c *gc.C) { 312 s.testExecuteOtherError(c, (operation.Factory).NewRetryHook) 313 } 314 315 func (s *RunHookSuite) testExecuteSuccess( 316 c *gc.C, newHook newHook, before, after operation.State, 317 ) { 318 op, _, _ := s.getExecuteRunnerTest(c, newHook, nil) 319 midState, err := op.Prepare(before) 320 c.Assert(err, jc.ErrorIsNil) 321 c.Assert(midState, gc.NotNil) 322 323 newState, err := op.Execute(*midState) 324 c.Assert(err, jc.ErrorIsNil) 325 c.Assert(newState, gc.DeepEquals, &after) 326 } 327 328 func (s *RunHookSuite) TestExecuteSuccess_BlankSlate(c *gc.C) { 329 for i, newHook := range []newHook{ 330 (operation.Factory).NewRunHook, 331 (operation.Factory).NewRetryHook, 332 } { 333 c.Logf("variant %d", i) 334 s.testExecuteSuccess(c, 335 newHook, 336 operation.State{}, 337 operation.State{ 338 Kind: operation.RunHook, 339 Step: operation.Done, 340 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 341 }, 342 ) 343 } 344 } 345 346 func (s *RunHookSuite) TestExecuteSuccess_Preserve(c *gc.C) { 347 for i, newHook := range []newHook{ 348 (operation.Factory).NewRunHook, 349 (operation.Factory).NewRetryHook, 350 } { 351 c.Logf("variant %d", i) 352 s.testExecuteSuccess(c, 353 newHook, 354 overwriteState, 355 operation.State{ 356 Started: true, 357 CollectMetricsTime: 1234567, 358 Kind: operation.RunHook, 359 Step: operation.Done, 360 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 361 }, 362 ) 363 } 364 } 365 366 func (s *RunHookSuite) testCommitError(c *gc.C, newHook newHook) { 367 callbacks := &CommitHookCallbacks{ 368 MockCommitHook: &MockCommitHook{nil, errors.New("pow")}, 369 } 370 factory := operation.NewFactory(nil, nil, callbacks, nil) 371 op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) 372 c.Assert(err, jc.ErrorIsNil) 373 374 newState, err := op.Commit(operation.State{}) 375 c.Assert(newState, gc.IsNil) 376 c.Assert(err, gc.ErrorMatches, "pow") 377 } 378 379 func (s *RunHookSuite) TestCommitError_Run(c *gc.C) { 380 s.testCommitError(c, (operation.Factory).NewRunHook) 381 } 382 383 func (s *RunHookSuite) TestCommitError_Retry(c *gc.C) { 384 s.testCommitError(c, (operation.Factory).NewRetryHook) 385 } 386 387 func (s *RunHookSuite) TestCommitError_Skip(c *gc.C) { 388 s.testCommitError(c, (operation.Factory).NewSkipHook) 389 } 390 391 func (s *RunHookSuite) testCommitSuccess(c *gc.C, newHook newHook, hookInfo hook.Info, before, after operation.State) { 392 callbacks := &CommitHookCallbacks{ 393 MockCommitHook: &MockCommitHook{}, 394 } 395 factory := operation.NewFactory(nil, nil, callbacks, nil) 396 op, err := newHook(factory, hookInfo) 397 c.Assert(err, jc.ErrorIsNil) 398 399 newState, err := op.Commit(before) 400 c.Assert(err, jc.ErrorIsNil) 401 c.Assert(newState, gc.DeepEquals, &after) 402 } 403 404 func (s *RunHookSuite) TestCommitSuccess_ConfigChanged_QueueStartHook(c *gc.C) { 405 for i, newHook := range []newHook{ 406 (operation.Factory).NewRunHook, 407 (operation.Factory).NewRetryHook, 408 (operation.Factory).NewSkipHook, 409 } { 410 c.Logf("variant %d", i) 411 s.testCommitSuccess(c, 412 newHook, 413 hook.Info{Kind: hooks.ConfigChanged}, 414 operation.State{}, 415 operation.State{ 416 Kind: operation.RunHook, 417 Step: operation.Queued, 418 Hook: &hook.Info{Kind: hooks.Start}, 419 }, 420 ) 421 } 422 } 423 424 func (s *RunHookSuite) TestCommitSuccess_ConfigChanged_Preserve(c *gc.C) { 425 for i, newHook := range []newHook{ 426 (operation.Factory).NewRunHook, 427 (operation.Factory).NewRetryHook, 428 (operation.Factory).NewSkipHook, 429 } { 430 c.Logf("variant %d", i) 431 s.testCommitSuccess(c, 432 newHook, 433 hook.Info{Kind: hooks.ConfigChanged}, 434 overwriteState, 435 operation.State{ 436 Started: true, 437 CollectMetricsTime: 1234567, 438 Kind: operation.Continue, 439 Step: operation.Pending, 440 Hook: &hook.Info{Kind: hooks.ConfigChanged}, 441 }, 442 ) 443 } 444 } 445 446 func (s *RunHookSuite) TestCommitSuccess_Start_SetStarted(c *gc.C) { 447 for i, newHook := range []newHook{ 448 (operation.Factory).NewRunHook, 449 (operation.Factory).NewRetryHook, 450 (operation.Factory).NewSkipHook, 451 } { 452 c.Logf("variant %d", i) 453 s.testCommitSuccess(c, 454 newHook, 455 hook.Info{Kind: hooks.Start}, 456 operation.State{}, 457 operation.State{ 458 Started: true, 459 Kind: operation.Continue, 460 Step: operation.Pending, 461 Hook: &hook.Info{Kind: hooks.Start}, 462 }, 463 ) 464 } 465 } 466 467 func (s *RunHookSuite) TestCommitSuccess_Start_Preserve(c *gc.C) { 468 for i, newHook := range []newHook{ 469 (operation.Factory).NewRunHook, 470 (operation.Factory).NewRetryHook, 471 (operation.Factory).NewSkipHook, 472 } { 473 c.Logf("variant %d", i) 474 s.testCommitSuccess(c, 475 newHook, 476 hook.Info{Kind: hooks.Start}, 477 overwriteState, 478 operation.State{ 479 Started: true, 480 CollectMetricsTime: 1234567, 481 Kind: operation.Continue, 482 Step: operation.Pending, 483 Hook: &hook.Info{Kind: hooks.Start}, 484 }, 485 ) 486 } 487 } 488 489 func (s *RunHookSuite) testQueueHook_BlankSlate(c *gc.C, cause, effect hooks.Kind) { 490 for i, newHook := range []newHook{ 491 (operation.Factory).NewRunHook, 492 (operation.Factory).NewRetryHook, 493 (operation.Factory).NewSkipHook, 494 } { 495 c.Logf("variant %d", i) 496 s.testCommitSuccess(c, 497 newHook, 498 hook.Info{Kind: cause}, 499 operation.State{}, 500 operation.State{ 501 Kind: operation.RunHook, 502 Step: operation.Queued, 503 Hook: &hook.Info{Kind: effect}, 504 }, 505 ) 506 } 507 } 508 509 func (s *RunHookSuite) testQueueHook_Preserve(c *gc.C, cause, effect hooks.Kind) { 510 for i, newHook := range []newHook{ 511 (operation.Factory).NewRunHook, 512 (operation.Factory).NewRetryHook, 513 (operation.Factory).NewSkipHook, 514 } { 515 c.Logf("variant %d", i) 516 s.testCommitSuccess(c, 517 newHook, 518 hook.Info{Kind: cause}, 519 overwriteState, 520 operation.State{ 521 Kind: operation.RunHook, 522 Step: operation.Queued, 523 Hook: &hook.Info{Kind: effect}, 524 Started: true, 525 CollectMetricsTime: 1234567, 526 }, 527 ) 528 } 529 } 530 531 func (s *RunHookSuite) TestQueueHook_Install_BlankSlate(c *gc.C) { 532 s.testQueueHook_BlankSlate(c, hooks.Install, hooks.ConfigChanged) 533 } 534 535 func (s *RunHookSuite) TestQueueHook_Install_Preserve(c *gc.C) { 536 s.testQueueHook_Preserve(c, hooks.Install, hooks.ConfigChanged) 537 } 538 539 func (s *RunHookSuite) TestQueueHook_UpgradeCharm_BlankSlate(c *gc.C) { 540 s.testQueueHook_BlankSlate(c, hooks.UpgradeCharm, hooks.ConfigChanged) 541 } 542 543 func (s *RunHookSuite) TestQueueHook_UpgradeCharm_Preserve(c *gc.C) { 544 s.testQueueHook_Preserve(c, hooks.UpgradeCharm, hooks.ConfigChanged) 545 } 546 547 func (s *RunHookSuite) testQueueNothing_BlankSlate(c *gc.C, hookInfo hook.Info) { 548 for i, newHook := range []newHook{ 549 (operation.Factory).NewRunHook, 550 (operation.Factory).NewRetryHook, 551 (operation.Factory).NewSkipHook, 552 } { 553 c.Logf("variant %d", i) 554 s.testCommitSuccess(c, 555 newHook, 556 hookInfo, 557 operation.State{}, 558 operation.State{ 559 Kind: operation.Continue, 560 Step: operation.Pending, 561 Hook: &hookInfo, 562 }, 563 ) 564 } 565 } 566 567 func (s *RunHookSuite) testQueueNothing_Preserve(c *gc.C, hookInfo hook.Info) { 568 for i, newHook := range []newHook{ 569 (operation.Factory).NewRunHook, 570 (operation.Factory).NewRetryHook, 571 (operation.Factory).NewSkipHook, 572 } { 573 c.Logf("variant %d", i) 574 s.testCommitSuccess(c, 575 newHook, 576 hookInfo, 577 overwriteState, 578 operation.State{ 579 Kind: operation.Continue, 580 Step: operation.Pending, 581 Hook: &hookInfo, 582 Started: true, 583 CollectMetricsTime: 1234567, 584 }, 585 ) 586 } 587 } 588 589 func (s *RunHookSuite) TestQueueNothing_Stop_BlankSlate(c *gc.C) { 590 s.testQueueNothing_BlankSlate(c, hook.Info{ 591 Kind: hooks.Stop, 592 }) 593 } 594 595 func (s *RunHookSuite) TestQueueNothing_Stop_Preserve(c *gc.C) { 596 s.testQueueNothing_Preserve(c, hook.Info{ 597 Kind: hooks.Stop, 598 }) 599 } 600 601 func (s *RunHookSuite) TestQueueNothing_RelationJoined_BlankSlate(c *gc.C) { 602 s.testQueueNothing_BlankSlate(c, hook.Info{ 603 Kind: hooks.RelationJoined, 604 RemoteUnit: "u/0", 605 }) 606 } 607 608 func (s *RunHookSuite) TestQueueNothing_RelationJoined_Preserve(c *gc.C) { 609 s.testQueueNothing_Preserve(c, hook.Info{ 610 Kind: hooks.RelationJoined, 611 RemoteUnit: "u/0", 612 }) 613 } 614 615 func (s *RunHookSuite) TestQueueNothing_RelationChanged_BlankSlate(c *gc.C) { 616 s.testQueueNothing_BlankSlate(c, hook.Info{ 617 Kind: hooks.RelationChanged, 618 RemoteUnit: "u/0", 619 }) 620 } 621 622 func (s *RunHookSuite) TestQueueNothing_RelationChanged_Preserve(c *gc.C) { 623 s.testQueueNothing_Preserve(c, hook.Info{ 624 Kind: hooks.RelationChanged, 625 RemoteUnit: "u/0", 626 }) 627 } 628 629 func (s *RunHookSuite) TestQueueNothing_RelationDeparted_BlankSlate(c *gc.C) { 630 s.testQueueNothing_BlankSlate(c, hook.Info{ 631 Kind: hooks.RelationDeparted, 632 RemoteUnit: "u/0", 633 }) 634 } 635 636 func (s *RunHookSuite) TestQueueNothing_RelationDeparted_Preserve(c *gc.C) { 637 s.testQueueNothing_Preserve(c, hook.Info{ 638 Kind: hooks.RelationDeparted, 639 RemoteUnit: "u/0", 640 }) 641 } 642 643 func (s *RunHookSuite) TestQueueNothing_RelationBroken_BlankSlate(c *gc.C) { 644 s.testQueueNothing_BlankSlate(c, hook.Info{ 645 Kind: hooks.RelationBroken, 646 }) 647 } 648 649 func (s *RunHookSuite) TestQueueNothing_RelationBroken_Preserve(c *gc.C) { 650 s.testQueueNothing_Preserve(c, hook.Info{ 651 Kind: hooks.RelationBroken, 652 }) 653 } 654 655 func (s *RunHookSuite) testCommitSuccess_CollectMetricsTime(c *gc.C, newHook newHook) { 656 hookInfo := hook.Info{Kind: hooks.CollectMetrics} 657 658 callbacks := &CommitHookCallbacks{ 659 MockCommitHook: &MockCommitHook{}, 660 } 661 factory := operation.NewFactory(nil, nil, callbacks, nil) 662 op, err := newHook(factory, hookInfo) 663 c.Assert(err, jc.ErrorIsNil) 664 665 nowBefore := time.Now().Unix() 666 newState, err := op.Commit(overwriteState) 667 c.Assert(err, jc.ErrorIsNil) 668 669 nowAfter := time.Now().Unix() 670 nowWritten := newState.CollectMetricsTime 671 c.Logf("%d <= %d <= %d", nowBefore, nowWritten, nowAfter) 672 c.Check(nowBefore <= nowWritten, jc.IsTrue) 673 c.Check(nowWritten <= nowAfter, jc.IsTrue) 674 675 // Check the other fields match. 676 newState.CollectMetricsTime = 0 677 c.Check(newState, gc.DeepEquals, &operation.State{ 678 Started: true, 679 Kind: operation.Continue, 680 Step: operation.Pending, 681 Hook: &hookInfo, 682 }) 683 } 684 685 func (s *RunHookSuite) TestCommitSuccess_CollectMetricsTime_Run(c *gc.C) { 686 s.testCommitSuccess_CollectMetricsTime(c, (operation.Factory).NewRunHook) 687 } 688 689 func (s *RunHookSuite) TestCommitSuccess_CollectMetricsTime_Retry(c *gc.C) { 690 s.testCommitSuccess_CollectMetricsTime(c, (operation.Factory).NewRetryHook) 691 } 692 693 func (s *RunHookSuite) TestCommitSuccess_CollectMetricsTime_Skip(c *gc.C) { 694 s.testCommitSuccess_CollectMetricsTime(c, (operation.Factory).NewSkipHook) 695 }