1
// Copyright 2012-2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
jc "github.com/juju/testing/checkers"
10
gc "gopkg.in/check.v1"
11
"gopkg.in/juju/charm.v6-unstable/hooks"
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"
19
type HookSenderSuite struct{}
21
var _ = gc.Suite(&HookSenderSuite{})
23
func assertNext(c *gc.C, out chan hook.Info, expect hook.Info) {
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)
33
func assertEmpty(c *gc.C, out chan hook.Info) {
35
case <-time.After(coretesting.ShortWait):
36
case actual, ok := <-out:
37
c.Fatalf("got unexpected %#v %#v", actual, ok)
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)
48
for i := range expect {
49
assertNext(c, out, expect[i])
52
statetesting.AssertStop(c, sender)
53
c.Assert(source.Empty(), jc.IsTrue)
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)
63
assertNext(c, out, expect[0])
64
assertNext(c, out, expect[1])
65
statetesting.AssertStop(c, sender)
67
c.Assert(source.Next(), gc.Equals, expect[2])
70
func (s *HookSenderSuite) TestHandlesUpdatesFullQueue(c *gc.C) {
71
source := hooktesting.NewFullUnbufferedSource()
72
defer statetesting.AssertStop(c, source)
74
out := make(chan hook.Info)
75
sender := hook.NewSender(out, source)
76
defer statetesting.AssertStop(c, sender)
78
// Check we're being sent hooks but not updates.
79
assertActive := func() {
80
assertNext(c, out, hook.Info{Kind: hooks.Install})
82
case update, ok := <-source.UpdatesC:
83
c.Fatalf("got unexpected update: %#v %#v", update, ok)
84
case <-time.After(coretesting.ShortWait):
89
// Send an event on the Changes() chan.
91
case source.ChangesC <- source.NewChange("sent"):
92
case <-time.After(coretesting.LongWait):
93
c.Fatalf("could not send change")
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.
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")
110
// Check we're still being sent hooks and not updates.
114
func (s *HookSenderSuite) TestHandlesUpdatesFullQueueSpam(c *gc.C) {
115
source := hooktesting.NewFullBufferedSource()
116
defer statetesting.AssertStop(c, source)
118
out := make(chan hook.Info)
119
sender := hook.NewSender(out, source)
120
defer statetesting.AssertStop(c, sender)
122
// Spam all channels continuously for a bit.
123
timeout := time.After(coretesting.LongWait)
127
for i := 0; i < 100; i++ {
129
case hi, ok := <-out:
130
c.Assert(ok, jc.IsTrue)
131
c.Assert(hi, gc.DeepEquals, hook.Info{Kind: hooks.Install})
133
case source.ChangesC <- source.NewChange("sent"):
135
case update, ok := <-source.UpdatesC:
136
c.Assert(ok, jc.IsTrue)
137
c.Assert(update, gc.Equals, "sent")
140
c.Fatalf("not enough things happened in time")
144
// Once we've finished sending, exhaust the updates...
145
for i := updateCount; i < changeCount && updateCount < changeCount; i++ {
147
case update, ok := <-source.UpdatesC:
148
c.Assert(ok, jc.IsTrue)
149
c.Assert(update, gc.Equals, "sent")
152
c.Fatalf("expected %d updates, got %d", changeCount, updateCount)
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)
161
func (s *HookSenderSuite) TestHandlesUpdatesEmptyQueue(c *gc.C) {
162
source := hooktesting.NewEmptySource()
163
defer statetesting.AssertStop(c, source)
165
out := make(chan hook.Info)
166
sender := hook.NewSender(out, source)
167
defer statetesting.AssertStop(c, sender)
169
// Check no hooks are sent and no updates delivered.
170
assertIdle := func() {
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):
181
// Send an event on the Changes() chan.
182
timeout := time.After(coretesting.LongWait)
184
case source.ChangesC <- source.NewChange("sent"):
186
c.Fatalf("timed out")
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.
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")
200
c.Fatalf("timed out")
203
// Now the change has been delivered, nothing should be happening.
207
func (s *HookSenderSuite) TestHandlesUpdatesEmptyQueueSpam(c *gc.C) {
208
source := hooktesting.NewEmptySource()
209
defer statetesting.AssertStop(c, source)
211
out := make(chan hook.Info)
212
sender := hook.NewSender(out, source)
213
defer statetesting.AssertStop(c, sender)
215
// Spam all channels continuously for a bit.
216
timeout := time.After(coretesting.LongWait)
219
for i := 0; i < 100; i++ {
221
case hi, ok := <-out:
222
c.Fatalf("got unexpected hook: %#v %#v", hi, ok)
223
case source.ChangesC <- source.NewChange("sent"):
225
case update, ok := <-source.UpdatesC:
226
c.Assert(ok, jc.IsTrue)
227
c.Assert(update, gc.Equals, "sent")
230
c.Fatalf("not enough things happened in time")
234
// Check sane end state.
235
c.Check(changeCount, gc.Equals, 50)
236
c.Check(updateCount, gc.Equals, 50)