github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  
    12  	"github.com/juju/juju/environs"
    13  	"github.com/juju/juju/environs/config"
    14  	coretesting "github.com/juju/juju/testing"
    15  	"github.com/juju/juju/watcher"
    16  	"github.com/juju/juju/worker"
    17  	"github.com/juju/juju/worker/workertest"
    18  )
    19  
    20  type fixture struct {
    21  	watcherErr    error
    22  	observerErrs  []error
    23  	initialConfig map[string]interface{}
    24  }
    25  
    26  func (fix *fixture) Run(c *gc.C, test func(*runContext)) {
    27  	watcher := newNotifyWatcher(fix.watcherErr)
    28  	defer workertest.DirtyKill(c, watcher)
    29  	context := &runContext{
    30  		config:  newModelConfig(c, fix.initialConfig),
    31  		watcher: watcher,
    32  	}
    33  	context.stub.SetErrors(fix.observerErrs...)
    34  	test(context)
    35  }
    36  
    37  type runContext struct {
    38  	mu      sync.Mutex
    39  	stub    testing.Stub
    40  	config  map[string]interface{}
    41  	watcher *notifyWatcher
    42  }
    43  
    44  // SetConfig updates the configuration returned by ModelConfig.
    45  func (context *runContext) SetConfig(c *gc.C, extraAttrs coretesting.Attrs) {
    46  	context.mu.Lock()
    47  	defer context.mu.Unlock()
    48  	context.config = newModelConfig(c, extraAttrs)
    49  }
    50  
    51  // ModelConfig is part of the environ.ConfigObserver interface.
    52  func (context *runContext) ModelConfig() (*config.Config, error) {
    53  	context.mu.Lock()
    54  	defer context.mu.Unlock()
    55  	context.stub.AddCall("ModelConfig")
    56  	if err := context.stub.NextErr(); err != nil {
    57  		return nil, err
    58  	}
    59  	return config.New(config.NoDefaults, context.config)
    60  }
    61  
    62  // KillNotify kills the watcher returned from WatchForModelConfigChanges with
    63  // the error configured in the enclosing fixture.
    64  func (context *runContext) KillNotify() {
    65  	context.watcher.Kill()
    66  }
    67  
    68  // SendNotify sends a value on the channel used by WatchForModelConfigChanges
    69  // results.
    70  func (context *runContext) SendNotify() {
    71  	context.watcher.changes <- struct{}{}
    72  }
    73  
    74  // CloseNotify closes the channel used by WatchForModelConfigChanges results.
    75  func (context *runContext) CloseNotify() {
    76  	close(context.watcher.changes)
    77  }
    78  
    79  // WatchForModelConfigChanges is part of the environ.ConfigObserver interface.
    80  func (context *runContext) WatchForModelConfigChanges() (watcher.NotifyWatcher, error) {
    81  	context.mu.Lock()
    82  	defer context.mu.Unlock()
    83  	context.stub.AddCall("WatchForModelConfigChanges")
    84  	if err := context.stub.NextErr(); err != nil {
    85  		return nil, err
    86  	}
    87  	return context.watcher, nil
    88  }
    89  
    90  func (context *runContext) CheckCallNames(c *gc.C, names ...string) {
    91  	context.mu.Lock()
    92  	defer context.mu.Unlock()
    93  	context.stub.CheckCallNames(c, names...)
    94  }
    95  
    96  // newNotifyWatcher returns a watcher.NotifyWatcher that will fail with the
    97  // supplied error when Kill()ed.
    98  func newNotifyWatcher(err error) *notifyWatcher {
    99  	return &notifyWatcher{
   100  		Worker:  workertest.NewErrorWorker(err),
   101  		changes: make(chan struct{}, 1000),
   102  	}
   103  }
   104  
   105  type notifyWatcher struct {
   106  	worker.Worker
   107  	changes chan struct{}
   108  }
   109  
   110  // Changes is part of the watcher.NotifyWatcher interface.
   111  func (w *notifyWatcher) Changes() watcher.NotifyChannel {
   112  	return w.changes
   113  }
   114  
   115  // newModelConfig returns an environment config map with the supplied attrs
   116  // (on top of some default set), or fails the test.
   117  func newModelConfig(c *gc.C, extraAttrs coretesting.Attrs) map[string]interface{} {
   118  	return coretesting.CustomModelConfig(c, extraAttrs).AllAttrs()
   119  }
   120  
   121  type mockEnviron struct {
   122  	environs.Environ
   123  	testing.Stub
   124  	cfg *config.Config
   125  	mu  sync.Mutex
   126  }
   127  
   128  func (e *mockEnviron) Config() *config.Config {
   129  	e.mu.Lock()
   130  	defer e.mu.Unlock()
   131  	e.MethodCall(e, "Config")
   132  	e.PopNoErr()
   133  	return e.cfg
   134  }
   135  
   136  func (e *mockEnviron) SetConfig(cfg *config.Config) error {
   137  	e.mu.Lock()
   138  	defer e.mu.Unlock()
   139  	e.MethodCall(e, "SetConfig", cfg)
   140  	if err := e.NextErr(); err != nil {
   141  		return err
   142  	}
   143  	e.cfg = cfg
   144  	return nil
   145  }
   146  
   147  func newMockEnviron(cfg *config.Config) (environs.Environ, error) {
   148  	return &mockEnviron{cfg: cfg}, nil
   149  }