github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/peergrouper/manifold_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package peergrouper_test 5 6 import ( 7 "time" 8 9 "github.com/juju/clock/testclock" 10 "github.com/juju/errors" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/juju/worker.v1" 15 "gopkg.in/juju/worker.v1/dependency" 16 dt "gopkg.in/juju/worker.v1/dependency/testing" 17 "gopkg.in/juju/worker.v1/workertest" 18 19 "github.com/juju/juju/agent" 20 "github.com/juju/juju/apiserver/params" 21 "github.com/juju/juju/state" 22 statetesting "github.com/juju/juju/state/testing" 23 "github.com/juju/juju/worker/peergrouper" 24 ) 25 26 type ManifoldSuite struct { 27 statetesting.StateSuite 28 29 manifold dependency.Manifold 30 context dependency.Context 31 clock *testclock.Clock 32 agent *mockAgent 33 hub *mockHub 34 stateTracker stubStateTracker 35 36 stub testing.Stub 37 } 38 39 var _ = gc.Suite(&ManifoldSuite{}) 40 41 func (s *ManifoldSuite) SetUpTest(c *gc.C) { 42 s.StateSuite.SetUpTest(c) 43 44 s.clock = testclock.NewClock(time.Time{}) 45 s.agent = &mockAgent{conf: mockAgentConfig{ 46 info: ¶ms.StateServingInfo{ 47 StatePort: 1234, 48 APIPort: 5678, 49 }, 50 }} 51 s.hub = &mockHub{} 52 s.stateTracker = stubStateTracker{pool: s.StatePool} 53 s.stub.ResetCalls() 54 55 s.context = s.newContext(nil) 56 s.manifold = peergrouper.Manifold(peergrouper.ManifoldConfig{ 57 AgentName: "agent", 58 ClockName: "clock", 59 ControllerPortName: "controller-port", 60 StateName: "state", 61 Hub: s.hub, 62 NewWorker: s.newWorker, 63 ControllerSupportsSpaces: func(st *state.State) (bool, error) { 64 if st != s.State { 65 return false, errors.New("invalid state") 66 } 67 return true, nil 68 }, 69 }) 70 } 71 72 func (s *ManifoldSuite) newContext(overlay map[string]interface{}) dependency.Context { 73 resources := map[string]interface{}{ 74 "agent": s.agent, 75 "clock": s.clock, 76 "controller-port": nil, 77 "state": &s.stateTracker, 78 } 79 for k, v := range overlay { 80 resources[k] = v 81 } 82 return dt.StubContext(nil, resources) 83 } 84 85 func (s *ManifoldSuite) newWorker(config peergrouper.Config) (worker.Worker, error) { 86 s.stub.MethodCall(s, "NewWorker", config) 87 if err := s.stub.NextErr(); err != nil { 88 return nil, err 89 } 90 w := worker.NewRunner(worker.RunnerParams{}) 91 s.AddCleanup(func(c *gc.C) { workertest.CleanKill(c, w) }) 92 return w, nil 93 } 94 95 var expectedInputs = []string{"agent", "clock", "controller-port", "state"} 96 97 func (s *ManifoldSuite) TestInputs(c *gc.C) { 98 c.Assert(s.manifold.Inputs, jc.SameContents, expectedInputs) 99 } 100 101 func (s *ManifoldSuite) TestMissingInputs(c *gc.C) { 102 for _, input := range expectedInputs { 103 context := s.newContext(map[string]interface{}{ 104 input: dependency.ErrMissing, 105 }) 106 _, err := s.manifold.Start(context) 107 c.Assert(errors.Cause(err), gc.Equals, dependency.ErrMissing) 108 } 109 } 110 111 func (s *ManifoldSuite) TestStart(c *gc.C) { 112 w := s.startWorkerClean(c) 113 workertest.CleanKill(c, w) 114 115 s.stub.CheckCallNames(c, "NewWorker") 116 args := s.stub.Calls()[0].Args 117 c.Assert(args, gc.HasLen, 1) 118 c.Assert(args[0], gc.FitsTypeOf, peergrouper.Config{}) 119 config := args[0].(peergrouper.Config) 120 121 c.Assert(config, jc.DeepEquals, peergrouper.Config{ 122 State: peergrouper.StateShim{s.State}, 123 MongoSession: peergrouper.MongoSessionShim{s.State.MongoSession()}, 124 APIHostPortsSetter: &peergrouper.CachingAPIHostPortsSetter{ 125 APIHostPortsSetter: s.State, 126 }, 127 Clock: s.clock, 128 Hub: s.hub, 129 SupportsSpaces: true, 130 MongoPort: 1234, 131 APIPort: 5678, 132 }) 133 } 134 135 func (s *ManifoldSuite) TestStopWorkerClosesState(c *gc.C) { 136 w := s.startWorkerClean(c) 137 defer workertest.CleanKill(c, w) 138 139 s.stateTracker.CheckCallNames(c, "Use") 140 141 workertest.CleanKill(c, w) 142 s.stateTracker.CheckCallNames(c, "Use", "Done") 143 } 144 145 func (s *ManifoldSuite) startWorkerClean(c *gc.C) worker.Worker { 146 w, err := s.manifold.Start(s.context) 147 c.Assert(err, jc.ErrorIsNil) 148 workertest.CheckAlive(c, w) 149 return w 150 } 151 152 type stubStateTracker struct { 153 testing.Stub 154 pool *state.StatePool 155 } 156 157 func (s *stubStateTracker) Use() (*state.StatePool, error) { 158 s.MethodCall(s, "Use") 159 return s.pool, s.NextErr() 160 } 161 162 func (s *stubStateTracker) Done() error { 163 s.MethodCall(s, "Done") 164 return s.NextErr() 165 } 166 167 func (s *stubStateTracker) Report() map[string]interface{} { 168 s.MethodCall(s, "Report") 169 return nil 170 } 171 172 type mockAgent struct { 173 agent.Agent 174 conf mockAgentConfig 175 } 176 177 func (ma *mockAgent) CurrentConfig() agent.Config { 178 return &ma.conf 179 } 180 181 type mockAgentConfig struct { 182 agent.Config 183 info *params.StateServingInfo 184 } 185 186 func (c *mockAgentConfig) StateServingInfo() (params.StateServingInfo, bool) { 187 if c.info != nil { 188 return *c.info, true 189 } 190 return params.StateServingInfo{}, false 191 } 192 193 type mockHub struct { 194 peergrouper.Hub 195 }