github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/state/restore_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 9 jc "github.com/juju/testing/checkers" 10 jujutxn "github.com/juju/txn" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/state" 14 statetesting "github.com/juju/juju/state/testing" 15 ) 16 17 // RestoreInfoSuite is *tremendously* incomplete: this test exists purely to 18 // verify that independent RestoreInfoSetters can be created concurrently. 19 // This says nothing about whether that's a good idea (it's *not*) but it's 20 // what we currently do and we need it to not just arbitrarily fail. 21 // 22 // TODO(fwereade): 2016-03-23 lp:1560920 23 // None of the other functionality is tested, and little of it is reliable or 24 // consistent with the other state code, but that's not for today. 25 type RestoreInfoSuite struct { 26 statetesting.StateSuite 27 info *state.RestoreInfo 28 } 29 30 var _ = gc.Suite(&RestoreInfoSuite{}) 31 32 func (s *RestoreInfoSuite) SetUpTest(c *gc.C) { 33 s.StateSuite.SetUpTest(c) 34 s.info = s.State.RestoreInfo() 35 } 36 37 func (s *RestoreInfoSuite) TestStartsNotActive(c *gc.C) { 38 s.checkStatus(c, state.RestoreNotActive) 39 } 40 41 func (s *RestoreInfoSuite) TestSetBadStatus(c *gc.C) { 42 err := s.info.SetStatus(state.RestoreStatus("LOLLYGAGGING")) 43 c.Check(err, gc.ErrorMatches, "unknown restore status: LOLLYGAGGING") 44 s.checkStatus(c, state.RestoreNotActive) 45 } 46 47 //-------------------------------------- 48 // Whitebox race tests to trigger different paths through the SetStatus 49 // code; use arbitrary sample transitions, full set of valid transitions 50 // are checked further down. 51 func (s *RestoreInfoSuite) TestInsertRaceHarmless(c *gc.C) { 52 defer state.SetBeforeHooks( 53 c, s.State, func() { 54 s.checkSetStatus(c, state.RestorePending) 55 }, 56 ).Check() 57 s.checkSetStatus(c, state.RestorePending) 58 } 59 60 func (s *RestoreInfoSuite) TestInsertRaceFailure(c *gc.C) { 61 defer state.SetBeforeHooks( 62 c, s.State, func() { 63 s.checkSetStatus(c, state.RestorePending) 64 s.checkSetStatus(c, state.RestoreInProgress) 65 }, 66 ).Check() 67 s.checkBadSetStatus(c, state.RestorePending) 68 s.checkStatus(c, state.RestoreInProgress) 69 } 70 71 func (s *RestoreInfoSuite) TestUpdateRaceHarmless(c *gc.C) { 72 s.setupInProgress(c) 73 defer state.SetBeforeHooks( 74 c, s.State, func() { 75 s.checkSetStatus(c, state.RestoreFinished) 76 }, 77 ).Check() 78 s.checkSetStatus(c, state.RestoreFinished) 79 } 80 81 func (s *RestoreInfoSuite) TestUpdateRaceFailure(c *gc.C) { 82 s.setupInProgress(c) 83 defer state.SetBeforeHooks( 84 c, s.State, func() { 85 s.checkSetStatus(c, state.RestoreFailed) 86 }, 87 ).Check() 88 s.checkBadSetStatus(c, state.RestoreFinished) 89 s.checkStatus(c, state.RestoreFailed) 90 } 91 92 func (s *RestoreInfoSuite) TestUpdateRaceExhaustion(c *gc.C) { 93 s.setupPending(c) 94 perturb := jujutxn.TestHook{ 95 Before: func() { 96 s.checkSetStatus(c, state.RestoreFailed) 97 }, 98 After: func() { 99 s.checkSetStatus(c, state.RestorePending) 100 }, 101 } 102 defer state.SetTestHooks( 103 c, s.State, 104 perturb, 105 perturb, 106 perturb, 107 ).Check() 108 err := s.info.SetStatus(state.RestoreInProgress) 109 c.Check(err, gc.ErrorMatches, "state changing too quickly; try again soon") 110 } 111 112 //-------------------------------------- 113 // Test NotActive -> ? transitions 114 func (s *RestoreInfoSuite) TestNotActiveSetNotActive(c *gc.C) { 115 s.checkSetStatus(c, state.RestoreNotActive) 116 } 117 118 func (s *RestoreInfoSuite) TestNotActiveSetPending(c *gc.C) { 119 s.checkSetStatus(c, state.RestorePending) 120 } 121 122 func (s *RestoreInfoSuite) TestNotActiveSetInProgress(c *gc.C) { 123 s.checkBadSetStatus(c, state.RestoreFinished) 124 } 125 126 func (s *RestoreInfoSuite) TestNotActiveSetFinished(c *gc.C) { 127 s.checkBadSetStatus(c, state.RestoreFinished) 128 } 129 130 func (s *RestoreInfoSuite) TestNotActiveSetChecked(c *gc.C) { 131 s.checkBadSetStatus(c, state.RestoreChecked) 132 } 133 134 func (s *RestoreInfoSuite) TestNotActiveSetFailed(c *gc.C) { 135 s.checkBadSetStatus(c, state.RestoreFailed) 136 } 137 138 //-------------------------------------- 139 // Test Pending -> ? transitions 140 func (s *RestoreInfoSuite) setupPending(c *gc.C) { 141 s.checkSetStatus(c, state.RestorePending) 142 } 143 144 func (s *RestoreInfoSuite) TestPendingSetNotActive(c *gc.C) { 145 s.setupPending(c) 146 s.checkBadSetStatus(c, state.RestoreNotActive) 147 } 148 149 func (s *RestoreInfoSuite) TestPendingSetPending(c *gc.C) { 150 s.setupPending(c) 151 s.checkSetStatus(c, state.RestorePending) 152 } 153 154 func (s *RestoreInfoSuite) TestPendingSetInProgress(c *gc.C) { 155 s.setupPending(c) 156 s.checkSetStatus(c, state.RestoreInProgress) 157 } 158 159 func (s *RestoreInfoSuite) TestPendingSetFinished(c *gc.C) { 160 s.setupPending(c) 161 s.checkBadSetStatus(c, state.RestoreFinished) 162 } 163 164 func (s *RestoreInfoSuite) TestPendingSetChecked(c *gc.C) { 165 s.setupPending(c) 166 s.checkBadSetStatus(c, state.RestoreChecked) 167 } 168 169 func (s *RestoreInfoSuite) TestPendingSetFailed(c *gc.C) { 170 s.setupPending(c) 171 s.checkSetStatus(c, state.RestoreFailed) 172 } 173 174 //-------------------------------------- 175 // Test InProgress -> ? transitions 176 func (s *RestoreInfoSuite) setupInProgress(c *gc.C) { 177 s.checkSetStatus(c, state.RestorePending) 178 s.checkSetStatus(c, state.RestoreInProgress) 179 } 180 181 func (s *RestoreInfoSuite) TestInProgressSetNotActive(c *gc.C) { 182 s.setupInProgress(c) 183 s.checkBadSetStatus(c, state.RestoreNotActive) 184 } 185 186 func (s *RestoreInfoSuite) TestInProgressSetPending(c *gc.C) { 187 s.setupInProgress(c) 188 s.checkBadSetStatus(c, state.RestorePending) 189 } 190 191 func (s *RestoreInfoSuite) TestInProgressSetInProgress(c *gc.C) { 192 s.setupInProgress(c) 193 s.checkSetStatus(c, state.RestoreInProgress) 194 } 195 196 func (s *RestoreInfoSuite) TestInProgressSetFinished(c *gc.C) { 197 s.setupInProgress(c) 198 s.checkSetStatus(c, state.RestoreFinished) 199 } 200 201 func (s *RestoreInfoSuite) TestInProgressSetChecked(c *gc.C) { 202 s.setupInProgress(c) 203 s.checkBadSetStatus(c, state.RestoreChecked) 204 } 205 206 func (s *RestoreInfoSuite) TestInProgressSetFailed(c *gc.C) { 207 s.setupInProgress(c) 208 s.checkSetStatus(c, state.RestoreFailed) 209 } 210 211 //-------------------------------------- 212 // Test Finished -> ? transitions 213 func (s *RestoreInfoSuite) setupFinished(c *gc.C) { 214 s.checkSetStatus(c, state.RestorePending) 215 s.checkSetStatus(c, state.RestoreInProgress) 216 s.checkSetStatus(c, state.RestoreFinished) 217 } 218 219 func (s *RestoreInfoSuite) TestFinishedSetNotActive(c *gc.C) { 220 s.setupFinished(c) 221 s.checkBadSetStatus(c, state.RestoreNotActive) 222 } 223 224 func (s *RestoreInfoSuite) TestFinishedSetPending(c *gc.C) { 225 s.setupFinished(c) 226 s.checkBadSetStatus(c, state.RestorePending) 227 } 228 229 func (s *RestoreInfoSuite) TestFinishedSetInProgress(c *gc.C) { 230 s.setupFinished(c) 231 s.checkBadSetStatus(c, state.RestoreInProgress) 232 } 233 234 func (s *RestoreInfoSuite) TestFinishedSetFinished(c *gc.C) { 235 s.setupFinished(c) 236 s.checkSetStatus(c, state.RestoreFinished) 237 } 238 239 func (s *RestoreInfoSuite) TestFinishedSetChecked(c *gc.C) { 240 s.setupFinished(c) 241 s.checkSetStatus(c, state.RestoreChecked) 242 } 243 244 func (s *RestoreInfoSuite) TestFinishedSetFailed(c *gc.C) { 245 s.setupFinished(c) 246 s.checkSetStatus(c, state.RestoreFailed) 247 } 248 249 //-------------------------------------- 250 // Test Checked -> ? transitions 251 func (s *RestoreInfoSuite) setupChecked(c *gc.C) { 252 s.checkSetStatus(c, state.RestorePending) 253 s.checkSetStatus(c, state.RestoreInProgress) 254 s.checkSetStatus(c, state.RestoreFinished) 255 s.checkSetStatus(c, state.RestoreChecked) 256 } 257 258 func (s *RestoreInfoSuite) TestCheckedSetNotActive(c *gc.C) { 259 s.setupChecked(c) 260 s.checkBadSetStatus(c, state.RestoreNotActive) 261 } 262 263 func (s *RestoreInfoSuite) TestCheckedSetPending(c *gc.C) { 264 s.setupChecked(c) 265 s.checkSetStatus(c, state.RestorePending) 266 } 267 268 func (s *RestoreInfoSuite) TestCheckedSetInProgress(c *gc.C) { 269 s.setupChecked(c) 270 s.checkBadSetStatus(c, state.RestoreInProgress) 271 } 272 273 func (s *RestoreInfoSuite) TestCheckedSetFinished(c *gc.C) { 274 s.setupChecked(c) 275 s.checkBadSetStatus(c, state.RestoreFinished) 276 } 277 278 func (s *RestoreInfoSuite) TestCheckedSetChecked(c *gc.C) { 279 s.setupChecked(c) 280 s.checkSetStatus(c, state.RestoreChecked) 281 } 282 283 func (s *RestoreInfoSuite) TestCheckedSetFailed(c *gc.C) { 284 s.setupChecked(c) 285 s.checkBadSetStatus(c, state.RestoreFailed) 286 } 287 288 //-------------------------------------- 289 // Test Failed -> ? transitions 290 func (s *RestoreInfoSuite) setupFailed(c *gc.C) { 291 s.checkSetStatus(c, state.RestorePending) 292 s.checkSetStatus(c, state.RestoreFailed) 293 } 294 295 func (s *RestoreInfoSuite) TestFailedSetNotActive(c *gc.C) { 296 s.setupFailed(c) 297 s.checkBadSetStatus(c, state.RestoreNotActive) 298 } 299 300 func (s *RestoreInfoSuite) TestFailedSetPending(c *gc.C) { 301 s.setupFailed(c) 302 s.checkSetStatus(c, state.RestorePending) 303 } 304 305 func (s *RestoreInfoSuite) TestFailedSetInProgress(c *gc.C) { 306 s.setupFailed(c) 307 s.checkBadSetStatus(c, state.RestoreInProgress) 308 } 309 310 func (s *RestoreInfoSuite) TestFailedSetFinished(c *gc.C) { 311 s.setupFailed(c) 312 s.checkBadSetStatus(c, state.RestoreFinished) 313 } 314 315 func (s *RestoreInfoSuite) TestFailedSetChecked(c *gc.C) { 316 s.setupFailed(c) 317 s.checkBadSetStatus(c, state.RestoreChecked) 318 } 319 320 func (s *RestoreInfoSuite) TestFailedSetFailed(c *gc.C) { 321 s.setupFailed(c) 322 s.checkSetStatus(c, state.RestoreFailed) 323 } 324 325 //-------------------- 326 327 func (s *RestoreInfoSuite) checkStatus(c *gc.C, expect state.RestoreStatus) { 328 actual, err := s.info.Status() 329 c.Check(err, jc.ErrorIsNil) 330 c.Check(actual, gc.Equals, expect) 331 } 332 333 func (s *RestoreInfoSuite) checkSetStatus(c *gc.C, status state.RestoreStatus) { 334 err := s.info.SetStatus(status) 335 c.Check(err, jc.ErrorIsNil) 336 s.checkStatus(c, status) 337 } 338 339 func (s *RestoreInfoSuite) checkBadSetStatus(c *gc.C, status state.RestoreStatus) { 340 err := s.info.SetStatus(status) 341 expect := fmt.Sprintf("invalid restore transition: [-A-Z]+ => %s", status) 342 c.Check(err, gc.ErrorMatches, expect) 343 }