github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/remotestate/mock_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package remotestate_test 5 6 import ( 7 "sync" 8 9 "gopkg.in/juju/charm.v6-unstable" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/core/leadership" 14 "github.com/juju/juju/watcher" 15 "github.com/juju/juju/worker/uniter/remotestate" 16 ) 17 18 func newMockWatcher() *mockWatcher { 19 return &mockWatcher{ 20 stopped: make(chan struct{}), 21 } 22 } 23 24 type mockWatcher struct { 25 mu sync.Mutex 26 stopped chan struct{} 27 } 28 29 func (w *mockWatcher) Kill() { 30 w.mu.Lock() 31 defer w.mu.Unlock() 32 if !w.Stopped() { 33 close(w.stopped) 34 } 35 } 36 37 func (w *mockWatcher) Wait() error { 38 <-w.stopped 39 return nil 40 } 41 42 func (w *mockWatcher) Stopped() bool { 43 select { 44 case <-w.stopped: 45 return true 46 default: 47 return false 48 } 49 } 50 51 func newMockNotifyWatcher() *mockNotifyWatcher { 52 return &mockNotifyWatcher{ 53 mockWatcher: newMockWatcher(), 54 changes: make(chan struct{}, 1), 55 } 56 } 57 58 type mockNotifyWatcher struct { 59 *mockWatcher 60 changes chan struct{} 61 } 62 63 func (w *mockNotifyWatcher) Changes() watcher.NotifyChannel { 64 return w.changes 65 } 66 67 func newMockStringsWatcher() *mockStringsWatcher { 68 return &mockStringsWatcher{ 69 mockWatcher: newMockWatcher(), 70 changes: make(chan []string, 1), 71 } 72 } 73 74 type mockStringsWatcher struct { 75 *mockWatcher 76 changes chan []string 77 } 78 79 func (w *mockStringsWatcher) Changes() watcher.StringsChannel { 80 return w.changes 81 } 82 83 func newMockRelationUnitsWatcher() *mockRelationUnitsWatcher { 84 return &mockRelationUnitsWatcher{ 85 mockWatcher: newMockWatcher(), 86 changes: make(chan watcher.RelationUnitsChange, 1), 87 } 88 } 89 90 type mockRelationUnitsWatcher struct { 91 *mockWatcher 92 changes chan watcher.RelationUnitsChange 93 } 94 95 func (w *mockRelationUnitsWatcher) Changes() watcher.RelationUnitsChannel { 96 return w.changes 97 } 98 99 type mockState struct { 100 unit mockUnit 101 relations map[names.RelationTag]*mockRelation 102 storageAttachment map[params.StorageAttachmentId]params.StorageAttachment 103 relationUnitsWatchers map[names.RelationTag]*mockRelationUnitsWatcher 104 storageAttachmentWatchers map[names.StorageTag]*mockNotifyWatcher 105 } 106 107 func (st *mockState) Relation(tag names.RelationTag) (remotestate.Relation, error) { 108 r, ok := st.relations[tag] 109 if !ok { 110 return nil, ¶ms.Error{Code: params.CodeNotFound} 111 } 112 return r, nil 113 } 114 115 func (st *mockState) StorageAttachment( 116 storageTag names.StorageTag, unitTag names.UnitTag, 117 ) (params.StorageAttachment, error) { 118 if unitTag != st.unit.tag { 119 return params.StorageAttachment{}, ¶ms.Error{Code: params.CodeNotFound} 120 } 121 attachment, ok := st.storageAttachment[params.StorageAttachmentId{ 122 UnitTag: unitTag.String(), 123 StorageTag: storageTag.String(), 124 }] 125 if !ok { 126 return params.StorageAttachment{}, ¶ms.Error{Code: params.CodeNotFound} 127 } 128 if attachment.Kind == params.StorageKindUnknown { 129 return params.StorageAttachment{}, ¶ms.Error{Code: params.CodeNotProvisioned} 130 } 131 return attachment, nil 132 } 133 134 func (st *mockState) StorageAttachmentLife( 135 ids []params.StorageAttachmentId, 136 ) ([]params.LifeResult, error) { 137 results := make([]params.LifeResult, len(ids)) 138 for i, id := range ids { 139 attachment, ok := st.storageAttachment[id] 140 if !ok { 141 results[i] = params.LifeResult{ 142 Error: ¶ms.Error{Code: params.CodeNotFound}, 143 } 144 continue 145 } 146 results[i] = params.LifeResult{Life: attachment.Life} 147 } 148 return results, nil 149 } 150 151 func (st *mockState) Unit(tag names.UnitTag) (remotestate.Unit, error) { 152 if tag != st.unit.tag { 153 return nil, ¶ms.Error{Code: params.CodeNotFound} 154 } 155 return &st.unit, nil 156 } 157 158 func (st *mockState) WatchRelationUnits( 159 relationTag names.RelationTag, unitTag names.UnitTag, 160 ) (watcher.RelationUnitsWatcher, error) { 161 if unitTag != st.unit.tag { 162 return nil, ¶ms.Error{Code: params.CodeNotFound} 163 } 164 watcher, ok := st.relationUnitsWatchers[relationTag] 165 if !ok { 166 return nil, ¶ms.Error{Code: params.CodeNotFound} 167 } 168 return watcher, nil 169 } 170 171 func (st *mockState) WatchStorageAttachment( 172 storageTag names.StorageTag, unitTag names.UnitTag, 173 ) (watcher.NotifyWatcher, error) { 174 if unitTag != st.unit.tag { 175 return nil, ¶ms.Error{Code: params.CodeNotFound} 176 } 177 watcher, ok := st.storageAttachmentWatchers[storageTag] 178 if !ok { 179 return nil, ¶ms.Error{Code: params.CodeNotFound} 180 } 181 return watcher, nil 182 } 183 184 type mockUnit struct { 185 tag names.UnitTag 186 life params.Life 187 resolved params.ResolvedMode 188 service mockService 189 unitWatcher *mockNotifyWatcher 190 addressesWatcher *mockNotifyWatcher 191 configSettingsWatcher *mockNotifyWatcher 192 storageWatcher *mockStringsWatcher 193 actionWatcher *mockStringsWatcher 194 } 195 196 func (u *mockUnit) Life() params.Life { 197 return u.life 198 } 199 200 func (u *mockUnit) Refresh() error { 201 return nil 202 } 203 204 func (u *mockUnit) Resolved() (params.ResolvedMode, error) { 205 return u.resolved, nil 206 } 207 208 func (u *mockUnit) Application() (remotestate.Application, error) { 209 return &u.service, nil 210 } 211 212 func (u *mockUnit) Tag() names.UnitTag { 213 return u.tag 214 } 215 216 func (u *mockUnit) Watch() (watcher.NotifyWatcher, error) { 217 return u.unitWatcher, nil 218 } 219 220 func (u *mockUnit) WatchAddresses() (watcher.NotifyWatcher, error) { 221 return u.addressesWatcher, nil 222 } 223 224 func (u *mockUnit) WatchConfigSettings() (watcher.NotifyWatcher, error) { 225 return u.configSettingsWatcher, nil 226 } 227 228 func (u *mockUnit) WatchStorage() (watcher.StringsWatcher, error) { 229 return u.storageWatcher, nil 230 } 231 232 func (u *mockUnit) WatchActionNotifications() (watcher.StringsWatcher, error) { 233 return u.actionWatcher, nil 234 } 235 236 type mockService struct { 237 tag names.ApplicationTag 238 life params.Life 239 curl *charm.URL 240 charmModifiedVersion int 241 forceUpgrade bool 242 serviceWatcher *mockNotifyWatcher 243 leaderSettingsWatcher *mockNotifyWatcher 244 relationsWatcher *mockStringsWatcher 245 } 246 247 func (s *mockService) CharmModifiedVersion() (int, error) { 248 return s.charmModifiedVersion, nil 249 } 250 251 func (s *mockService) CharmURL() (*charm.URL, bool, error) { 252 return s.curl, s.forceUpgrade, nil 253 } 254 255 func (s *mockService) Life() params.Life { 256 return s.life 257 } 258 259 func (s *mockService) Refresh() error { 260 return nil 261 } 262 263 func (s *mockService) Tag() names.ApplicationTag { 264 return s.tag 265 } 266 267 func (s *mockService) Watch() (watcher.NotifyWatcher, error) { 268 return s.serviceWatcher, nil 269 } 270 271 func (s *mockService) WatchLeadershipSettings() (watcher.NotifyWatcher, error) { 272 return s.leaderSettingsWatcher, nil 273 } 274 275 func (s *mockService) WatchRelations() (watcher.StringsWatcher, error) { 276 return s.relationsWatcher, nil 277 } 278 279 type mockRelation struct { 280 id int 281 life params.Life 282 } 283 284 func (r *mockRelation) Id() int { 285 return r.id 286 } 287 288 func (r *mockRelation) Life() params.Life { 289 return r.life 290 } 291 292 type mockLeadershipTracker struct { 293 leadership.Tracker 294 claimTicket mockTicket 295 leaderTicket mockTicket 296 minionTicket mockTicket 297 } 298 299 func (mock *mockLeadershipTracker) ClaimLeader() leadership.Ticket { 300 return &mock.claimTicket 301 } 302 303 func (mock *mockLeadershipTracker) WaitLeader() leadership.Ticket { 304 return &mock.leaderTicket 305 } 306 307 func (mock *mockLeadershipTracker) WaitMinion() leadership.Ticket { 308 return &mock.minionTicket 309 } 310 311 type mockTicket struct { 312 ch chan struct{} 313 result bool 314 } 315 316 func (t *mockTicket) Ready() <-chan struct{} { 317 return t.ch 318 } 319 320 func (t *mockTicket) Wait() bool { 321 return t.result 322 }