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