github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/common/watch_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"launchpad.net/tomb"
    10  
    11  	"github.com/juju/names"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/apiserver/common"
    16  	"github.com/juju/juju/apiserver/params"
    17  	apiservertesting "github.com/juju/juju/apiserver/testing"
    18  	"github.com/juju/juju/state"
    19  	statetesting "github.com/juju/juju/state/testing"
    20  )
    21  
    22  type agentEntityWatcherSuite struct{}
    23  
    24  var _ = gc.Suite(&agentEntityWatcherSuite{})
    25  
    26  type fakeAgentEntityWatcher struct {
    27  	state.Entity
    28  	fetchError
    29  }
    30  
    31  func (a *fakeAgentEntityWatcher) Watch() state.NotifyWatcher {
    32  	changes := make(chan struct{}, 1)
    33  	// Simulate initial event.
    34  	changes <- struct{}{}
    35  	return &fakeNotifyWatcher{changes: changes}
    36  }
    37  
    38  type fakeNotifyWatcher struct {
    39  	tomb    tomb.Tomb
    40  	changes chan struct{}
    41  }
    42  
    43  func (w *fakeNotifyWatcher) Stop() error {
    44  	w.Kill()
    45  	return w.Wait()
    46  }
    47  
    48  func (w *fakeNotifyWatcher) Kill() {
    49  	w.tomb.Kill(nil)
    50  	w.tomb.Done()
    51  }
    52  
    53  func (w *fakeNotifyWatcher) Wait() error {
    54  	return w.tomb.Wait()
    55  }
    56  
    57  func (w *fakeNotifyWatcher) Err() error {
    58  	return w.tomb.Err()
    59  }
    60  
    61  func (w *fakeNotifyWatcher) Changes() <-chan struct{} {
    62  	return w.changes
    63  }
    64  
    65  func (*agentEntityWatcherSuite) TestWatch(c *gc.C) {
    66  	st := &fakeState{
    67  		entities: map[names.Tag]entityWithError{
    68  			u("x/0"): &fakeAgentEntityWatcher{fetchError: "x0 fails"},
    69  			u("x/1"): &fakeAgentEntityWatcher{},
    70  			u("x/2"): &fakeAgentEntityWatcher{},
    71  		},
    72  	}
    73  	getCanWatch := func() (common.AuthFunc, error) {
    74  		x0 := u("x/0")
    75  		x1 := u("x/1")
    76  		return func(tag names.Tag) bool {
    77  			return tag == x0 || tag == x1
    78  		}, nil
    79  	}
    80  	resources := common.NewResources()
    81  	a := common.NewAgentEntityWatcher(st, resources, getCanWatch)
    82  	entities := params.Entities{[]params.Entity{
    83  		{"unit-x-0"}, {"unit-x-1"}, {"unit-x-2"}, {"unit-x-3"},
    84  	}}
    85  	result, err := a.Watch(entities)
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{
    88  		Results: []params.NotifyWatchResult{
    89  			{Error: &params.Error{Message: "x0 fails"}},
    90  			{"1", nil},
    91  			{Error: apiservertesting.ErrUnauthorized},
    92  			{Error: apiservertesting.ErrUnauthorized},
    93  		},
    94  	})
    95  }
    96  
    97  func (*agentEntityWatcherSuite) TestWatchError(c *gc.C) {
    98  	getCanWatch := func() (common.AuthFunc, error) {
    99  		return nil, fmt.Errorf("pow")
   100  	}
   101  	resources := common.NewResources()
   102  	a := common.NewAgentEntityWatcher(
   103  		&fakeState{},
   104  		resources,
   105  		getCanWatch,
   106  	)
   107  	_, err := a.Watch(params.Entities{[]params.Entity{{"x0"}}})
   108  	c.Assert(err, gc.ErrorMatches, "pow")
   109  }
   110  
   111  func (*agentEntityWatcherSuite) TestWatchNoArgsNoError(c *gc.C) {
   112  	getCanWatch := func() (common.AuthFunc, error) {
   113  		return nil, fmt.Errorf("pow")
   114  	}
   115  	resources := common.NewResources()
   116  	a := common.NewAgentEntityWatcher(
   117  		&fakeState{},
   118  		resources,
   119  		getCanWatch,
   120  	)
   121  	result, err := a.Watch(params.Entities{})
   122  	c.Assert(err, jc.ErrorIsNil)
   123  	c.Assert(result.Results, gc.HasLen, 0)
   124  }
   125  
   126  type multiNotifyWatcherSuite struct{}
   127  
   128  var _ = gc.Suite(&multiNotifyWatcherSuite{})
   129  
   130  func (*multiNotifyWatcherSuite) TestMultiNotifyWatcher(c *gc.C) {
   131  	w0 := &fakeNotifyWatcher{changes: make(chan struct{}, 1)}
   132  	w1 := &fakeNotifyWatcher{changes: make(chan struct{}, 1)}
   133  	w0.changes <- struct{}{}
   134  	w1.changes <- struct{}{}
   135  
   136  	mw := common.NewMultiNotifyWatcher(w0, w1)
   137  	defer statetesting.AssertStop(c, mw)
   138  
   139  	wc := statetesting.NewNotifyWatcherC(c, nopSyncStarter{}, mw)
   140  	wc.AssertOneChange()
   141  
   142  	w0.changes <- struct{}{}
   143  	wc.AssertOneChange()
   144  	w1.changes <- struct{}{}
   145  	wc.AssertOneChange()
   146  
   147  	w0.changes <- struct{}{}
   148  	w1.changes <- struct{}{}
   149  	wc.AssertOneChange()
   150  }
   151  
   152  func (*multiNotifyWatcherSuite) TestMultiNotifyWatcherStop(c *gc.C) {
   153  	w0 := &fakeNotifyWatcher{changes: make(chan struct{}, 1)}
   154  	w1 := &fakeNotifyWatcher{changes: make(chan struct{}, 1)}
   155  	w0.changes <- struct{}{}
   156  	w1.changes <- struct{}{}
   157  
   158  	mw := common.NewMultiNotifyWatcher(w0, w1)
   159  	wc := statetesting.NewNotifyWatcherC(c, nopSyncStarter{}, mw)
   160  	wc.AssertOneChange()
   161  	statetesting.AssertCanStopWhenSending(c, mw)
   162  	wc.AssertClosed()
   163  }
   164  
   165  type nopSyncStarter struct{}
   166  
   167  func (nopSyncStarter) StartSync() {}