github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/meterstatus/connected_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package meterstatus_test
     5  
     6  import (
     7  	"fmt"
     8  	"path"
     9  	"time"
    10  
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	coretesting "github.com/juju/juju/testing"
    16  	"github.com/juju/juju/worker/common/charmrunner"
    17  	"github.com/juju/juju/worker/meterstatus"
    18  )
    19  
    20  type ConnectedWorkerSuite struct {
    21  	coretesting.BaseSuite
    22  
    23  	stub *testing.Stub
    24  
    25  	dataDir  string
    26  	msClient *stubMeterStatusClient
    27  }
    28  
    29  var _ = gc.Suite(&ConnectedWorkerSuite{})
    30  
    31  func (s *ConnectedWorkerSuite) SetUpTest(c *gc.C) {
    32  	s.BaseSuite.SetUpTest(c)
    33  	s.stub = &testing.Stub{}
    34  
    35  	s.dataDir = c.MkDir()
    36  
    37  	s.msClient = newStubMeterStatusClient(s.stub)
    38  }
    39  
    40  func assertSignal(c *gc.C, signal <-chan struct{}) {
    41  	select {
    42  	case <-signal:
    43  	case <-time.After(coretesting.LongWait):
    44  		c.Fatal("timed out waiting for signal")
    45  	}
    46  }
    47  
    48  func (s *ConnectedWorkerSuite) TestConfigValidation(c *gc.C) {
    49  	tests := []struct {
    50  		cfg      meterstatus.ConnectedConfig
    51  		expected string
    52  	}{{
    53  		cfg: meterstatus.ConnectedConfig{
    54  			Status:    s.msClient,
    55  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
    56  		},
    57  		expected: "hook runner not provided",
    58  	}, {
    59  		cfg: meterstatus.ConnectedConfig{
    60  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
    61  			Runner:    &stubRunner{stub: s.stub},
    62  		},
    63  		expected: "meter status API client not provided",
    64  	}, {
    65  		cfg: meterstatus.ConnectedConfig{
    66  			Status: s.msClient,
    67  			Runner: &stubRunner{stub: s.stub},
    68  		},
    69  		expected: "state file not provided",
    70  	}}
    71  	for i, test := range tests {
    72  		c.Logf("running test %d", i)
    73  		err := test.cfg.Validate()
    74  		c.Assert(err, gc.ErrorMatches, test.expected)
    75  	}
    76  }
    77  
    78  // TestStatusHandlerDoesNotRerunNoChange ensures that the handler does not execute the hook if it
    79  // detects no actual meter status change.
    80  func (s *ConnectedWorkerSuite) TestStatusHandlerDoesNotRerunNoChange(c *gc.C) {
    81  	handler, err := meterstatus.NewConnectedStatusHandler(
    82  		meterstatus.ConnectedConfig{
    83  			Runner:    &stubRunner{stub: s.stub},
    84  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
    85  			Status:    s.msClient,
    86  		})
    87  	c.Assert(err, jc.ErrorIsNil)
    88  	c.Assert(handler, gc.NotNil)
    89  	_, err = handler.SetUp()
    90  	c.Assert(err, jc.ErrorIsNil)
    91  
    92  	err = handler.Handle(nil)
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	err = handler.Handle(nil)
    95  	c.Assert(err, jc.ErrorIsNil)
    96  
    97  	s.stub.CheckCallNames(c, "WatchMeterStatus", "MeterStatus", "RunHook", "MeterStatus")
    98  }
    99  
   100  // TestStatusHandlerRunsHookOnChanges ensures that the handler runs the meter-status-changed hook
   101  // if an actual meter status change is detected.
   102  func (s *ConnectedWorkerSuite) TestStatusHandlerRunsHookOnChanges(c *gc.C) {
   103  	handler, err := meterstatus.NewConnectedStatusHandler(
   104  		meterstatus.ConnectedConfig{
   105  			Runner:    &stubRunner{stub: s.stub},
   106  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
   107  			Status:    s.msClient,
   108  		})
   109  	c.Assert(err, jc.ErrorIsNil)
   110  	c.Assert(handler, gc.NotNil)
   111  	_, err = handler.SetUp()
   112  	c.Assert(err, jc.ErrorIsNil)
   113  
   114  	handler.Handle(nil)
   115  	s.msClient.SetStatus("RED")
   116  	handler.Handle(nil)
   117  
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	s.stub.CheckCallNames(c, "WatchMeterStatus", "MeterStatus", "RunHook", "MeterStatus", "RunHook")
   120  }
   121  
   122  // TestStatusHandlerHandlesHookMissingError tests that the handler does not report errors
   123  // caused by a missing meter-status-changed hook.
   124  func (s *ConnectedWorkerSuite) TestStatusHandlerHandlesHookMissingError(c *gc.C) {
   125  	s.stub.SetErrors(charmrunner.NewMissingHookError("meter-status-changed"))
   126  	handler, err := meterstatus.NewConnectedStatusHandler(
   127  		meterstatus.ConnectedConfig{
   128  			Runner:    &stubRunner{stub: s.stub},
   129  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
   130  			Status:    s.msClient,
   131  		})
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	c.Assert(handler, gc.NotNil)
   134  	_, err = handler.SetUp()
   135  	c.Assert(err, jc.ErrorIsNil)
   136  
   137  	err = handler.Handle(nil)
   138  	c.Assert(err, jc.ErrorIsNil)
   139  	s.stub.CheckCallNames(c, "WatchMeterStatus", "MeterStatus", "RunHook")
   140  }
   141  
   142  // TestStatusHandlerHandlesRandomHookError tests that the meter status handler does not return
   143  // errors encountered while executing the hook.
   144  func (s *ConnectedWorkerSuite) TestStatusHandlerHandlesRandomHookError(c *gc.C) {
   145  	s.stub.SetErrors(fmt.Errorf("blah"))
   146  	handler, err := meterstatus.NewConnectedStatusHandler(
   147  		meterstatus.ConnectedConfig{
   148  			Runner:    &stubRunner{stub: s.stub},
   149  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
   150  			Status:    s.msClient,
   151  		})
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	c.Assert(handler, gc.NotNil)
   154  	_, err = handler.SetUp()
   155  	c.Assert(err, jc.ErrorIsNil)
   156  
   157  	err = handler.Handle(nil)
   158  	c.Assert(err, jc.ErrorIsNil)
   159  
   160  	s.stub.CheckCallNames(c, "WatchMeterStatus", "MeterStatus", "RunHook")
   161  }
   162  
   163  // TestStatusHandlerDoesNotRerunAfterRestart tests that the status handler will not rerun a meter-status-changed
   164  // hook if it is restarted, but no actual changes are recorded.
   165  func (s *ConnectedWorkerSuite) TestStatusHandlerDoesNotRerunAfterRestart(c *gc.C) {
   166  	handler, err := meterstatus.NewConnectedStatusHandler(
   167  		meterstatus.ConnectedConfig{
   168  			Runner:    &stubRunner{stub: s.stub},
   169  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
   170  			Status:    s.msClient,
   171  		})
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	c.Assert(handler, gc.NotNil)
   174  	_, err = handler.SetUp()
   175  	c.Assert(err, jc.ErrorIsNil)
   176  
   177  	err = handler.Handle(nil)
   178  	c.Assert(err, jc.ErrorIsNil)
   179  
   180  	s.stub.CheckCallNames(c, "WatchMeterStatus", "MeterStatus", "RunHook")
   181  	s.stub.ResetCalls()
   182  
   183  	// Create a new handler (imitating worker restart).
   184  	handler, err = meterstatus.NewConnectedStatusHandler(
   185  		meterstatus.ConnectedConfig{
   186  			Runner:    &stubRunner{stub: s.stub},
   187  			StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")),
   188  			Status:    s.msClient})
   189  	c.Assert(err, jc.ErrorIsNil)
   190  	c.Assert(handler, gc.NotNil)
   191  	_, err = handler.SetUp()
   192  	c.Assert(err, jc.ErrorIsNil)
   193  
   194  	err = handler.Handle(nil)
   195  	c.Assert(err, jc.ErrorIsNil)
   196  
   197  	s.stub.CheckCallNames(c, "WatchMeterStatus", "MeterStatus")
   198  }