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: ¶ms.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() {}