github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/hook/sender_test.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package hook_test 5 6 import ( 7 "time" 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/charm.v6-unstable/hooks" 12 13 statetesting "github.com/juju/juju/state/testing" 14 coretesting "github.com/juju/juju/testing" 15 "github.com/juju/juju/worker/uniter/hook" 16 "github.com/juju/juju/worker/uniter/hook/hooktesting" 17 ) 18 19 type HookSenderSuite struct{} 20 21 var _ = gc.Suite(&HookSenderSuite{}) 22 23 func assertNext(c *gc.C, out chan hook.Info, expect hook.Info) { 24 select { 25 case <-time.After(coretesting.LongWait): 26 c.Fatalf("timed out waiting for %#v", expect) 27 case actual, ok := <-out: 28 c.Assert(ok, jc.IsTrue) 29 c.Assert(actual, gc.Equals, expect) 30 } 31 } 32 33 func assertEmpty(c *gc.C, out chan hook.Info) { 34 select { 35 case <-time.After(coretesting.ShortWait): 36 case actual, ok := <-out: 37 c.Fatalf("got unexpected %#v %#v", actual, ok) 38 } 39 } 40 41 func (s *HookSenderSuite) TestSendsHooks(c *gc.C) { 42 expect := hooktesting.HookList(hooks.Install, hooks.ConfigChanged, hooks.Start) 43 source := hook.NewListSource(expect) 44 out := make(chan hook.Info) 45 sender := hook.NewSender(out, source) 46 defer statetesting.AssertStop(c, sender) 47 48 for i := range expect { 49 assertNext(c, out, expect[i]) 50 } 51 assertEmpty(c, out) 52 statetesting.AssertStop(c, sender) 53 c.Assert(source.Empty(), jc.IsTrue) 54 } 55 56 func (s *HookSenderSuite) TestStopsHooks(c *gc.C) { 57 expect := hooktesting.HookList(hooks.Install, hooks.ConfigChanged, hooks.Start) 58 source := hook.NewListSource(expect) 59 out := make(chan hook.Info) 60 sender := hook.NewSender(out, source) 61 defer statetesting.AssertStop(c, sender) 62 63 assertNext(c, out, expect[0]) 64 assertNext(c, out, expect[1]) 65 statetesting.AssertStop(c, sender) 66 assertEmpty(c, out) 67 c.Assert(source.Next(), gc.Equals, expect[2]) 68 } 69 70 func (s *HookSenderSuite) TestHandlesUpdatesFullQueue(c *gc.C) { 71 source := hooktesting.NewFullUnbufferedSource() 72 defer statetesting.AssertStop(c, source) 73 74 out := make(chan hook.Info) 75 sender := hook.NewSender(out, source) 76 defer statetesting.AssertStop(c, sender) 77 78 // Check we're being sent hooks but not updates. 79 assertActive := func() { 80 assertNext(c, out, hook.Info{Kind: hooks.Install}) 81 select { 82 case update, ok := <-source.UpdatesC: 83 c.Fatalf("got unexpected update: %#v %#v", update, ok) 84 case <-time.After(coretesting.ShortWait): 85 } 86 } 87 assertActive() 88 89 // Send an event on the Changes() chan. 90 select { 91 case source.ChangesC <- source.NewChange("sent"): 92 case <-time.After(coretesting.LongWait): 93 c.Fatalf("could not send change") 94 } 95 96 // Now that a change has been delivered, nothing should be sent on the out 97 // chan, or read from the changes chan, until the Update method has completed. 98 select { 99 case source.ChangesC <- source.NewChange("notSent"): 100 c.Fatalf("sent extra change while updating queue") 101 case hi, ok := <-out: 102 c.Fatalf("got unexpected hook while updating queue: %#v %#v", hi, ok) 103 case got, ok := <-source.UpdatesC: 104 c.Assert(ok, jc.IsTrue) 105 c.Assert(got, gc.Equals, "sent") 106 case <-time.After(coretesting.LongWait): 107 c.Fatalf("timed out") 108 } 109 110 // Check we're still being sent hooks and not updates. 111 assertActive() 112 } 113 114 func (s *HookSenderSuite) TestHandlesUpdatesFullQueueSpam(c *gc.C) { 115 source := hooktesting.NewFullBufferedSource() 116 defer statetesting.AssertStop(c, source) 117 118 out := make(chan hook.Info) 119 sender := hook.NewSender(out, source) 120 defer statetesting.AssertStop(c, sender) 121 122 // Spam all channels continuously for a bit. 123 timeout := time.After(coretesting.LongWait) 124 hookCount := 0 125 changeCount := 0 126 updateCount := 0 127 for i := 0; i < 100; i++ { 128 select { 129 case hi, ok := <-out: 130 c.Assert(ok, jc.IsTrue) 131 c.Assert(hi, gc.DeepEquals, hook.Info{Kind: hooks.Install}) 132 hookCount++ 133 case source.ChangesC <- source.NewChange("sent"): 134 changeCount++ 135 case update, ok := <-source.UpdatesC: 136 c.Assert(ok, jc.IsTrue) 137 c.Assert(update, gc.Equals, "sent") 138 updateCount++ 139 case <-timeout: 140 c.Fatalf("not enough things happened in time") 141 } 142 } 143 144 // Once we've finished sending, exhaust the updates... 145 for i := updateCount; i < changeCount && updateCount < changeCount; i++ { 146 select { 147 case update, ok := <-source.UpdatesC: 148 c.Assert(ok, jc.IsTrue) 149 c.Assert(update, gc.Equals, "sent") 150 updateCount++ 151 case <-timeout: 152 c.Fatalf("expected %d updates, got %d", changeCount, updateCount) 153 } 154 } 155 156 // ...and check sane end state to validate the foregoing. 157 c.Check(hookCount, gc.Not(gc.Equals), 0) 158 c.Check(changeCount, gc.Not(gc.Equals), 0) 159 } 160 161 func (s *HookSenderSuite) TestHandlesUpdatesEmptyQueue(c *gc.C) { 162 source := hooktesting.NewEmptySource() 163 defer statetesting.AssertStop(c, source) 164 165 out := make(chan hook.Info) 166 sender := hook.NewSender(out, source) 167 defer statetesting.AssertStop(c, sender) 168 169 // Check no hooks are sent and no updates delivered. 170 assertIdle := func() { 171 select { 172 case hi, ok := <-out: 173 c.Fatalf("got unexpected hook: %#v %#v", hi, ok) 174 case update, ok := <-source.UpdatesC: 175 c.Fatalf("got unexpected update: %#v %#v", update, ok) 176 case <-time.After(coretesting.ShortWait): 177 } 178 } 179 assertIdle() 180 181 // Send an event on the Changes() chan. 182 timeout := time.After(coretesting.LongWait) 183 select { 184 case source.ChangesC <- source.NewChange("sent"): 185 case <-timeout: 186 c.Fatalf("timed out") 187 } 188 189 // Now that a change has been delivered, nothing should be sent on the out 190 // chan, or read from the changes chan, until the Update method has completed. 191 select { 192 case source.ChangesC <- source.NewChange("notSent"): 193 c.Fatalf("sent extra update while updating queue") 194 case hi, ok := <-out: 195 c.Fatalf("got unexpected hook while updating queue: %#v %#v", hi, ok) 196 case got, ok := <-source.UpdatesC: 197 c.Assert(ok, jc.IsTrue) 198 c.Assert(got, gc.Equals, "sent") 199 case <-timeout: 200 c.Fatalf("timed out") 201 } 202 203 // Now the change has been delivered, nothing should be happening. 204 assertIdle() 205 } 206 207 func (s *HookSenderSuite) TestHandlesUpdatesEmptyQueueSpam(c *gc.C) { 208 source := hooktesting.NewEmptySource() 209 defer statetesting.AssertStop(c, source) 210 211 out := make(chan hook.Info) 212 sender := hook.NewSender(out, source) 213 defer statetesting.AssertStop(c, sender) 214 215 // Spam all channels continuously for a bit. 216 timeout := time.After(coretesting.LongWait) 217 changeCount := 0 218 updateCount := 0 219 for i := 0; i < 100; i++ { 220 select { 221 case hi, ok := <-out: 222 c.Fatalf("got unexpected hook: %#v %#v", hi, ok) 223 case source.ChangesC <- source.NewChange("sent"): 224 changeCount++ 225 case update, ok := <-source.UpdatesC: 226 c.Assert(ok, jc.IsTrue) 227 c.Assert(update, gc.Equals, "sent") 228 updateCount++ 229 case <-timeout: 230 c.Fatalf("not enough things happened in time") 231 } 232 } 233 234 // Check sane end state. 235 c.Check(changeCount, gc.Equals, 50) 236 c.Check(updateCount, gc.Equals, 50) 237 }