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 }