github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/apicaller/manifold_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package apicaller_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names" 9 "github.com/juju/testing" 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 coreagent "github.com/juju/juju/agent" 14 "github.com/juju/juju/api/base" 15 coretesting "github.com/juju/juju/testing" 16 "github.com/juju/juju/worker" 17 "github.com/juju/juju/worker/agent" 18 "github.com/juju/juju/worker/apicaller" 19 "github.com/juju/juju/worker/dependency" 20 dt "github.com/juju/juju/worker/dependency/testing" 21 ) 22 23 type ManifoldSuite struct { 24 testing.IsolationSuite 25 testing.Stub 26 manifold dependency.Manifold 27 agent *mockAgent 28 conn *mockConn 29 getResource dependency.GetResourceFunc 30 } 31 32 var _ = gc.Suite(&ManifoldSuite{}) 33 34 func (s *ManifoldSuite) SetUpTest(c *gc.C) { 35 s.IsolationSuite.SetUpTest(c) 36 s.Stub = testing.Stub{} 37 s.manifold = apicaller.Manifold(apicaller.ManifoldConfig{ 38 AgentName: "agent-name", 39 }) 40 41 s.agent = &mockAgent{ 42 stub: &s.Stub, 43 env: coretesting.EnvironmentTag, 44 } 45 s.getResource = dt.StubGetResource(dt.StubResources{ 46 "agent-name": dt.StubResource{Output: s.agent}, 47 }) 48 49 // Watch out for this: it uses its own Stub because Close calls are made from 50 // the worker's loop goroutine. You should make sure to stop the worker before 51 // checking the mock conn's calls (unless you know the connection will outlive 52 // the test -- see setupMutatorTest). 53 s.conn = &mockConn{ 54 stub: &testing.Stub{}, 55 broken: make(chan struct{}), 56 } 57 s.PatchValue(apicaller.OpenConnection, func(agent agent.Agent) (apicaller.Connection, error) { 58 s.AddCall("openConnection", agent) 59 if err := s.NextErr(); err != nil { 60 return nil, err 61 } 62 return s.conn, nil 63 }) 64 } 65 66 func (s *ManifoldSuite) TestInputs(c *gc.C) { 67 c.Check(s.manifold.Inputs, jc.DeepEquals, []string{"agent-name"}) 68 } 69 70 func (s *ManifoldSuite) TestStartMissingDependency(c *gc.C) { 71 getResource := dt.StubGetResource(dt.StubResources{ 72 "agent-name": dt.StubResource{Error: dependency.ErrMissing}, 73 }) 74 75 worker, err := s.manifold.Start(getResource) 76 c.Check(worker, gc.IsNil) 77 c.Check(err, gc.Equals, dependency.ErrMissing) 78 s.CheckCalls(c, nil) 79 } 80 81 func (s *ManifoldSuite) TestStartCannotOpenAPI(c *gc.C) { 82 s.SetErrors(errors.New("no api for you")) 83 84 worker, err := s.manifold.Start(s.getResource) 85 c.Check(worker, gc.IsNil) 86 c.Check(err, gc.ErrorMatches, "cannot open api: no api for you") 87 s.CheckCalls(c, []testing.StubCall{{ 88 FuncName: "openConnection", 89 Args: []interface{}{s.agent}, 90 }}) 91 } 92 93 func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdSet(c *gc.C) { 94 worker, err := s.manifold.Start(s.getResource) 95 c.Check(err, jc.ErrorIsNil) 96 defer assertStop(c, worker) 97 s.CheckCalls(c, []testing.StubCall{{ 98 FuncName: "openConnection", 99 Args: []interface{}{s.agent}, 100 }}) 101 } 102 103 func (s *ManifoldSuite) setupMutatorTest(c *gc.C) coreagent.ConfigMutator { 104 s.agent.env = names.EnvironTag{} 105 s.conn.stub = &s.Stub // will be unsafe if worker stopped before test finished 106 s.SetErrors( 107 nil, // openConnection, 108 errors.New("nonfatal: always logged and ignored"), // ChangeConfig 109 ) 110 111 worker, err := s.manifold.Start(s.getResource) 112 c.Assert(err, jc.ErrorIsNil) 113 s.AddCleanup(func(c *gc.C) { assertStop(c, worker) }) 114 115 s.CheckCallNames(c, "openConnection", "ChangeConfig") 116 changeArgs := s.Calls()[1].Args 117 c.Assert(changeArgs, gc.HasLen, 1) 118 s.ResetCalls() 119 return changeArgs[0].(coreagent.ConfigMutator) 120 } 121 122 func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdNotSet(c *gc.C) { 123 mutator := s.setupMutatorTest(c) 124 mockSetter := &mockSetter{stub: &s.Stub} 125 126 err := mutator(mockSetter) 127 c.Check(err, jc.ErrorIsNil) 128 s.CheckCalls(c, []testing.StubCall{{ 129 FuncName: "EnvironTag", 130 }, { 131 FuncName: "Migrate", 132 Args: []interface{}{coreagent.MigrateParams{ 133 Environment: coretesting.EnvironmentTag, 134 }}, 135 }}) 136 } 137 138 func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdNotSetBadAPIState(c *gc.C) { 139 mutator := s.setupMutatorTest(c) 140 s.SetErrors(errors.New("no tag for you")) 141 142 err := mutator(nil) 143 c.Check(err, gc.ErrorMatches, "no environment uuid set on api: no tag for you") 144 s.CheckCalls(c, []testing.StubCall{{ 145 FuncName: "EnvironTag", 146 }}) 147 } 148 149 func (s *ManifoldSuite) TestStartSuccessWithEnvironnmentIdNotSetMigrateFailure(c *gc.C) { 150 mutator := s.setupMutatorTest(c) 151 mockSetter := &mockSetter{stub: &s.Stub} 152 s.SetErrors(nil, errors.New("migrate failure")) 153 154 err := mutator(mockSetter) 155 c.Check(err, gc.ErrorMatches, "migrate failure") 156 s.CheckCalls(c, []testing.StubCall{{ 157 FuncName: "EnvironTag", 158 }, { 159 FuncName: "Migrate", 160 Args: []interface{}{coreagent.MigrateParams{ 161 Environment: coretesting.EnvironmentTag, 162 }}, 163 }}) 164 } 165 166 func (s *ManifoldSuite) setupWorkerTest(c *gc.C) worker.Worker { 167 w, err := s.manifold.Start(s.getResource) 168 c.Assert(err, jc.ErrorIsNil) 169 s.AddCleanup(func(c *gc.C) { w.Kill() }) 170 return w 171 } 172 173 func (s *ManifoldSuite) TestKillWorkerClosesConnection(c *gc.C) { 174 worker := s.setupWorkerTest(c) 175 assertStop(c, worker) 176 s.conn.stub.CheckCalls(c, []testing.StubCall{{ 177 FuncName: "Close", 178 }}) 179 } 180 181 func (s *ManifoldSuite) TestKillWorkerReportsCloseErr(c *gc.C) { 182 s.conn.stub.SetErrors(errors.New("bad plumbing")) 183 worker := s.setupWorkerTest(c) 184 185 assertStopError(c, worker, "bad plumbing") 186 s.conn.stub.CheckCalls(c, []testing.StubCall{{ 187 FuncName: "Close", 188 }}) 189 } 190 191 func (s *ManifoldSuite) TestBrokenConnectionKillsWorkerWithCloseErr(c *gc.C) { 192 s.conn.stub.SetErrors(errors.New("bad plumbing")) 193 worker := s.setupWorkerTest(c) 194 195 close(s.conn.broken) 196 err := worker.Wait() 197 c.Check(err, gc.ErrorMatches, "bad plumbing") 198 s.conn.stub.CheckCalls(c, []testing.StubCall{{ 199 FuncName: "Close", 200 }}) 201 } 202 203 func (s *ManifoldSuite) TestBrokenConnectionKillsWorkerWithFallbackErr(c *gc.C) { 204 worker := s.setupWorkerTest(c) 205 206 close(s.conn.broken) 207 err := worker.Wait() 208 c.Check(err, gc.ErrorMatches, "api connection broken unexpectedly") 209 s.conn.stub.CheckCalls(c, []testing.StubCall{{ 210 FuncName: "Close", 211 }}) 212 } 213 214 func (s *ManifoldSuite) TestOutputSuccess(c *gc.C) { 215 worker := s.setupWorkerTest(c) 216 217 var apicaller base.APICaller 218 err := s.manifold.Output(worker, &apicaller) 219 c.Check(err, jc.ErrorIsNil) 220 c.Check(apicaller, gc.Equals, s.conn) 221 } 222 223 func (s *ManifoldSuite) TestOutputBadWorker(c *gc.C) { 224 var apicaller base.APICaller 225 err := s.manifold.Output(dummyWorker{}, &apicaller) 226 c.Check(apicaller, gc.IsNil) 227 c.Check(err.Error(), gc.Equals, "expected *apicaller.apiConnWorker->*base.APICaller; got apicaller_test.dummyWorker->*base.APICaller") 228 } 229 230 func (s *ManifoldSuite) TestOutputBadTarget(c *gc.C) { 231 worker := s.setupWorkerTest(c) 232 233 var apicaller interface{} 234 err := s.manifold.Output(worker, &apicaller) 235 c.Check(apicaller, gc.IsNil) 236 c.Check(err.Error(), gc.Equals, "expected *apicaller.apiConnWorker->*base.APICaller; got *apicaller.apiConnWorker->*interface {}") 237 }