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