github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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/errors"
    11  	"github.com/juju/testing"
    12  	"github.com/juju/utils/set"
    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  
   138  // NewFakeService returns a new FakeService.
   139  func NewFakeService(name string, conf common.Conf) *FakeService {
   140  	return &FakeService{
   141  		FakeServiceData: NewFakeServiceData(),
   142  		Service: common.Service{
   143  			Name: name,
   144  			Conf: conf,
   145  		},
   146  	}
   147  }
   148  
   149  // Name implements Service.
   150  func (ss *FakeService) Name() string {
   151  	ss.AddCall("Name")
   152  
   153  	ss.NextErr()
   154  	return ss.Service.Name
   155  }
   156  
   157  // Conf implements Service.
   158  func (ss *FakeService) Conf() common.Conf {
   159  	ss.AddCall("Conf")
   160  
   161  	ss.NextErr()
   162  	return ss.Service.Conf
   163  }
   164  
   165  // Running implements Service.
   166  func (ss *FakeService) Running() (bool, error) {
   167  	ss.AddCall("Running")
   168  
   169  	return ss.running(), ss.NextErr()
   170  }
   171  
   172  func (ss *FakeService) running() bool {
   173  	ss.mu.Lock()
   174  	defer ss.mu.Unlock()
   175  	return ss.FakeServiceData.runningNames.Contains(ss.Service.Name)
   176  }
   177  
   178  // Start implements Service.
   179  func (ss *FakeService) Start() error {
   180  	ss.AddCall("Start")
   181  	// TODO(ericsnow) Check managed?
   182  	if ss.running() {
   183  		ss.mu.Lock()
   184  		ss.FakeServiceData.runningNames.Add(ss.Service.Name)
   185  		ss.mu.Unlock()
   186  	}
   187  
   188  	return ss.NextErr()
   189  }
   190  
   191  // Stop implements Service.
   192  func (ss *FakeService) Stop() error {
   193  	ss.AddCall("Stop")
   194  	if !ss.running() {
   195  		ss.mu.Lock()
   196  		ss.FakeServiceData.runningNames.Remove(ss.Service.Name)
   197  		ss.mu.Unlock()
   198  	}
   199  
   200  	return ss.NextErr()
   201  }
   202  
   203  // Exists implements Service.
   204  func (ss *FakeService) Exists() (bool, error) {
   205  	ss.AddCall("Exists")
   206  
   207  	return ss.managed(), ss.NextErr()
   208  }
   209  
   210  func (ss *FakeService) managed() bool {
   211  	ss.mu.Lock()
   212  	defer ss.mu.Unlock()
   213  	return ss.FakeServiceData.managedNames.Contains(ss.Service.Name)
   214  }
   215  
   216  // Installed implements Service.
   217  func (ss *FakeService) Installed() (bool, error) {
   218  	ss.AddCall("Installed")
   219  
   220  	return ss.installed(), ss.NextErr()
   221  }
   222  
   223  func (ss *FakeService) installed() bool {
   224  	ss.mu.Lock()
   225  	defer ss.mu.Unlock()
   226  	return ss.FakeServiceData.installedNames.Contains(ss.Service.Name)
   227  }
   228  
   229  // Install implements Service.
   230  func (ss *FakeService) Install() error {
   231  	ss.AddCall("Install")
   232  	if !ss.running() && !ss.installed() {
   233  		ss.mu.Lock()
   234  		ss.FakeServiceData.installed = append(ss.FakeServiceData.installed, ss)
   235  		ss.FakeServiceData.installedNames.Add(ss.Service.Name)
   236  		ss.mu.Unlock()
   237  	}
   238  
   239  	return ss.NextErr()
   240  }
   241  
   242  // Remove implements Service.
   243  func (ss *FakeService) Remove() error {
   244  	ss.AddCall("Remove")
   245  	if ss.installed() {
   246  		ss.mu.Lock()
   247  		ss.FakeServiceData.removed = append(ss.FakeServiceData.removed, ss)
   248  		ss.FakeServiceData.installedNames.Remove(ss.Service.Name)
   249  		ss.mu.Unlock()
   250  	}
   251  
   252  	return ss.NextErr()
   253  }
   254  
   255  // InstallCommands implements Service.
   256  func (ss *FakeService) InstallCommands() ([]string, error) {
   257  	ss.AddCall("InstallCommands")
   258  
   259  	return nil, ss.NextErr()
   260  }
   261  
   262  // StartCommands implements Service.
   263  func (ss *FakeService) StartCommands() ([]string, error) {
   264  	ss.AddCall("StartCommands")
   265  
   266  	return nil, ss.NextErr()
   267  }