github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/apicaller/util_test.go (about) 1 // Copyright 2015-2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package apicaller_test 5 6 import ( 7 "time" 8 9 "github.com/juju/testing" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/utils" 12 gc "gopkg.in/check.v1" 13 "gopkg.in/juju/names.v2" 14 "gopkg.in/juju/worker.v1" 15 16 "github.com/juju/juju/agent" 17 "github.com/juju/juju/api" 18 apiagent "github.com/juju/juju/api/agent" 19 "github.com/juju/juju/api/base" 20 "github.com/juju/juju/apiserver/params" 21 coretesting "github.com/juju/juju/testing" 22 "github.com/juju/juju/worker/apicaller" 23 ) 24 25 var errNotProvisioned = ¶ms.Error{Code: params.CodeNotProvisioned} 26 var errNotAuthorized = ¶ms.Error{Code: params.CodeUnauthorized} 27 28 type mockAgent struct { 29 agent.Agent 30 stub *testing.Stub 31 entity names.Tag 32 model names.ModelTag 33 } 34 35 func (mock *mockAgent) CurrentConfig() agent.Config { 36 return dummyConfig{ 37 entity: mock.entity, 38 model: mock.model, 39 } 40 } 41 42 func (mock *mockAgent) ChangeConfig(mutator agent.ConfigMutator) error { 43 mock.stub.AddCall("ChangeConfig") 44 if err := mock.stub.NextErr(); err != nil { 45 return err 46 } 47 return mutator(&mockSetter{stub: mock.stub}) 48 } 49 50 type dummyConfig struct { 51 agent.Config 52 entity names.Tag 53 model names.ModelTag 54 } 55 56 func (dummy dummyConfig) Tag() names.Tag { 57 return dummy.entity 58 } 59 60 func (dummy dummyConfig) Model() names.ModelTag { 61 return dummy.model 62 } 63 64 func (dummy dummyConfig) APIInfo() (*api.Info, bool) { 65 return &api.Info{ 66 ModelTag: dummy.model, 67 Tag: dummy.entity, 68 Password: "new", 69 }, true 70 } 71 72 func (dummy dummyConfig) OldPassword() string { 73 return "old" 74 } 75 76 type mockSetter struct { 77 stub *testing.Stub 78 agent.ConfigSetter 79 } 80 81 func (mock *mockSetter) SetOldPassword(pw string) { 82 mock.stub.AddCall("SetOldPassword", pw) 83 mock.stub.PopNoErr() 84 } 85 86 func (mock *mockSetter) SetPassword(pw string) { 87 mock.stub.AddCall("SetPassword", pw) 88 mock.stub.PopNoErr() 89 } 90 91 type mockConn struct { 92 stub *testing.Stub 93 api.Connection 94 controllerOnly bool 95 broken chan struct{} 96 } 97 98 func (mock *mockConn) ModelTag() (names.ModelTag, bool) { 99 mock.stub.AddCall("ModelTag") 100 if mock.controllerOnly { 101 return names.ModelTag{}, false 102 } 103 return coretesting.ModelTag, true 104 } 105 106 func (mock *mockConn) Broken() <-chan struct{} { 107 return mock.broken 108 } 109 110 func (mock *mockConn) Addr() string { 111 return "testing.invalid" 112 } 113 114 func (mock *mockConn) Close() error { 115 mock.stub.AddCall("Close") 116 return mock.stub.NextErr() 117 } 118 119 func newMockConnFacade(stub *testing.Stub, life apiagent.Life) apiagent.ConnFacade { 120 return &mockConnFacade{ 121 stub: stub, 122 life: life, 123 } 124 } 125 126 type mockConnFacade struct { 127 stub *testing.Stub 128 life apiagent.Life 129 } 130 131 func (mock *mockConnFacade) Life(entity names.Tag) (apiagent.Life, error) { 132 mock.stub.AddCall("Life", entity) 133 if err := mock.stub.NextErr(); err != nil { 134 return "", err 135 } 136 return mock.life, nil 137 } 138 139 func (mock *mockConnFacade) SetPassword(entity names.Tag, password string) error { 140 mock.stub.AddCall("SetPassword", entity, password) 141 return mock.stub.NextErr() 142 } 143 144 type dummyWorker struct { 145 worker.Worker 146 } 147 148 func assertStop(c *gc.C, w worker.Worker) { 149 c.Assert(worker.Stop(w), jc.ErrorIsNil) 150 } 151 152 func assertStopError(c *gc.C, w worker.Worker, match string) { 153 c.Assert(worker.Stop(w), gc.ErrorMatches, match) 154 } 155 156 func lifeTest(c *gc.C, stub *testing.Stub, life apiagent.Life, test func() (api.Connection, error)) (api.Connection, error) { 157 newFacade := func(apiCaller base.APICaller) (apiagent.ConnFacade, error) { 158 c.Check(apiCaller, gc.FitsTypeOf, (*mockConn)(nil)) 159 return newMockConnFacade(stub, life), nil 160 } 161 unpatch := testing.PatchValue(apicaller.NewConnFacade, newFacade) 162 defer unpatch() 163 return test() 164 } 165 166 // TODO(katco): 2016-08-09: lp:1611427 167 func strategyTest(stub *testing.Stub, strategy utils.AttemptStrategy, test func(api.OpenFunc) (api.Connection, error)) (api.Connection, error) { 168 unpatch := testing.PatchValue(apicaller.Strategy, strategy) 169 defer unpatch() 170 return test(func(info *api.Info, opts api.DialOpts) (api.Connection, error) { 171 // copy because I don't trust what might happen to info 172 stub.AddCall("apiOpen", *info, opts) 173 err := stub.NextErr() 174 if err != nil { 175 return nil, err 176 } 177 return &mockConn{stub: stub}, nil 178 }) 179 } 180 181 func checkOpenCalls(c *gc.C, stub *testing.Stub, passwords ...string) { 182 calls := openCalls(names.ModelTag{}, testEntity, passwords...) 183 stub.CheckCalls(c, calls) 184 } 185 186 func openCalls(model names.ModelTag, entity names.Tag, passwords ...string) []testing.StubCall { 187 calls := make([]testing.StubCall, len(passwords)) 188 for i, pw := range passwords { 189 info := api.Info{ 190 ModelTag: model, 191 Tag: entity, 192 Password: pw, 193 } 194 calls[i] = testing.StubCall{ 195 FuncName: "apiOpen", 196 Args: []interface{}{info, api.DialOpts{ 197 DialAddressInterval: 200 * time.Millisecond, 198 DialTimeout: 3 * time.Second, 199 Timeout: time.Minute, 200 }}, 201 } 202 } 203 return calls 204 }