github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/controllerport/manifold_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package controllerport_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "github.com/juju/pubsub" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/juju/worker.v1" 14 "gopkg.in/juju/worker.v1/dependency" 15 dt "gopkg.in/juju/worker.v1/dependency/testing" 16 "gopkg.in/juju/worker.v1/workertest" 17 18 "github.com/juju/juju/agent" 19 "github.com/juju/juju/apiserver/params" 20 "github.com/juju/juju/controller" 21 "github.com/juju/juju/state" 22 "github.com/juju/juju/worker/controllerport" 23 ) 24 25 type ManifoldSuite struct { 26 testing.IsolationSuite 27 28 config controllerport.ManifoldConfig 29 manifold dependency.Manifold 30 context dependency.Context 31 agent *mockAgent 32 hub *pubsub.StructuredHub 33 state stubStateTracker 34 logger loggo.Logger 35 controllerConfig controller.Config 36 worker worker.Worker 37 38 stub testing.Stub 39 } 40 41 var _ = gc.Suite(&ManifoldSuite{}) 42 43 func (s *ManifoldSuite) SetUpTest(c *gc.C) { 44 s.IsolationSuite.SetUpTest(c) 45 46 s.agent = &mockAgent{} 47 s.hub = pubsub.NewStructuredHub(nil) 48 s.state = stubStateTracker{} 49 s.logger = loggo.GetLogger("controllerport_manifold") 50 s.controllerConfig = controller.Config(map[string]interface{}{ 51 "controller-api-port": 2048, 52 }) 53 s.worker = &struct{ worker.Worker }{} 54 s.stub.ResetCalls() 55 56 s.context = s.newContext(nil) 57 s.config = controllerport.ManifoldConfig{ 58 AgentName: "agent", 59 HubName: "hub", 60 StateName: "state", 61 Logger: s.logger, 62 UpdateControllerAPIPort: s.updatePort, 63 GetControllerConfig: s.getControllerConfig, 64 NewWorker: s.newWorker, 65 } 66 s.manifold = controllerport.Manifold(s.config) 67 } 68 69 func (s *ManifoldSuite) newContext(overlay map[string]interface{}) dependency.Context { 70 resources := map[string]interface{}{ 71 "agent": s.agent, 72 "hub": s.hub, 73 "state": &s.state, 74 } 75 for k, v := range overlay { 76 resources[k] = v 77 } 78 return dt.StubContext(nil, resources) 79 } 80 81 func (s *ManifoldSuite) getControllerConfig(st *state.State) (controller.Config, error) { 82 s.stub.MethodCall(s, "GetControllerConfig", st) 83 if err := s.stub.NextErr(); err != nil { 84 return nil, err 85 } 86 return s.controllerConfig, nil 87 } 88 89 func (s *ManifoldSuite) updatePort(port int) error { 90 return errors.Errorf("braincake") 91 } 92 93 func (s *ManifoldSuite) newWorker(config controllerport.Config) (worker.Worker, error) { 94 s.stub.MethodCall(s, "NewWorker", config) 95 if err := s.stub.NextErr(); err != nil { 96 return nil, err 97 } 98 return s.worker, nil 99 } 100 101 var expectedInputs = []string{"state", "agent", "hub"} 102 103 func (s *ManifoldSuite) TestInputs(c *gc.C) { 104 c.Assert(s.manifold.Inputs, jc.SameContents, expectedInputs) 105 } 106 107 func (s *ManifoldSuite) TestMissingInputs(c *gc.C) { 108 for _, input := range expectedInputs { 109 context := s.newContext(map[string]interface{}{ 110 input: dependency.ErrMissing, 111 }) 112 _, err := s.manifold.Start(context) 113 c.Assert(errors.Cause(err), gc.Equals, dependency.ErrMissing) 114 } 115 } 116 117 func (s *ManifoldSuite) TestValidate(c *gc.C) { 118 type test struct { 119 f func(*controllerport.ManifoldConfig) 120 expect string 121 } 122 tests := []test{{ 123 func(cfg *controllerport.ManifoldConfig) { cfg.StateName = "" }, 124 "empty StateName not valid", 125 }, { 126 func(cfg *controllerport.ManifoldConfig) { cfg.HubName = "" }, 127 "empty HubName not valid", 128 }, { 129 func(cfg *controllerport.ManifoldConfig) { cfg.AgentName = "" }, 130 "empty AgentName not valid", 131 }, { 132 func(cfg *controllerport.ManifoldConfig) { cfg.Logger = nil }, 133 "nil Logger not valid", 134 }, { 135 func(cfg *controllerport.ManifoldConfig) { cfg.UpdateControllerAPIPort = nil }, 136 "nil UpdateControllerAPIPort not valid", 137 }, { 138 func(cfg *controllerport.ManifoldConfig) { cfg.GetControllerConfig = nil }, 139 "nil GetControllerConfig not valid", 140 }, { 141 func(cfg *controllerport.ManifoldConfig) { cfg.NewWorker = nil }, 142 "nil NewWorker not valid", 143 }} 144 for i, test := range tests { 145 c.Logf("test #%d (%s)", i, test.expect) 146 config := s.config 147 test.f(&config) 148 manifold := controllerport.Manifold(config) 149 w, err := manifold.Start(s.context) 150 workertest.CheckNilOrKill(c, w) 151 c.Check(err, gc.ErrorMatches, test.expect) 152 } 153 } 154 155 func (s *ManifoldSuite) TestStart(c *gc.C) { 156 s.startWorkerClean(c) 157 158 s.stub.CheckCallNames(c, "GetControllerConfig", "NewWorker") 159 args := s.stub.Calls()[1].Args 160 c.Assert(args, gc.HasLen, 1) 161 c.Assert(args[0], gc.FitsTypeOf, controllerport.Config{}) 162 config := args[0].(controllerport.Config) 163 164 // Can't directly compare functions, so blank it out. 165 c.Assert(config.UpdateControllerAPIPort(3), gc.ErrorMatches, "braincake") 166 config.UpdateControllerAPIPort = nil 167 168 c.Assert(config, jc.DeepEquals, controllerport.Config{ 169 AgentConfig: &s.agent.conf, 170 Hub: s.hub, 171 Logger: s.logger, 172 ControllerAPIPort: 2048, 173 }) 174 } 175 176 func (s *ManifoldSuite) startWorkerClean(c *gc.C) worker.Worker { 177 w, err := s.manifold.Start(s.context) 178 c.Assert(err, jc.ErrorIsNil) 179 c.Assert(w, gc.Equals, s.worker) 180 return w 181 } 182 183 type stubStateTracker struct { 184 testing.Stub 185 pool state.StatePool 186 } 187 188 func (s *stubStateTracker) Use() (*state.StatePool, error) { 189 s.MethodCall(s, "Use") 190 return &s.pool, s.NextErr() 191 } 192 193 func (s *stubStateTracker) Done() error { 194 s.MethodCall(s, "Done") 195 return s.NextErr() 196 } 197 198 func (s *stubStateTracker) Report() map[string]interface{} { 199 s.MethodCall(s, "Report") 200 return nil 201 } 202 203 type mockAgent struct { 204 agent.Agent 205 conf mockAgentConfig 206 } 207 208 func (ma *mockAgent) CurrentConfig() agent.Config { 209 return &ma.conf 210 } 211 212 type mockAgentConfig struct { 213 agent.Config 214 port int 215 } 216 217 func (c *mockAgentConfig) StateServingInfo() (params.StateServingInfo, bool) { 218 return params.StateServingInfo{ControllerAPIPort: c.port}, true 219 }