github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/modelgeneration_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "time" 8 9 "github.com/juju/charm/v12" 10 "github.com/juju/clock/testclock" 11 "github.com/juju/errors" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/core/model" 16 "github.com/juju/juju/core/settings" 17 "github.com/juju/juju/state" 18 "github.com/juju/juju/testing" 19 ) 20 21 const ( 22 newBranchName = "new-branch" 23 newBranchCreator = "new-branch-user" 24 branchCommitter = "commit-user" 25 ) 26 27 type generationSuite struct { 28 ConnSuite 29 30 ch *state.Charm 31 } 32 33 var _ = gc.Suite(&generationSuite{}) 34 35 func (s *generationSuite) TestBranchNameNotFound(c *gc.C) { 36 _, err := s.Model.Branch("non-extant-branch") 37 c.Assert(errors.IsNotFound(err), jc.IsTrue) 38 } 39 40 func (s *generationSuite) TestAddBranchSuccess(c *gc.C) { 41 s.setupTestingClock(c) 42 gen := s.addBranch(c) 43 44 c.Assert(gen, gc.NotNil) 45 c.Check(gen.ModelUUID(), gc.Equals, s.Model.UUID()) 46 c.Check(gen.GenerationId(), gc.Equals, 0) 47 c.Check(gen.Created(), gc.Not(gc.Equals), 0) 48 c.Check(gen.CreatedBy(), gc.Equals, newBranchCreator) 49 c.Check(gen.BranchName(), gc.Equals, newBranchName) 50 c.Check(gen.IsCompleted(), jc.IsFalse) 51 c.Check(gen.CompletedBy(), gc.Equals, "") 52 } 53 54 func (s *generationSuite) TestAssignApplicationCompletedError(c *gc.C) { 55 s.setupTestingClock(c) 56 gen := s.addBranch(c) 57 58 // Absence of changes will result in an aborted generation. 59 _, err := gen.Commit(branchCommitter) 60 c.Assert(err, jc.ErrorIsNil) 61 62 c.Assert(gen.Refresh(), jc.ErrorIsNil) 63 c.Assert(gen.AssignApplication("redis"), gc.ErrorMatches, "branch was already aborted") 64 } 65 66 func (s *generationSuite) TestAssignApplicationSuccess(c *gc.C) { 67 gen := s.addBranch(c) 68 69 c.Assert(gen.AssignApplication("redis"), jc.ErrorIsNil) 70 c.Assert(gen.Refresh(), jc.ErrorIsNil) 71 c.Check(gen.AssignedUnits(), gc.DeepEquals, map[string][]string{"redis": {}}) 72 73 // Idempotent. 74 c.Assert(gen.AssignApplication("redis"), jc.ErrorIsNil) 75 c.Assert(gen.Refresh(), jc.ErrorIsNil) 76 c.Check(gen.AssignedUnits(), gc.DeepEquals, map[string][]string{"redis": {}}) 77 } 78 79 func (s *generationSuite) TestAssignUnitBranchAbortedError(c *gc.C) { 80 s.setupTestingClock(c) 81 gen := s.addBranch(c) 82 83 // Absence of changes will result in an aborted generation. 84 _, err := gen.Commit(branchCommitter) 85 86 c.Assert(err, jc.ErrorIsNil) 87 88 c.Assert(gen.Refresh(), jc.ErrorIsNil) 89 c.Assert(gen.AssignUnit("redis/0"), gc.ErrorMatches, "branch was already aborted") 90 } 91 92 func (s *generationSuite) TestAssignUnitNotExistsError(c *gc.C) { 93 s.setupTestingClock(c) 94 gen := s.addBranch(c) 95 c.Assert(gen.AssignUnit("redis/0"), gc.ErrorMatches, `unit "redis/0" not found`) 96 } 97 98 func (s *generationSuite) TestAssignUnitBranchCommittedError(c *gc.C) { 99 s.setupTestingClock(c) 100 gen := s.setupAssignAllUnits(c) 101 102 // Make a change so that commit is a real commit with a generation ID. 103 c.Assert(gen.AssignApplication("riak"), jc.ErrorIsNil) 104 c.Assert(gen.Refresh(), jc.ErrorIsNil) 105 _, err := gen.Commit(branchCommitter) 106 107 c.Assert(err, jc.ErrorIsNil) 108 109 c.Assert(gen.Refresh(), jc.ErrorIsNil) 110 c.Assert(gen.AssignUnit("redis/0"), gc.ErrorMatches, "branch was already committed") 111 } 112 113 func (s *generationSuite) TestAssignUnitSuccess(c *gc.C) { 114 s.setupTestingClock(c) 115 gen := s.setupAssignAllUnits(c) 116 117 c.Assert(gen.AssignUnit("riak/0"), jc.ErrorIsNil) 118 119 expected := map[string][]string{"riak": {"riak/0"}} 120 121 c.Assert(gen.Refresh(), jc.ErrorIsNil) 122 c.Check(gen.AssignedUnits(), gc.DeepEquals, expected) 123 124 // Idempotent. 125 c.Assert(gen.AssignUnit("riak/0"), jc.ErrorIsNil) 126 c.Assert(gen.Refresh(), jc.ErrorIsNil) 127 c.Check(gen.AssignedUnits(), gc.DeepEquals, expected) 128 } 129 130 func (s *generationSuite) TestAssignAllUnitsSuccessAll(c *gc.C) { 131 gen := s.setupAssignAllUnits(c) 132 133 c.Assert(gen.AssignAllUnits("riak"), jc.ErrorIsNil) 134 135 expected := []string{"riak/0", "riak/1", "riak/2", "riak/3"} 136 137 c.Assert(gen.Refresh(), jc.ErrorIsNil) 138 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 139 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 140 141 // Idempotent. 142 c.Assert(gen.AssignAllUnits("riak"), jc.ErrorIsNil) 143 c.Assert(gen.Refresh(), jc.ErrorIsNil) 144 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 145 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 146 } 147 148 func (s *generationSuite) TestAssignAllUnitsSuccessRemaining(c *gc.C) { 149 gen := s.setupAssignAllUnits(c) 150 151 c.Assert(gen.AssignUnit("riak/2"), jc.ErrorIsNil) 152 c.Assert(gen.AssignAllUnits("riak"), jc.ErrorIsNil) 153 154 expected := []string{"riak/2", "riak/3", "riak/1", "riak/0"} 155 156 c.Assert(gen.Refresh(), jc.ErrorIsNil) 157 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 158 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 159 160 // Idempotent. 161 c.Assert(gen.AssignAllUnits("riak"), jc.ErrorIsNil) 162 c.Assert(gen.Refresh(), jc.ErrorIsNil) 163 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 164 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 165 } 166 167 func (s *generationSuite) TestAssignNumUnitsSuccessRemaining(c *gc.C) { 168 gen := s.setupAssignAllUnits(c) 169 170 expected := []string{"riak/0", "riak/1", "riak/2", "riak/3"} 171 172 c.Assert(gen.AssignUnits("riak", 1), jc.ErrorIsNil) 173 c.Assert(gen.Refresh(), jc.ErrorIsNil) 174 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 175 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected[:1]) 176 177 c.Assert(gen.AssignUnits("riak", 2), jc.ErrorIsNil) 178 c.Assert(gen.Refresh(), jc.ErrorIsNil) 179 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 180 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected[:3]) 181 182 c.Assert(gen.AssignUnits("riak", 1), jc.ErrorIsNil) 183 c.Assert(gen.Refresh(), jc.ErrorIsNil) 184 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 185 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 186 187 // Idempotent. 188 c.Assert(gen.AssignAllUnits("riak"), jc.ErrorIsNil) 189 c.Assert(gen.Refresh(), jc.ErrorIsNil) 190 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 191 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 192 } 193 194 func (s *generationSuite) TestAssignUnitsNoOperations(c *gc.C) { 195 gen := s.setupAssignUnits(c) 196 197 c.Assert(gen.AssignUnits("riak", 1), jc.ErrorIsNil) 198 c.Assert(gen.Refresh(), jc.ErrorIsNil) 199 c.Check(gen.AssignedUnits(), gc.HasLen, 0) 200 } 201 202 func (s *generationSuite) TestAssignNumUnitsSelectAll(c *gc.C) { 203 gen := s.setupAssignAllUnits(c) 204 205 expected := []string{"riak/0", "riak/1", "riak/2", "riak/3"} 206 207 c.Assert(gen.AssignUnits("riak", 100), jc.ErrorIsNil) 208 c.Assert(gen.Refresh(), jc.ErrorIsNil) 209 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 210 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 211 212 // Idempotent. 213 c.Assert(gen.AssignAllUnits("riak"), jc.ErrorIsNil) 214 c.Assert(gen.Refresh(), jc.ErrorIsNil) 215 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 216 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, expected) 217 } 218 219 func (s *generationSuite) TestAssignAllUnitsCompletedError(c *gc.C) { 220 s.setupTestingClock(c) 221 gen := s.setupAssignAllUnits(c) 222 223 // Absence of changes will result in an aborted generation. 224 _, err := gen.Commit(branchCommitter) 225 c.Assert(err, jc.ErrorIsNil) 226 227 c.Assert(gen.Refresh(), jc.ErrorIsNil) 228 c.Assert(gen.AssignAllUnits("riak"), gc.ErrorMatches, "branch was already aborted") 229 } 230 231 func (s *generationSuite) TestCommitAssignsRemainingUnits(c *gc.C) { 232 s.setupTestingClock(c) 233 gen := s.setupAssignAllUnits(c) 234 235 c.Assert(gen.AssignUnit("riak/0"), jc.ErrorIsNil) 236 c.Assert(gen.Refresh(), jc.ErrorIsNil) 237 238 genId, err := gen.Commit(branchCommitter) 239 c.Assert(err, jc.ErrorIsNil) 240 c.Check(genId, gc.Not(gc.Equals), 0) 241 242 c.Assert(gen.Refresh(), jc.ErrorIsNil) 243 c.Check(gen.IsCompleted(), jc.IsTrue) 244 c.Check(gen.CompletedBy(), gc.Equals, branchCommitter) 245 c.Check(gen.AssignedUnits(), gc.HasLen, 1) 246 c.Check(gen.AssignedUnits()["riak"], jc.SameContents, []string{"riak/0", "riak/1", "riak/2", "riak/3"}) 247 248 // Idempotent. 249 _, err = gen.Commit(branchCommitter) 250 c.Assert(err, jc.ErrorIsNil) 251 } 252 253 func (s *generationSuite) TestCommitNoChangesEffectivelyAborted(c *gc.C) { 254 s.setupTestingClock(c) 255 gen := s.addBranch(c) 256 257 genId, err := gen.Commit(branchCommitter) 258 c.Assert(err, jc.ErrorIsNil) 259 c.Check(genId, gc.Equals, 0) 260 261 c.Assert(gen.Refresh(), jc.ErrorIsNil) 262 c.Check(gen.IsCompleted(), jc.IsTrue) 263 c.Check(gen.CompletedBy(), gc.Equals, branchCommitter) 264 } 265 266 func (s *generationSuite) TestCommitAppliesConfigDeltas(c *gc.C) { 267 s.setupTestingClock(c) 268 gen := s.setupAssignAllUnits(c) 269 270 app, err := s.State.Application("riak") 271 c.Assert(err, jc.ErrorIsNil) 272 273 newCfg := map[string]interface{}{"http_port": int64(9999)} 274 c.Assert(app.UpdateCharmConfig(newBranchName, newCfg), jc.ErrorIsNil) 275 c.Assert(gen.Refresh(), jc.ErrorIsNil) 276 277 _, err = gen.Commit(branchCommitter) 278 c.Assert(err, jc.ErrorIsNil) 279 c.Assert(gen.Refresh(), jc.ErrorIsNil) 280 281 cfg, err := app.CharmConfig(model.GenerationMaster) 282 c.Assert(err, jc.ErrorIsNil) 283 284 c.Check(cfg, gc.DeepEquals, charm.Settings(newCfg)) 285 } 286 287 func (s *generationSuite) TestAbortSuccess(c *gc.C) { 288 s.setupTestingClock(c) 289 290 gen := s.addBranch(c) 291 292 err := gen.Abort(branchCommitter) 293 c.Assert(err, jc.ErrorIsNil) 294 295 // Idempotent. 296 err = gen.Refresh() 297 c.Assert(err, jc.ErrorIsNil) 298 err = gen.Abort(branchCommitter) 299 c.Assert(err, jc.ErrorIsNil) 300 } 301 302 func (s *generationSuite) TestAbortSuccessApplicationNoAssignedUnits(c *gc.C) { 303 s.setupTestingClock(c) 304 305 gen := s.addBranch(c) 306 err := gen.AssignApplication("riak") 307 c.Assert(err, jc.ErrorIsNil) 308 err = gen.Refresh() 309 c.Assert(err, jc.ErrorIsNil) 310 311 err = gen.Abort(branchCommitter) 312 c.Assert(err, jc.ErrorIsNil) 313 } 314 315 func (s *generationSuite) TestAbortFailsAssignedUnits(c *gc.C) { 316 s.setupTestingClock(c) 317 318 gen := s.setupAssignAllUnits(c) 319 err := gen.AssignUnit("riak/0") 320 c.Assert(err, jc.ErrorIsNil) 321 err = gen.Refresh() 322 c.Assert(err, jc.ErrorIsNil) 323 324 err = gen.Abort(branchCommitter) 325 c.Assert(err, gc.ErrorMatches, "branch is in progress. Either reset values on tracking units and commit the branch or remove them to abort.") 326 } 327 328 func (s *generationSuite) TestAbortCommittedBranch(c *gc.C) { 329 s.setupTestingClock(c) 330 331 gen := s.setupAssignAllUnits(c) 332 err := gen.AssignUnit("riak/0") 333 c.Assert(err, jc.ErrorIsNil) 334 err = gen.Refresh() 335 c.Assert(err, jc.ErrorIsNil) 336 337 _, err = gen.Commit(branchCommitter) 338 c.Assert(err, jc.ErrorIsNil) 339 err = gen.Refresh() 340 c.Assert(err, jc.ErrorIsNil) 341 342 err = gen.Abort(branchCommitter) 343 c.Assert(err, gc.ErrorMatches, "branch was already committed") 344 } 345 346 func (s *generationSuite) TestBranchCharmConfigDeltas(c *gc.C) { 347 gen := s.setupAssignAllUnits(c) 348 c.Assert(gen.Config(), gc.HasLen, 0) 349 350 current := state.GetPopulatedSettings(map[string]interface{}{ 351 "http_port": 8098, 352 "handoff_port": 8099, 353 "riak_version": "1.1.4-1", 354 }) 355 356 // Process a modification, deletion, and addition. 357 changes := charm.Settings{ 358 "http_port": 8100, 359 "handoff_port": nil, 360 "node_name": "nodey-node", 361 } 362 c.Assert(gen.UpdateCharmConfig("riak", current, changes), jc.ErrorIsNil) 363 c.Assert(gen.Refresh(), jc.ErrorIsNil) 364 c.Check(gen.Config(), gc.DeepEquals, map[string]settings.ItemChanges{"riak": { 365 settings.MakeDeletion("handoff_port", 8099), 366 settings.MakeModification("http_port", 8098, 8100), 367 settings.MakeAddition("node_name", "nodey-node"), 368 }}) 369 370 // Now simulate node_name being set on master in the meantime, 371 // along with changes to http_port and handoff_port. 372 current = state.GetPopulatedSettings(map[string]interface{}{ 373 "http_port": 100, 374 "handoff_port": 100, 375 "riak_version": "1.1.4-1", 376 "node_name": "come-lately", 377 }) 378 379 // Re-set previously deleted handoff_port, update node_name. 380 changes = charm.Settings{ 381 "handoff_port": 9000, 382 "node_name": "latest-nodey-node", 383 } 384 c.Assert(gen.UpdateCharmConfig("riak", current, changes), jc.ErrorIsNil) 385 c.Assert(gen.Refresh(), jc.ErrorIsNil) 386 387 // handoff_port old value is the original. 388 // http_port unchanged. 389 // node_name remains as an addition. 390 c.Check(gen.Config(), gc.DeepEquals, map[string]settings.ItemChanges{"riak": { 391 settings.MakeModification("handoff_port", 8099, 9000), 392 settings.MakeModification("http_port", 8098, 8100), 393 settings.MakeAddition("node_name", "latest-nodey-node"), 394 }}) 395 } 396 397 func (s *generationSuite) TestBranches(c *gc.C) { 398 s.setupTestingClock(c) 399 400 branches, err := s.State.Branches() 401 c.Assert(err, jc.ErrorIsNil) 402 c.Check(branches, gc.HasLen, 0) 403 404 _ = s.addBranch(c) 405 branches, err = s.State.Branches() 406 c.Assert(err, jc.ErrorIsNil) 407 c.Check(branches, gc.HasLen, 1) 408 c.Check(branches[0].BranchName(), gc.Equals, newBranchName) 409 410 const otherBranchName = "other-branch" 411 c.Assert(s.Model.AddBranch(otherBranchName, newBranchCreator), jc.ErrorIsNil) 412 branches, err = s.State.Branches() 413 c.Assert(err, jc.ErrorIsNil) 414 c.Check(branches, gc.HasLen, 2) 415 416 // Commit the newly added branch. Branches call should not return it. 417 branch, err := s.Model.Branch(otherBranchName) 418 c.Assert(err, jc.ErrorIsNil) 419 _, err = branch.Commit(newBranchCreator) 420 c.Assert(err, jc.ErrorIsNil) 421 422 branches, err = s.State.Branches() 423 c.Assert(err, jc.ErrorIsNil) 424 c.Check(branches, gc.HasLen, 1) 425 c.Check(branches[0].BranchName(), gc.Equals, newBranchName) 426 } 427 428 func (s *generationSuite) TestUnitBranch(c *gc.C) { 429 s.setupTestingClock(c) 430 431 branchA := s.setupAssignAllUnits(c) 432 c.Assert(branchA.AssignUnit("riak/0"), jc.ErrorIsNil) 433 434 c.Assert(branchA.AssignUnit("riak/2"), jc.ErrorIsNil) 435 c.Assert(s.Model.AddBranch("banana", newBranchCreator), jc.ErrorIsNil) 436 branchB, err := s.Model.Branch("banana") 437 c.Assert(err, jc.ErrorIsNil) 438 439 c.Assert(branchB.AssignUnit("riak/1"), jc.ErrorIsNil) 440 441 unit2Branch, err := state.UnitBranch(s.Model, "riak/2") 442 c.Assert(err, jc.ErrorIsNil) 443 c.Assert(unit2Branch.BranchName(), gc.Equals, branchA.BranchName()) 444 445 unit1Branch, err := state.UnitBranch(s.Model, "riak/1") 446 c.Assert(err, jc.ErrorIsNil) 447 c.Assert(unit1Branch.BranchName(), gc.Equals, branchB.BranchName()) 448 449 // Idempotent. 450 unit2BranchTake2, err := state.UnitBranch(s.Model, "riak/2") 451 c.Assert(err, jc.ErrorIsNil) 452 c.Assert(unit2BranchTake2.BranchName(), gc.Equals, unit2Branch.BranchName()) 453 } 454 455 func (s *generationSuite) TestApplicationBranches(c *gc.C) { 456 s.setupTestingClock(c) 457 458 branchA := s.setupAssignAllUnits(c) 459 c.Assert(branchA.AssignUnit("riak/0"), jc.ErrorIsNil) 460 461 appBranchesA, err := state.ApplicationBranches(s.Model, "riak") 462 c.Assert(err, jc.ErrorIsNil) 463 c.Assert(appBranchesA, gc.HasLen, 1) 464 c.Assert(appBranchesA[0].BranchName(), gc.Equals, branchA.BranchName()) 465 466 c.Assert(s.Model.AddBranch("banana", newBranchCreator), jc.ErrorIsNil) 467 branchB, err := s.Model.Branch("banana") 468 c.Assert(err, jc.ErrorIsNil) 469 470 appBranchesATake2, err := state.ApplicationBranches(s.Model, "riak") 471 c.Assert(err, jc.ErrorIsNil) 472 c.Assert(appBranchesATake2, gc.HasLen, 1) 473 c.Assert(appBranchesA[0].BranchName(), gc.Equals, appBranchesATake2[0].BranchName()) 474 475 c.Assert(branchB.AssignUnit("riak/1"), jc.ErrorIsNil) 476 477 appBranchesA, err = state.ApplicationBranches(s.Model, "riak") 478 c.Assert(err, jc.ErrorIsNil) 479 c.Assert(appBranchesA, gc.HasLen, 2) 480 481 // Idempotent. 482 appBranchesATake2, err = state.ApplicationBranches(s.Model, "riak") 483 c.Assert(err, jc.ErrorIsNil) 484 c.Assert(appBranchesATake2, gc.DeepEquals, appBranchesA) 485 } 486 487 func (s *generationSuite) TestDestroyCleansupBranches(c *gc.C) { 488 s.setupTestingClock(c) 489 490 branches, err := s.State.Branches() 491 c.Assert(err, jc.ErrorIsNil) 492 c.Check(branches, gc.HasLen, 0) 493 494 _ = s.addBranch(c) 495 496 branches, err = s.State.Branches() 497 c.Assert(err, jc.ErrorIsNil) 498 c.Check(branches, gc.HasLen, 1) 499 c.Check(branches[0].BranchName(), gc.Equals, newBranchName) 500 501 c.Assert(s.Model.Destroy(state.DestroyModelParams{}), jc.ErrorIsNil) 502 c.Assert(s.Model.Refresh(), jc.ErrorIsNil) 503 assertNeedsCleanup(c, s.State) 504 assertCleanupRuns(c, s.State) 505 506 branches, err = s.State.Branches() 507 c.Assert(err, jc.ErrorIsNil) 508 c.Check(branches, gc.HasLen, 0) 509 } 510 511 func (s *generationSuite) setupAssignAllUnits(c *gc.C) *state.Generation { 512 var cfgYAML = ` 513 options: 514 http_port: {default: 8089, description: HTTP Port, type: int} 515 ` 516 s.ch = s.AddConfigCharm(c, "riak", cfgYAML, 666) 517 518 riak := s.AddTestingApplication(c, "riak", s.ch) 519 for i := 0; i < 4; i++ { 520 _, err := riak.AddUnit(state.AddUnitParams{}) 521 c.Assert(err, jc.ErrorIsNil) 522 } 523 524 return s.addBranch(c) 525 } 526 527 func (s *generationSuite) setupAssignUnits(c *gc.C) *state.Generation { 528 var cfgYAML = ` 529 options: 530 http_port: {default: 8089, description: HTTP Port, type: int} 531 ` 532 s.ch = s.AddConfigCharm(c, "riak", cfgYAML, 666) 533 534 s.AddTestingApplication(c, "riak", s.ch) 535 536 return s.addBranch(c) 537 } 538 539 func (s *generationSuite) addBranch(c *gc.C) *state.Generation { 540 c.Assert(s.Model.AddBranch(newBranchName, newBranchCreator), jc.ErrorIsNil) 541 branch, err := s.Model.Branch(newBranchName) 542 c.Assert(err, jc.ErrorIsNil) 543 return branch 544 } 545 546 func (s *generationSuite) setupTestingClock(c *gc.C) { 547 clock := testclock.NewClock(testing.NonZeroTime()) 548 clock.Advance(400000 * time.Hour) 549 c.Assert(s.State.SetClockForTesting(clock), jc.ErrorIsNil) 550 }