github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/meterstatus/isolated_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/clock" 12 "github.com/juju/clock/testclock" 13 "github.com/juju/testing" 14 jc "github.com/juju/testing/checkers" 15 gc "gopkg.in/check.v1" 16 "gopkg.in/juju/worker.v1" 17 18 coretesting "github.com/juju/juju/testing" 19 "github.com/juju/juju/worker/common/charmrunner" 20 "github.com/juju/juju/worker/meterstatus" 21 ) 22 23 const ( 24 AmberGracePeriod = time.Minute 25 RedGracePeriod = time.Minute * 5 26 ) 27 28 type IsolatedWorkerConfigSuite struct { 29 coretesting.BaseSuite 30 31 stub *testing.Stub 32 33 dataDir string 34 } 35 36 var _ = gc.Suite(&IsolatedWorkerConfigSuite{}) 37 38 func (s *IsolatedWorkerConfigSuite) SetUpTest(c *gc.C) { 39 s.BaseSuite.SetUpTest(c) 40 s.stub = &testing.Stub{} 41 s.dataDir = c.MkDir() 42 } 43 44 func (s *IsolatedWorkerConfigSuite) TestConfigValidation(c *gc.C) { 45 tests := []struct { 46 cfg meterstatus.IsolatedConfig 47 expected string 48 }{{ 49 cfg: meterstatus.IsolatedConfig{ 50 Runner: &stubRunner{stub: s.stub}, 51 StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")), 52 }, 53 expected: "clock not provided", 54 }, { 55 cfg: meterstatus.IsolatedConfig{ 56 Clock: testclock.NewClock(time.Now()), 57 StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")), 58 }, 59 expected: "hook runner not provided", 60 }, { 61 cfg: meterstatus.IsolatedConfig{ 62 Clock: testclock.NewClock(time.Now()), 63 Runner: &stubRunner{stub: s.stub}, 64 }, 65 expected: "state file not provided", 66 }} 67 for i, test := range tests { 68 c.Logf("running test %d", i) 69 err := test.cfg.Validate() 70 c.Assert(err, gc.ErrorMatches, test.expected) 71 } 72 } 73 74 type IsolatedWorkerSuite struct { 75 coretesting.BaseSuite 76 77 stub *testing.Stub 78 79 dataDir string 80 clk *testclock.Clock 81 82 hookRan chan struct{} 83 triggersCreated chan struct{} 84 85 worker worker.Worker 86 } 87 88 var _ = gc.Suite(&IsolatedWorkerSuite{}) 89 90 func (s *IsolatedWorkerSuite) SetUpTest(c *gc.C) { 91 s.BaseSuite.SetUpTest(c) 92 s.stub = &testing.Stub{} 93 94 s.dataDir = c.MkDir() 95 96 s.hookRan = make(chan struct{}) 97 s.triggersCreated = make(chan struct{}) 98 99 triggerFactory := func(state meterstatus.WorkerState, status string, disconectedAt time.Time, clk clock.Clock, amber time.Duration, red time.Duration) (<-chan time.Time, <-chan time.Time) { 100 select { 101 case s.triggersCreated <- struct{}{}: 102 case <-time.After(coretesting.LongWait): 103 c.Fatalf("failed to signal trigger creation") 104 } 105 return meterstatus.GetTriggers(state, status, disconectedAt, clk, amber, red) 106 } 107 108 s.clk = testclock.NewClock(time.Now()) 109 wrk, err := meterstatus.NewIsolatedStatusWorker( 110 meterstatus.IsolatedConfig{ 111 Runner: &stubRunner{stub: s.stub, ran: s.hookRan}, 112 StateFile: meterstatus.NewStateFile(path.Join(s.dataDir, "meter-status.yaml")), 113 Clock: s.clk, 114 AmberGracePeriod: AmberGracePeriod, 115 RedGracePeriod: RedGracePeriod, 116 TriggerFactory: triggerFactory, 117 }) 118 c.Assert(err, jc.ErrorIsNil) 119 c.Assert(wrk, gc.NotNil) 120 s.worker = wrk 121 } 122 123 func (s *IsolatedWorkerSuite) TearDownTest(c *gc.C) { 124 s.worker.Kill() 125 err := s.worker.Wait() 126 c.Assert(err, jc.ErrorIsNil) 127 } 128 129 func (s *IsolatedWorkerSuite) TestTriggering(c *gc.C) { 130 assertSignal(c, s.triggersCreated) 131 s.clk.Advance(AmberGracePeriod + time.Second) 132 assertSignal(c, s.hookRan) 133 s.clk.Advance(RedGracePeriod + time.Second) 134 assertSignal(c, s.hookRan) 135 136 s.stub.CheckCallNames(c, "RunHook", "RunHook") 137 } 138 139 // TestMissingHookError tests that errors caused by missing hooks do not stop the worker. 140 func (s *IsolatedWorkerSuite) TestMissingHookError(c *gc.C) { 141 s.stub.SetErrors(charmrunner.NewMissingHookError("meter-status-changed")) 142 143 assertSignal(c, s.triggersCreated) 144 s.clk.Advance(AmberGracePeriod + time.Second) 145 assertSignal(c, s.hookRan) 146 147 s.stub.CheckCallNames(c, "RunHook") 148 } 149 150 // TestRandomHookError tests that errors returned by hooks do not stop the worker. 151 func (s *IsolatedWorkerSuite) TestRandomHookError(c *gc.C) { 152 s.stub.SetErrors(fmt.Errorf("blah")) 153 154 assertSignal(c, s.triggersCreated) 155 s.clk.Advance(AmberGracePeriod + time.Second) 156 assertSignal(c, s.hookRan) 157 158 s.stub.CheckCallNames(c, "RunHook") 159 }