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