github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/environ/fixture_test.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package environ_test 5 6 import ( 7 "sync" 8 9 "github.com/juju/testing" 10 gc "gopkg.in/check.v1" 11 names "gopkg.in/juju/names.v2" 12 "gopkg.in/juju/worker.v1" 13 "gopkg.in/juju/worker.v1/workertest" 14 15 "github.com/juju/juju/core/watcher" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/config" 18 coretesting "github.com/juju/juju/testing" 19 ) 20 21 type fixture struct { 22 watcherErr error 23 observerErrs []error 24 cloud environs.CloudSpec 25 initialConfig map[string]interface{} 26 } 27 28 func (fix *fixture) Run(c *gc.C, test func(*runContext)) { 29 watcher := newNotifyWatcher(fix.watcherErr) 30 defer workertest.DirtyKill(c, watcher) 31 context := &runContext{ 32 cloud: fix.cloud, 33 config: newModelConfig(c, fix.initialConfig), 34 watcher: watcher, 35 } 36 context.stub.SetErrors(fix.observerErrs...) 37 test(context) 38 } 39 40 type runContext struct { 41 mu sync.Mutex 42 stub testing.Stub 43 cloud environs.CloudSpec 44 config map[string]interface{} 45 watcher *notifyWatcher 46 credWatcher *notifyWatcher 47 } 48 49 // SetConfig updates the configuration returned by ModelConfig. 50 func (context *runContext) SetConfig(c *gc.C, extraAttrs coretesting.Attrs) { 51 context.mu.Lock() 52 defer context.mu.Unlock() 53 context.config = newModelConfig(c, extraAttrs) 54 } 55 56 // CloudSpec is part of the environ.ConfigObserver interface. 57 func (context *runContext) CloudSpec() (environs.CloudSpec, error) { 58 context.mu.Lock() 59 defer context.mu.Unlock() 60 context.stub.AddCall("CloudSpec") 61 if err := context.stub.NextErr(); err != nil { 62 return environs.CloudSpec{}, err 63 } 64 return context.cloud, nil 65 } 66 67 // ModelConfig is part of the environ.ConfigObserver interface. 68 func (context *runContext) ModelConfig() (*config.Config, error) { 69 context.mu.Lock() 70 defer context.mu.Unlock() 71 context.stub.AddCall("ModelConfig") 72 if err := context.stub.NextErr(); err != nil { 73 return nil, err 74 } 75 return config.New(config.NoDefaults, context.config) 76 } 77 78 // KillModelConfigNotify kills the watcher returned from WatchForModelConfigChanges with 79 // the error configured in the enclosing fixture. 80 func (context *runContext) KillModelConfigNotify() { 81 context.watcher.Kill() 82 } 83 84 // SendModelConfigNotify sends a value on the channel used by WatchForModelConfigChanges 85 // results. 86 func (context *runContext) SendModelConfigNotify() { 87 context.watcher.changes <- struct{}{} 88 } 89 90 // CloseModelConfigNotify closes the channel used by WatchForModelConfigChanges results. 91 func (context *runContext) CloseModelConfigNotify() { 92 close(context.watcher.changes) 93 } 94 95 // WatchForModelConfigChanges is part of the environ.ConfigObserver interface. 96 func (context *runContext) WatchForModelConfigChanges() (watcher.NotifyWatcher, error) { 97 context.mu.Lock() 98 defer context.mu.Unlock() 99 context.stub.AddCall("WatchForModelConfigChanges") 100 if err := context.stub.NextErr(); err != nil { 101 return nil, err 102 } 103 return context.watcher, nil 104 } 105 106 // KillCredentialNotify kills the watcher returned from WatchCredentialChanges with 107 // the error configured in the enclosing fixture. 108 func (context *runContext) KillCredentialNotify() { 109 context.credWatcher.Kill() 110 } 111 112 // SendCredentialNotify sends a value on the channel used by WatchCredentialChanges 113 // results. 114 func (context *runContext) SendCredentialNotify() { 115 context.credWatcher.changes <- struct{}{} 116 } 117 118 // CloseCredentialNotify closes the channel used by WatchCredentialChanges results. 119 func (context *runContext) CloseCredentialNotify() { 120 close(context.credWatcher.changes) 121 } 122 123 // WatchCredential is part of the environ.ConfigObserver interface. 124 func (context *runContext) WatchCredential(cred names.CloudCredentialTag) (watcher.NotifyWatcher, error) { 125 context.mu.Lock() 126 defer context.mu.Unlock() 127 context.stub.AddCall("WatchCredential") 128 if err := context.stub.NextErr(); err != nil { 129 return nil, err 130 } 131 return context.watcher, nil 132 } 133 134 func (context *runContext) CheckCallNames(c *gc.C, names ...string) { 135 context.mu.Lock() 136 defer context.mu.Unlock() 137 context.stub.CheckCallNames(c, names...) 138 } 139 140 // newNotifyWatcher returns a watcher.NotifyWatcher that will fail with the 141 // supplied error when Kill()ed. 142 func newNotifyWatcher(err error) *notifyWatcher { 143 return ¬ifyWatcher{ 144 Worker: workertest.NewErrorWorker(err), 145 changes: make(chan struct{}, 1000), 146 } 147 } 148 149 type notifyWatcher struct { 150 worker.Worker 151 changes chan struct{} 152 } 153 154 // Changes is part of the watcher.NotifyWatcher interface. 155 func (w *notifyWatcher) Changes() watcher.NotifyChannel { 156 return w.changes 157 } 158 159 // newModelConfig returns an environment config map with the supplied attrs 160 // (on top of some default set), or fails the test. 161 func newModelConfig(c *gc.C, extraAttrs coretesting.Attrs) map[string]interface{} { 162 return coretesting.CustomModelConfig(c, extraAttrs).AllAttrs() 163 } 164 165 type mockEnviron struct { 166 environs.Environ 167 testing.Stub 168 cfg *config.Config 169 mu sync.Mutex 170 } 171 172 func (e *mockEnviron) Config() *config.Config { 173 e.mu.Lock() 174 defer e.mu.Unlock() 175 e.MethodCall(e, "Config") 176 e.PopNoErr() 177 return e.cfg 178 } 179 180 func (e *mockEnviron) SetConfig(cfg *config.Config) error { 181 e.mu.Lock() 182 defer e.mu.Unlock() 183 e.MethodCall(e, "SetConfig", cfg) 184 if err := e.NextErr(); err != nil { 185 return err 186 } 187 e.cfg = cfg 188 return nil 189 } 190 191 func newMockEnviron(args environs.OpenParams) (environs.Environ, error) { 192 return &mockEnviron{cfg: args.Config}, nil 193 }