github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/service/common/testing/fake.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package testing 5 6 import ( 7 "strings" 8 "sync" 9 10 "github.com/juju/collections/set" 11 "github.com/juju/errors" 12 "github.com/juju/testing" 13 14 "github.com/juju/juju/service/common" 15 ) 16 17 type ServiceInfo interface { 18 Name() string 19 Conf() common.Conf 20 } 21 22 // FakeServiceData holds the results of Service method calls. 23 type FakeServiceData struct { 24 testing.Stub 25 26 mu sync.Mutex 27 28 // installed is the list of all services that were installed. 29 installed []ServiceInfo 30 31 // removed is the list of all services that were removed. 32 removed []ServiceInfo 33 34 // managedNames is the set of "currently" juju-managed services. 35 managedNames set.Strings 36 37 // installedNames is the set of "currently" installed services. 38 installedNames set.Strings 39 40 // runningNames is the set of "currently" running services. 41 runningNames set.Strings 42 } 43 44 // NewFakeServiceData returns a new FakeServiceData. 45 func NewFakeServiceData(names ...string) *FakeServiceData { 46 fsd := FakeServiceData{ 47 managedNames: set.NewStrings(), 48 installedNames: set.NewStrings(), 49 runningNames: set.NewStrings(), 50 } 51 for _, name := range names { 52 fsd.installedNames.Add(name) 53 } 54 return &fsd 55 } 56 57 // InstalledNames returns a copy of the list of the installed names. 58 func (f *FakeServiceData) InstalledNames() []string { 59 f.mu.Lock() 60 defer f.mu.Unlock() 61 return f.installedNames.Values() 62 } 63 64 // Installed returns a copy of the list of installed Services 65 func (f *FakeServiceData) Installed() []ServiceInfo { 66 f.mu.Lock() 67 defer f.mu.Unlock() 68 names := make([]ServiceInfo, len(f.installed)) 69 copy(names, f.installed) 70 return names 71 } 72 73 // GetInstalled returns the installed service that matches name. 74 75 // Removed returns a copy of the list of removed Services 76 func (f *FakeServiceData) Removed() []ServiceInfo { 77 f.mu.Lock() 78 defer f.mu.Unlock() 79 names := make([]ServiceInfo, len(f.removed)) 80 copy(names, f.removed) 81 return names 82 } 83 84 // GetInstalled returns the installed service that matches name. 85 // If name is not found, the method panics. 86 func (f *FakeServiceData) GetInstalled(name string) ServiceInfo { 87 f.mu.Lock() 88 defer f.mu.Unlock() 89 90 for _, i := range f.installed { 91 if i.Name() == name { 92 return i 93 } 94 } 95 panic(name + " not found") 96 } 97 98 // SetStatus updates the status of the named service. 99 func (f *FakeServiceData) SetStatus(name, status string) error { 100 f.mu.Lock() 101 defer f.mu.Unlock() 102 if status == "" { 103 f.managedNames.Remove(name) 104 f.installedNames.Remove(name) 105 f.runningNames.Remove(name) 106 return nil 107 } 108 109 managed := true 110 if strings.HasPrefix(status, "(") && strings.HasSuffix(status, ")") { 111 status = status[1 : len(status)-1] 112 managed = false 113 } 114 115 switch status { 116 case "installed": 117 f.installedNames.Add(name) 118 f.runningNames.Remove(name) 119 case "running": 120 f.installedNames.Add(name) 121 f.runningNames.Add(name) 122 default: 123 return errors.NotSupportedf("status %q", status) 124 } 125 126 if managed { 127 f.managedNames.Add(name) 128 } 129 return nil 130 } 131 132 // FakeService is a Service implementation for testing. 133 type FakeService struct { 134 *FakeServiceData 135 common.Service 136 137 DataDir string 138 } 139 140 // NewFakeService returns a new FakeService. 141 func NewFakeService(name string, conf common.Conf) *FakeService { 142 return &FakeService{ 143 FakeServiceData: NewFakeServiceData(), 144 Service: common.Service{ 145 Name: name, 146 Conf: conf, 147 }, 148 } 149 } 150 151 // Name implements Service. 152 func (ss *FakeService) Name() string { 153 ss.AddCall("Name") 154 155 return ss.Service.Name 156 } 157 158 // Conf implements Service. 159 func (ss *FakeService) Conf() common.Conf { 160 ss.AddCall("Conf") 161 162 ss.NextErr() 163 return ss.Service.Conf 164 } 165 166 // Running implements Service. 167 func (ss *FakeService) Running() (bool, error) { 168 ss.AddCall("Running") 169 170 return ss.running(), ss.NextErr() 171 } 172 173 func (ss *FakeService) running() bool { 174 ss.mu.Lock() 175 defer ss.mu.Unlock() 176 return ss.FakeServiceData.runningNames.Contains(ss.Service.Name) 177 } 178 179 // Start implements Service. 180 func (ss *FakeService) Start() error { 181 ss.AddCall("Start", ss.Service.Name) 182 // TODO(ericsnow) Check managed? 183 if !ss.running() { 184 ss.mu.Lock() 185 ss.FakeServiceData.runningNames.Add(ss.Service.Name) 186 ss.mu.Unlock() 187 } 188 189 return ss.NextErr() 190 } 191 192 // Stop implements Service. 193 func (ss *FakeService) Stop() error { 194 ss.AddCall("Stop") 195 if ss.running() { 196 ss.mu.Lock() 197 ss.FakeServiceData.runningNames.Remove(ss.Service.Name) 198 ss.mu.Unlock() 199 } 200 201 return ss.NextErr() 202 } 203 204 // Exists implements Service. 205 func (ss *FakeService) Exists() (bool, error) { 206 ss.AddCall("Exists") 207 208 return ss.managed(), ss.NextErr() 209 } 210 211 func (ss *FakeService) managed() bool { 212 ss.mu.Lock() 213 defer ss.mu.Unlock() 214 return ss.FakeServiceData.managedNames.Contains(ss.Service.Name) 215 } 216 217 // Installed implements Service. 218 func (ss *FakeService) Installed() (bool, error) { 219 ss.AddCall("Installed") 220 221 return ss.installed(), ss.NextErr() 222 } 223 224 func (ss *FakeService) installed() bool { 225 ss.mu.Lock() 226 defer ss.mu.Unlock() 227 return ss.FakeServiceData.installedNames.Contains(ss.Service.Name) 228 } 229 230 // Install implements Service. 231 func (ss *FakeService) Install() error { 232 ss.AddCall("Install") 233 if !ss.running() && !ss.installed() { 234 ss.mu.Lock() 235 ss.FakeServiceData.installed = append(ss.FakeServiceData.installed, ss) 236 ss.FakeServiceData.installedNames.Add(ss.Service.Name) 237 ss.mu.Unlock() 238 } 239 240 return ss.NextErr() 241 } 242 243 // Remove implements Service. 244 func (ss *FakeService) Remove() error { 245 ss.AddCall("Remove") 246 if ss.installed() { 247 ss.mu.Lock() 248 ss.FakeServiceData.removed = append(ss.FakeServiceData.removed, ss) 249 ss.FakeServiceData.installedNames.Remove(ss.Service.Name) 250 ss.mu.Unlock() 251 } 252 253 return ss.NextErr() 254 } 255 256 // InstallCommands implements Service. 257 func (ss *FakeService) InstallCommands() ([]string, error) { 258 ss.AddCall("InstallCommands") 259 260 return nil, ss.NextErr() 261 } 262 263 // StartCommands implements Service. 264 func (ss *FakeService) StartCommands() ([]string, error) { 265 ss.AddCall("StartCommands") 266 267 return nil, ss.NextErr() 268 } 269 270 // WriteService implements UpgradableService. 271 func (ss *FakeService) WriteService() error { 272 ss.AddCall("WriteService") 273 retErr := ss.NextErr() 274 if retErr != nil { 275 return retErr 276 } 277 return nil 278 }