github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/upgrades/upgrade_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgrades_test 5 6 import ( 7 "errors" 8 "strings" 9 stdtesting "testing" 10 11 gc "launchpad.net/gocheck" 12 13 "launchpad.net/juju-core/agent" 14 "launchpad.net/juju-core/state" 15 "launchpad.net/juju-core/state/api" 16 "launchpad.net/juju-core/state/api/params" 17 coretesting "launchpad.net/juju-core/testing" 18 jc "launchpad.net/juju-core/testing/checkers" 19 "launchpad.net/juju-core/testing/testbase" 20 "launchpad.net/juju-core/upgrades" 21 "launchpad.net/juju-core/version" 22 ) 23 24 func TestPackage(t *stdtesting.T) { 25 coretesting.MgoTestPackage(t) 26 } 27 28 // assertExpectedSteps is a helper function used to check that the upgrade steps match 29 // what is expected for a version. 30 func assertExpectedSteps(c *gc.C, steps []upgrades.Step, expectedSteps []string) { 31 var stepNames = make([]string, len(steps)) 32 for i, step := range steps { 33 stepNames[i] = step.Description() 34 } 35 c.Assert(stepNames, gc.DeepEquals, expectedSteps) 36 } 37 38 type upgradeSuite struct { 39 testbase.LoggingSuite 40 } 41 42 var _ = gc.Suite(&upgradeSuite{}) 43 44 type mockUpgradeOperation struct { 45 targetVersion version.Number 46 steps []upgrades.Step 47 } 48 49 func (m *mockUpgradeOperation) TargetVersion() version.Number { 50 return m.targetVersion 51 } 52 53 func (m *mockUpgradeOperation) Steps() []upgrades.Step { 54 return m.steps 55 } 56 57 type mockUpgradeStep struct { 58 msg string 59 targets []upgrades.Target 60 } 61 62 func (u *mockUpgradeStep) Description() string { 63 return u.msg 64 } 65 66 func (u *mockUpgradeStep) Targets() []upgrades.Target { 67 return u.targets 68 } 69 70 func (u *mockUpgradeStep) Run(context upgrades.Context) error { 71 if strings.HasSuffix(u.msg, "error") { 72 return errors.New("upgrade error occurred") 73 } 74 ctx := context.(*mockContext) 75 ctx.messages = append(ctx.messages, u.msg) 76 return nil 77 } 78 79 type mockContext struct { 80 messages []string 81 agentConfig *mockAgentConfig 82 apiState *api.State 83 state *state.State 84 } 85 86 func (c *mockContext) APIState() *api.State { 87 return c.apiState 88 } 89 90 func (c *mockContext) State() *state.State { 91 return c.state 92 } 93 94 func (c *mockContext) AgentConfig() agent.Config { 95 return c.agentConfig 96 } 97 98 type mockAgentConfig struct { 99 agent.Config 100 dataDir string 101 logDir string 102 tag string 103 namespace string 104 jobs []params.MachineJob 105 apiAddresses []string 106 } 107 108 func (mock *mockAgentConfig) Tag() string { 109 return mock.tag 110 } 111 112 func (mock *mockAgentConfig) DataDir() string { 113 return mock.dataDir 114 } 115 116 func (mock *mockAgentConfig) LogDir() string { 117 return mock.logDir 118 } 119 120 func (mock *mockAgentConfig) Jobs() []params.MachineJob { 121 return mock.jobs 122 } 123 124 func (mock *mockAgentConfig) APIAddresses() ([]string, error) { 125 return mock.apiAddresses, nil 126 } 127 128 func (mock *mockAgentConfig) Value(name string) string { 129 if name == agent.Namespace { 130 return mock.namespace 131 } 132 return "" 133 } 134 135 func targets(targets ...upgrades.Target) (upgradeTargets []upgrades.Target) { 136 for _, t := range targets { 137 upgradeTargets = append(upgradeTargets, t) 138 } 139 return upgradeTargets 140 } 141 142 func upgradeOperations() []upgrades.Operation { 143 steps := []upgrades.Operation{ 144 &mockUpgradeOperation{ 145 targetVersion: version.MustParse("1.12.0"), 146 steps: []upgrades.Step{ 147 &mockUpgradeStep{"step 1 - 1.12.0", nil}, 148 &mockUpgradeStep{"step 2 error", targets(upgrades.HostMachine)}, 149 &mockUpgradeStep{"step 3", targets(upgrades.HostMachine)}, 150 }, 151 }, 152 &mockUpgradeOperation{ 153 targetVersion: version.MustParse("1.16.0"), 154 steps: []upgrades.Step{ 155 &mockUpgradeStep{"step 1 - 1.16.0", targets(upgrades.HostMachine)}, 156 &mockUpgradeStep{"step 2 - 1.16.0", targets(upgrades.HostMachine)}, 157 &mockUpgradeStep{"step 3 - 1.16.0", targets(upgrades.StateServer)}, 158 }, 159 }, 160 &mockUpgradeOperation{ 161 targetVersion: version.MustParse("1.17.0"), 162 steps: []upgrades.Step{ 163 &mockUpgradeStep{"step 1 - 1.17.0", targets(upgrades.HostMachine)}, 164 }, 165 }, 166 &mockUpgradeOperation{ 167 targetVersion: version.MustParse("1.17.1"), 168 steps: []upgrades.Step{ 169 &mockUpgradeStep{"step 1 - 1.17.1", targets(upgrades.HostMachine)}, 170 &mockUpgradeStep{"step 2 - 1.17.1", targets(upgrades.StateServer)}, 171 }, 172 }, 173 &mockUpgradeOperation{ 174 targetVersion: version.MustParse("1.18.0"), 175 steps: []upgrades.Step{ 176 &mockUpgradeStep{"step 1 - 1.18.0", targets(upgrades.HostMachine)}, 177 &mockUpgradeStep{"step 2 - 1.18.0", targets(upgrades.StateServer)}, 178 }, 179 }, 180 &mockUpgradeOperation{ 181 targetVersion: version.MustParse("1.20.0"), 182 steps: []upgrades.Step{ 183 &mockUpgradeStep{"step 1 - 1.20.0", targets(upgrades.AllMachines)}, 184 &mockUpgradeStep{"step 2 - 1.20.0", targets(upgrades.HostMachine)}, 185 &mockUpgradeStep{"step 3 - 1.20.0", targets(upgrades.StateServer)}, 186 }, 187 }, 188 } 189 return steps 190 } 191 192 type upgradeTest struct { 193 about string 194 fromVersion string 195 toVersion string 196 target upgrades.Target 197 expectedSteps []string 198 err string 199 } 200 201 var upgradeTests = []upgradeTest{ 202 { 203 about: "from version excludes steps for same version", 204 fromVersion: "1.18.0", 205 target: upgrades.HostMachine, 206 expectedSteps: []string{}, 207 }, 208 { 209 about: "target version excludes steps for newer version", 210 toVersion: "1.17.1", 211 target: upgrades.HostMachine, 212 expectedSteps: []string{"step 1 - 1.17.0", "step 1 - 1.17.1"}, 213 }, 214 { 215 about: "from version excludes older steps", 216 fromVersion: "1.17.0", 217 target: upgrades.HostMachine, 218 expectedSteps: []string{"step 1 - 1.17.1", "step 1 - 1.18.0"}, 219 }, 220 { 221 about: "incompatible targets excluded", 222 fromVersion: "1.17.1", 223 target: upgrades.StateServer, 224 expectedSteps: []string{"step 2 - 1.18.0"}, 225 }, 226 { 227 about: "allMachines matches everything", 228 fromVersion: "1.18.1", 229 toVersion: "1.20.0", 230 target: upgrades.HostMachine, 231 expectedSteps: []string{"step 1 - 1.20.0", "step 2 - 1.20.0"}, 232 }, 233 { 234 about: "allMachines matches everything", 235 fromVersion: "1.18.1", 236 toVersion: "1.20.0", 237 target: upgrades.StateServer, 238 expectedSteps: []string{"step 1 - 1.20.0", "step 3 - 1.20.0"}, 239 }, 240 { 241 about: "error aborts, subsequent steps not run", 242 fromVersion: "1.10.0", 243 target: upgrades.HostMachine, 244 expectedSteps: []string{"step 1 - 1.12.0"}, 245 err: "step 2 error: upgrade error occurred", 246 }, 247 { 248 about: "default from version is 1.16", 249 fromVersion: "", 250 target: upgrades.StateServer, 251 expectedSteps: []string{"step 2 - 1.17.1", "step 2 - 1.18.0"}, 252 }, 253 } 254 255 func (s *upgradeSuite) TestPerformUpgrade(c *gc.C) { 256 s.PatchValue(upgrades.UpgradeOperations, upgradeOperations) 257 for i, test := range upgradeTests { 258 c.Logf("%d: %s", i, test.about) 259 var messages []string 260 ctx := &mockContext{ 261 messages: messages, 262 } 263 fromVersion := version.Zero 264 if test.fromVersion != "" { 265 fromVersion = version.MustParse(test.fromVersion) 266 } 267 toVersion := version.MustParse("1.18.0") 268 if test.toVersion != "" { 269 toVersion = version.MustParse(test.toVersion) 270 } 271 vers := version.Current 272 vers.Number = toVersion 273 s.PatchValue(&version.Current, vers) 274 err := upgrades.PerformUpgrade(fromVersion, test.target, ctx) 275 if test.err == "" { 276 c.Check(err, gc.IsNil) 277 } else { 278 c.Check(err, gc.ErrorMatches, test.err) 279 } 280 c.Check(ctx.messages, jc.DeepEquals, test.expectedSteps) 281 } 282 } 283 284 func (s *upgradeSuite) TestUpgradeOperationsOrdered(c *gc.C) { 285 var previous version.Number 286 for i, utv := range (*upgrades.UpgradeOperations)() { 287 vers := utv.TargetVersion() 288 if i > 0 { 289 c.Check(previous.Compare(vers), gc.Equals, -1) 290 } 291 previous = vers 292 } 293 } 294 295 var expectedVersions = []string{"1.18.0"} 296 297 func (s *upgradeSuite) TestUpgradeOperationsVersions(c *gc.C) { 298 var versions []string 299 for _, utv := range (*upgrades.UpgradeOperations)() { 300 versions = append(versions, utv.TargetVersion().String()) 301 302 } 303 c.Assert(versions, gc.DeepEquals, expectedVersions) 304 }