github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/meterstatus_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "time" 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/mgo.v2/bson" 12 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/testing" 15 "github.com/juju/juju/testing/factory" 16 ) 17 18 type MeterStateSuite struct { 19 ConnSuite 20 unit *state.Unit 21 factory *factory.Factory 22 metricsManager *state.MetricsManager 23 } 24 25 var _ = gc.Suite(&MeterStateSuite{}) 26 27 func (s *MeterStateSuite) SetUpTest(c *gc.C) { 28 s.ConnSuite.SetUpTest(c) 29 s.factory = factory.NewFactory(s.State) 30 s.unit = s.factory.MakeUnit(c, nil) 31 c.Assert(s.unit.Series(), gc.Equals, "quantal") 32 var err error 33 s.metricsManager, err = s.State.MetricsManager() 34 c.Assert(err, jc.ErrorIsNil) 35 } 36 37 func (s *MeterStateSuite) TestMeterStatus(c *gc.C) { 38 status, err := s.unit.GetMeterStatus() 39 c.Assert(err, jc.ErrorIsNil) 40 c.Assert(status.Code, gc.Equals, state.MeterNotSet) 41 err = s.unit.SetMeterStatus("GREEN", "Additional information.") 42 c.Assert(err, jc.ErrorIsNil) 43 status, err = s.unit.GetMeterStatus() 44 c.Assert(err, jc.ErrorIsNil) 45 c.Assert(status.Code, gc.Equals, state.MeterGreen) 46 } 47 48 func (s *MeterStateSuite) TestMeterStatusIncludesModelUUID(c *gc.C) { 49 jujuDB := s.MgoSuite.Session.DB("juju") 50 meterStatus := jujuDB.C("meterStatus") 51 var docs []bson.M 52 err := meterStatus.Find(nil).All(&docs) 53 c.Assert(err, jc.ErrorIsNil) 54 c.Assert(docs, gc.HasLen, 1) 55 c.Assert(docs[0]["model-uuid"], gc.Equals, s.State.ModelUUID()) 56 } 57 58 func (s *MeterStateSuite) TestSetMeterStatusIncorrect(c *gc.C) { 59 err := s.unit.SetMeterStatus("NOT SET", "Additional information.") 60 c.Assert(err, gc.ErrorMatches, `invalid meter status "NOT SET"`) 61 status, err := s.unit.GetMeterStatus() 62 c.Assert(err, jc.ErrorIsNil) 63 c.Assert(status.Code, gc.Equals, state.MeterNotSet) 64 65 err = s.unit.SetMeterStatus("this-is-not-a-valid-status", "Additional information.") 66 c.Assert(err, gc.ErrorMatches, `invalid meter status "NOT AVAILABLE"`) 67 status, err = s.unit.GetMeterStatus() 68 c.Assert(err, jc.ErrorIsNil) 69 c.Assert(status.Code, gc.Equals, state.MeterNotSet) 70 } 71 72 func (s *MeterStateSuite) TestSetMeterStatusWhenDying(c *gc.C) { 73 preventUnitDestroyRemove(c, s.unit) 74 testWhenDying(c, s.unit, contentionErr, contentionErr, func() error { 75 err := s.unit.SetMeterStatus("GREEN", "Additional information.") 76 if err != nil { 77 return err 78 } 79 status, err := s.unit.GetMeterStatus() 80 c.Assert(err, jc.ErrorIsNil) 81 c.Assert(status.Code, gc.Equals, state.MeterNotSet) 82 return nil 83 }) 84 } 85 86 func (s *MeterStateSuite) TestMeterStatusRemovedWithUnit(c *gc.C) { 87 err := s.unit.SetMeterStatus("GREEN", "Information.") 88 c.Assert(err, jc.ErrorIsNil) 89 err = s.unit.EnsureDead() 90 c.Assert(err, jc.ErrorIsNil) 91 err = s.unit.Remove() 92 c.Assert(err, jc.ErrorIsNil) 93 status, err := s.unit.GetMeterStatus() 94 c.Assert(err, gc.ErrorMatches, "cannot retrieve meter status for unit .*: not found") 95 c.Assert(status.Code, gc.Equals, state.MeterNotAvailable) 96 } 97 98 func (s *MeterStateSuite) TestMeterStatusWatcherRespondstoMeterStatus(c *gc.C) { 99 watcher := s.unit.WatchMeterStatus() 100 assertMeterStatusChanged(c, watcher) 101 err := s.unit.SetMeterStatus("GREEN", "Information.") 102 c.Assert(err, jc.ErrorIsNil) 103 assertMeterStatusChanged(c, watcher) 104 } 105 106 func (s *MeterStateSuite) TestMeterStatusWatcherRespondsToMetricsManager(c *gc.C) { 107 mm, err := s.State.MetricsManager() 108 c.Assert(err, jc.ErrorIsNil) 109 watcher := s.unit.WatchMeterStatus() 110 assertMeterStatusChanged(c, watcher) 111 err = mm.SetLastSuccessfulSend(testing.NonZeroTime()) 112 c.Assert(err, jc.ErrorIsNil) 113 for i := 0; i < 3; i++ { 114 err := mm.IncrementConsecutiveErrors() 115 c.Assert(err, jc.ErrorIsNil) 116 } 117 status := mm.MeterStatus() 118 c.Assert(status.Code, gc.Equals, state.MeterAmber) 119 assertMeterStatusChanged(c, watcher) 120 } 121 122 func (s *MeterStateSuite) TestMeterStatusWatcherRespondsToMetricsManagerAndStatus(c *gc.C) { 123 mm, err := s.State.MetricsManager() 124 c.Assert(err, jc.ErrorIsNil) 125 watcher := s.unit.WatchMeterStatus() 126 assertMeterStatusChanged(c, watcher) 127 err = mm.SetLastSuccessfulSend(testing.NonZeroTime()) 128 c.Assert(err, jc.ErrorIsNil) 129 for i := 0; i < 3; i++ { 130 err := mm.IncrementConsecutiveErrors() 131 c.Assert(err, jc.ErrorIsNil) 132 } 133 status := mm.MeterStatus() 134 c.Assert(status.Code, gc.Equals, state.MeterAmber) 135 err = s.unit.SetMeterStatus("GREEN", "Information.") 136 c.Assert(err, jc.ErrorIsNil) 137 assertMeterStatusChanged(c, watcher) 138 assertMeterStatusNotChanged(c, watcher) 139 } 140 141 func assertMeterStatusChanged(c *gc.C, w state.NotifyWatcher) { 142 select { 143 case <-w.Changes(): 144 case <-time.After(testing.LongWait): 145 c.Fatalf("expected event from watcher by now") 146 } 147 } 148 149 func assertMeterStatusNotChanged(c *gc.C, w state.NotifyWatcher) { 150 select { 151 case <-w.Changes(): 152 c.Fatalf("unexpected event from watcher") 153 case <-time.After(testing.ShortWait): 154 } 155 } 156 157 func assertMetricsManagerAmberState(c *gc.C, metricsManager *state.MetricsManager) { 158 err := metricsManager.SetLastSuccessfulSend(testing.NonZeroTime()) 159 c.Assert(err, jc.ErrorIsNil) 160 for i := 0; i < 3; i++ { 161 err := metricsManager.IncrementConsecutiveErrors() 162 c.Assert(err, jc.ErrorIsNil) 163 } 164 status := metricsManager.MeterStatus() 165 c.Assert(status.Code, gc.Equals, state.MeterAmber) 166 } 167 168 // TODO (mattyw) This function could be moved into a metricsmanager testing package. 169 func assertMetricsManagerRedState(c *gc.C, metricsManager *state.MetricsManager) { 170 // To enter the red state we need to set a last successful send as over 1 week ago 171 err := metricsManager.SetLastSuccessfulSend(testing.NonZeroTime().Add(-8 * 24 * time.Hour)) 172 c.Assert(err, jc.ErrorIsNil) 173 for i := 0; i < 3; i++ { 174 err := metricsManager.IncrementConsecutiveErrors() 175 c.Assert(err, jc.ErrorIsNil) 176 } 177 status := metricsManager.MeterStatus() 178 c.Assert(status.Code, gc.Equals, state.MeterRed) 179 } 180 181 // TestMeterStatusMetricsManagerCombinations test every possible combination 182 // of meter status from the unit and the metrics manager. 183 func (s *MeterStateSuite) TestMeterStatusMetricsManagerCombinations(c *gc.C) { 184 greenMetricsMangager := func() {} 185 amberMetricsManager := func() { 186 assertMetricsManagerAmberState(c, s.metricsManager) 187 } 188 redMetricsManager := func() { 189 assertMetricsManagerRedState(c, s.metricsManager) 190 } 191 greenUnit := func() { 192 err := s.unit.SetMeterStatus("GREEN", "Unit") 193 c.Assert(err, jc.ErrorIsNil) 194 } 195 amberUnit := func() { 196 err := s.unit.SetMeterStatus("AMBER", "Unit") 197 c.Assert(err, jc.ErrorIsNil) 198 } 199 redUnit := func() { 200 err := s.unit.SetMeterStatus("RED", "Unit") 201 c.Assert(err, jc.ErrorIsNil) 202 } 203 204 tests := []struct { 205 about string 206 metricsManager func() 207 unit func() 208 expectedCode state.MeterStatusCode 209 expectedInfo string 210 }{{ 211 "green metrics manager and green unit returns green overall", 212 greenMetricsMangager, 213 greenUnit, 214 state.MeterGreen, 215 "Unit", 216 }, { 217 "amber metrics manager and amber unit returns amber overall", 218 amberMetricsManager, 219 amberUnit, 220 state.MeterAmber, 221 "Unit", 222 }, { 223 "red metrics manager and red unit returns red overall", 224 redMetricsManager, 225 redUnit, 226 state.MeterRed, 227 "failed to send metrics, exceeded grace period", 228 }, { 229 230 "red metrics manager and amber unit returns red overall", 231 redMetricsManager, 232 amberUnit, 233 state.MeterRed, 234 "failed to send metrics, exceeded grace period", 235 }, { 236 "red metrics manager and green unit returns red overall", 237 redMetricsManager, 238 greenUnit, 239 state.MeterRed, 240 "failed to send metrics, exceeded grace period", 241 }, { 242 "amber metrics manager and red unit returns red overall", 243 amberMetricsManager, 244 redUnit, 245 state.MeterRed, 246 "Unit", 247 }, { 248 "amber metrics manager and green unit returns amber overall", 249 amberMetricsManager, 250 greenUnit, 251 state.MeterAmber, 252 "failed to send metrics", 253 }, { 254 "green metrics manager and red unit returns red overall", 255 greenMetricsMangager, 256 redUnit, 257 state.MeterRed, 258 "Unit", 259 }, { 260 "green metrics manager and amber unit returns amber overall", 261 greenMetricsMangager, 262 amberUnit, 263 state.MeterAmber, 264 "Unit", 265 }} 266 267 for i, test := range tests { 268 c.Logf("running test %d %s", i, test.about) 269 test.metricsManager() 270 test.unit() 271 status, err := s.unit.GetMeterStatus() 272 c.Assert(err, jc.ErrorIsNil) 273 c.Check(status.Code, gc.Equals, test.expectedCode) 274 } 275 } 276 277 func (s *MeterStateSuite) TestMeterStatusCombination(c *gc.C) { 278 var ( 279 Red = state.MeterStatus{state.MeterRed, ""} 280 Amber = state.MeterStatus{state.MeterAmber, ""} 281 Green = state.MeterStatus{state.MeterGreen, ""} 282 NotSet = state.MeterStatus{state.MeterNotSet, ""} 283 NotAvailable = state.MeterStatus{state.MeterNotAvailable, ""} 284 ) 285 c.Assert(state.CombineMeterStatus(Red, Red).Code, gc.Equals, Red.Code) 286 c.Assert(state.CombineMeterStatus(Red, Amber).Code, gc.Equals, Red.Code) 287 c.Assert(state.CombineMeterStatus(Red, Green).Code, gc.Equals, Red.Code) 288 c.Assert(state.CombineMeterStatus(Red, NotSet).Code, gc.Equals, Red.Code) 289 c.Assert(state.CombineMeterStatus(Red, NotAvailable).Code, gc.Equals, NotAvailable.Code) 290 291 c.Assert(state.CombineMeterStatus(Amber, Red).Code, gc.Equals, Red.Code) 292 c.Assert(state.CombineMeterStatus(Amber, Amber).Code, gc.Equals, Amber.Code) 293 c.Assert(state.CombineMeterStatus(Amber, Green).Code, gc.Equals, Amber.Code) 294 c.Assert(state.CombineMeterStatus(Amber, NotSet).Code, gc.Equals, Amber.Code) 295 c.Assert(state.CombineMeterStatus(Amber, NotAvailable).Code, gc.Equals, NotAvailable.Code) 296 297 c.Assert(state.CombineMeterStatus(Green, Red).Code, gc.Equals, Red.Code) 298 c.Assert(state.CombineMeterStatus(Green, Amber).Code, gc.Equals, Amber.Code) 299 c.Assert(state.CombineMeterStatus(Green, Green).Code, gc.Equals, Green.Code) 300 c.Assert(state.CombineMeterStatus(Green, NotSet).Code, gc.Equals, NotSet.Code) 301 c.Assert(state.CombineMeterStatus(Green, NotAvailable).Code, gc.Equals, NotAvailable.Code) 302 303 c.Assert(state.CombineMeterStatus(NotSet, Red).Code, gc.Equals, Red.Code) 304 c.Assert(state.CombineMeterStatus(NotSet, Amber).Code, gc.Equals, Amber.Code) 305 c.Assert(state.CombineMeterStatus(NotSet, Green).Code, gc.Equals, NotSet.Code) 306 c.Assert(state.CombineMeterStatus(NotSet, NotSet).Code, gc.Equals, NotSet.Code) 307 c.Assert(state.CombineMeterStatus(NotSet, NotAvailable).Code, gc.Equals, NotAvailable.Code) 308 309 c.Assert(state.CombineMeterStatus(NotAvailable, Red).Code, gc.Equals, NotAvailable.Code) 310 c.Assert(state.CombineMeterStatus(NotAvailable, Amber).Code, gc.Equals, NotAvailable.Code) 311 c.Assert(state.CombineMeterStatus(NotAvailable, Green).Code, gc.Equals, NotAvailable.Code) 312 c.Assert(state.CombineMeterStatus(NotAvailable, NotSet).Code, gc.Equals, NotAvailable.Code) 313 c.Assert(state.CombineMeterStatus(NotAvailable, NotAvailable).Code, gc.Equals, NotAvailable.Code) 314 }