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  }