github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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(time.Now())
   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(time.Now())
   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(time.Now())
   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(time.Now().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  }