github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/resumer/manifold_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package resumer_test 5 6 import ( 7 "errors" 8 "time" 9 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils/clock" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/juju/names.v2" 15 16 "github.com/juju/juju/agent" 17 "github.com/juju/juju/api/base" 18 "github.com/juju/juju/apiserver/params" 19 "github.com/juju/juju/state/multiwatcher" 20 "github.com/juju/juju/worker" 21 "github.com/juju/juju/worker/dependency" 22 dt "github.com/juju/juju/worker/dependency/testing" 23 resumer "github.com/juju/juju/worker/resumer" 24 "github.com/juju/juju/worker/workertest" 25 ) 26 27 type ManifoldSuite struct { 28 testing.IsolationSuite 29 } 30 31 var _ = gc.Suite(&ManifoldSuite{}) 32 33 func (*ManifoldSuite) TestInputs(c *gc.C) { 34 manifold := resumer.Manifold(resumer.ManifoldConfig{ 35 AgentName: "bill", 36 APICallerName: "ben", 37 }) 38 expect := []string{"bill", "ben"} 39 c.Check(manifold.Inputs, jc.DeepEquals, expect) 40 } 41 42 func (*ManifoldSuite) TestOutput(c *gc.C) { 43 manifold := resumer.Manifold(resumer.ManifoldConfig{}) 44 c.Check(manifold.Output, gc.IsNil) 45 } 46 47 func (*ManifoldSuite) TestMissingAgent(c *gc.C) { 48 manifold := resumer.Manifold(resumer.ManifoldConfig{ 49 AgentName: "agent", 50 APICallerName: "api-caller", 51 }) 52 53 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 54 "agent": dependency.ErrMissing, 55 "api-caller": &fakeAPICaller{}, 56 })) 57 workertest.CheckNilOrKill(c, worker) 58 c.Check(err, gc.Equals, dependency.ErrMissing) 59 } 60 61 func (*ManifoldSuite) TestMissingAPICaller(c *gc.C) { 62 manifold := resumer.Manifold(resumer.ManifoldConfig{ 63 AgentName: "agent", 64 APICallerName: "api-caller", 65 }) 66 67 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 68 "agent": &fakeAgent{}, 69 "api-caller": dependency.ErrMissing, 70 })) 71 workertest.CheckNilOrKill(c, worker) 72 c.Check(err, gc.Equals, dependency.ErrMissing) 73 } 74 75 func (*ManifoldSuite) TestAgentEntity_Error(c *gc.C) { 76 manifold := resumer.Manifold(resumer.ManifoldConfig{ 77 AgentName: "agent", 78 APICallerName: "api-caller", 79 }) 80 81 stub := &testing.Stub{} 82 stub.SetErrors(errors.New("zap")) 83 apiCaller := &fakeAPICaller{stub: stub} 84 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 85 "agent": &fakeAgent{}, 86 "api-caller": apiCaller, 87 })) 88 workertest.CheckNilOrKill(c, worker) 89 c.Check(err, gc.ErrorMatches, "zap") 90 91 stub.CheckCalls(c, []testing.StubCall{{ 92 FuncName: "Agent.GetEntities", 93 Args: []interface{}{params.Entities{ 94 Entities: []params.Entity{{ 95 Tag: "machine-123", 96 }}, 97 }}, 98 }}) 99 } 100 101 func (s *ManifoldSuite) TestAgentEntity_NoJob(c *gc.C) { 102 manifold := resumer.Manifold(resumer.ManifoldConfig{ 103 AgentName: "agent", 104 APICallerName: "api-caller", 105 }) 106 107 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 108 "agent": &fakeAgent{}, 109 "api-caller": &fakeAPICaller{}, 110 })) 111 workertest.CheckNilOrKill(c, worker) 112 c.Check(err, gc.Equals, dependency.ErrMissing) 113 } 114 115 func (s *ManifoldSuite) TestAgentEntity_NotModelManager(c *gc.C) { 116 manifold := resumer.Manifold(resumer.ManifoldConfig{ 117 AgentName: "agent", 118 APICallerName: "api-caller", 119 }) 120 121 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 122 "agent": &fakeAgent{}, 123 "api-caller": newFakeAPICaller(multiwatcher.JobHostUnits), 124 })) 125 workertest.CheckNilOrKill(c, worker) 126 c.Check(err, gc.Equals, dependency.ErrMissing) 127 } 128 129 func (s *ManifoldSuite) TestNewFacade_Missing(c *gc.C) { 130 manifold := resumer.Manifold(resumer.ManifoldConfig{ 131 AgentName: "agent", 132 APICallerName: "api-caller", 133 }) 134 135 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 136 "agent": &fakeAgent{}, 137 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 138 })) 139 workertest.CheckNilOrKill(c, worker) 140 c.Check(err, gc.Equals, dependency.ErrUninstall) 141 } 142 143 func (s *ManifoldSuite) TestNewFacade_Error(c *gc.C) { 144 apiCaller := newFakeAPICaller(multiwatcher.JobManageModel) 145 manifold := resumer.Manifold(resumer.ManifoldConfig{ 146 AgentName: "agent", 147 APICallerName: "api-caller", 148 NewFacade: func(actual base.APICaller) (resumer.Facade, error) { 149 c.Check(actual, gc.Equals, apiCaller) 150 return nil, errors.New("pow") 151 }, 152 }) 153 154 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 155 "agent": &fakeAgent{}, 156 "api-caller": apiCaller, 157 })) 158 workertest.CheckNilOrKill(c, worker) 159 c.Check(err, gc.ErrorMatches, "pow") 160 } 161 162 func (s *ManifoldSuite) TestNewWorker_Missing(c *gc.C) { 163 manifold := resumer.Manifold(resumer.ManifoldConfig{ 164 AgentName: "agent", 165 APICallerName: "api-caller", 166 NewFacade: func(base.APICaller) (resumer.Facade, error) { 167 return &fakeFacade{}, nil 168 }, 169 }) 170 171 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 172 "agent": &fakeAgent{}, 173 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 174 })) 175 workertest.CheckNilOrKill(c, worker) 176 c.Check(err, gc.Equals, dependency.ErrUninstall) 177 } 178 179 func (s *ManifoldSuite) TestNewWorker_Error(c *gc.C) { 180 clock := &fakeClock{} 181 facade := &fakeFacade{} 182 manifold := resumer.Manifold(resumer.ManifoldConfig{ 183 AgentName: "agent", 184 APICallerName: "api-caller", 185 Clock: clock, 186 Interval: time.Hour, 187 NewFacade: func(base.APICaller) (resumer.Facade, error) { 188 return facade, nil 189 }, 190 NewWorker: func(actual resumer.Config) (worker.Worker, error) { 191 c.Check(actual, jc.DeepEquals, resumer.Config{ 192 Facade: facade, 193 Clock: clock, 194 Interval: time.Hour, 195 }) 196 return nil, errors.New("blam") 197 }, 198 }) 199 200 worker, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 201 "agent": &fakeAgent{}, 202 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 203 })) 204 workertest.CheckNilOrKill(c, worker) 205 c.Check(err, gc.ErrorMatches, "blam") 206 } 207 208 func (s *ManifoldSuite) TestNewWorker_Success(c *gc.C) { 209 expect := &fakeWorker{} 210 manifold := resumer.Manifold(resumer.ManifoldConfig{ 211 AgentName: "agent", 212 APICallerName: "api-caller", 213 NewFacade: func(base.APICaller) (resumer.Facade, error) { 214 return &fakeFacade{}, nil 215 }, 216 NewWorker: func(actual resumer.Config) (worker.Worker, error) { 217 return expect, nil 218 }, 219 }) 220 221 actual, err := manifold.Start(dt.StubContext(nil, map[string]interface{}{ 222 "agent": &fakeAgent{}, 223 "api-caller": newFakeAPICaller(multiwatcher.JobManageModel), 224 })) 225 c.Check(err, jc.ErrorIsNil) 226 c.Check(actual, gc.Equals, expect) 227 } 228 229 // fakeFacade should not be called. 230 type fakeFacade struct { 231 resumer.Facade 232 } 233 234 // fakeClock should not be called. 235 type fakeClock struct { 236 clock.Clock 237 } 238 239 // fakeWorker should not be called. 240 type fakeWorker struct { 241 worker.Worker 242 } 243 244 // fakeAgent exists to expose a tag via CurrentConfig().Tag(). 245 type fakeAgent struct { 246 agent.Agent 247 } 248 249 // CurrentConfig returns an agent.Config with a working Tag() method. 250 func (a *fakeAgent) CurrentConfig() agent.Config { 251 return &fakeConfig{} 252 } 253 254 // fakeConfig exists to expose Tag. 255 type fakeConfig struct { 256 agent.Config 257 } 258 259 // Tag returns a Tag. 260 func (c *fakeConfig) Tag() names.Tag { 261 return names.NewMachineTag("123") 262 } 263 264 func newFakeAPICaller(jobs ...multiwatcher.MachineJob) *fakeAPICaller { 265 return &fakeAPICaller{jobs: jobs} 266 } 267 268 // fakeAPICaller exists to handle the hackish checkModelManager's api 269 // call directly, because it shouldn't happen in this context at all 270 // and we don't want it leaking into the config. 271 type fakeAPICaller struct { 272 base.APICaller 273 stub *testing.Stub 274 jobs []multiwatcher.MachineJob 275 } 276 277 // APICall is part of the base.APICaller interface. 278 func (f *fakeAPICaller) APICall(objType string, version int, id, request string, args interface{}, response interface{}) error { 279 if f.stub != nil { 280 // We don't usually set the stub here, most of the time 281 // the APICall hack is just an unwanted distraction from 282 // the NewFacade/NewWorker bits that *should* exist long- 283 // term. This makes it easier to just delete the broken 284 // tests, and most of this type, including all of the 285 // methods, when we drop the job check. 286 f.stub.AddCall(objType+"."+request, args) 287 if err := f.stub.NextErr(); err != nil { 288 return err 289 } 290 } 291 292 if res, ok := response.(*params.AgentGetEntitiesResults); ok { 293 jobs := make([]multiwatcher.MachineJob, 0, len(f.jobs)) 294 jobs = append(jobs, f.jobs...) 295 res.Entities = []params.AgentGetEntitiesResult{ 296 {Jobs: jobs}, 297 } 298 } 299 return nil 300 } 301 302 // BestFacadeVersion is part of the base.APICaller interface. 303 func (*fakeAPICaller) BestFacadeVersion(facade string) int { 304 return 42 305 }