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