-
Notifications
You must be signed in to change notification settings - Fork 0
/
channel.go
148 lines (133 loc) · 4.07 KB
/
channel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2011, 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package testing
import (
"reflect"
"time"
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"
)
// NotifyAsserterC gives helper functions for making assertions about how a
// channel operates (whether we get a receive event or not, whether it is
// closed, etc.)
type NotifyAsserterC struct {
// C is a gocheck C structure for doing assertions
C *gc.C
// Chan is the channel we want to receive on
Chan <-chan struct{}
// Precond will be called before waiting on the channel, can be nil
Precond func()
}
// AssertReceive will ensure that we get an event on the channel and the
// channel is not closed.
func (a *NotifyAsserterC) AssertReceive() {
if a.Precond != nil {
a.Precond()
}
select {
case _, ok := <-a.Chan:
a.C.Assert(ok, jc.IsTrue)
case <-time.After(LongWait):
a.C.Fatalf("timed out waiting for channel message")
}
}
// AssertOneReceive checks that we have exactly one message, and no more
func (a *NotifyAsserterC) AssertOneReceive() {
a.AssertReceive()
a.AssertNoReceive()
}
// AssertClosed ensures that we get a closed event on the channel
func (a *NotifyAsserterC) AssertClosed() {
if a.Precond != nil {
a.Precond()
}
select {
case _, ok := <-a.Chan:
a.C.Assert(ok, jc.IsFalse)
case <-time.After(LongWait):
a.C.Fatalf("timed out waiting for channel to close")
}
}
// Assert that we fail to receive on the channel after a short wait.
func (a *NotifyAsserterC) AssertNoReceive() {
select {
case <-a.Chan:
a.C.Fatalf("unexpected receive")
case <-time.After(ShortWait):
}
}
// ContentAsserterC is like NotifyAsserterC in that it checks the behavior of a
// channel. The difference is that we expect actual content on the channel, so
// callers need to put that into and out of an 'interface{}'
type ContentAsserterC struct {
// C is a gocheck C structure for doing assertions
C *gc.C
// Chan is the channel we want to receive on
Chan interface{}
// Precond will be called before waiting on the channel, can be nil
Precond func()
}
// recv waits to receive a value on the channe for the given
// time. It returns the value received, if any, whether it
// was received ok (the channel was not closed) and
// whether the receive timed out.
func (a *ContentAsserterC) recv(timeout time.Duration) (val interface{}, ok, timedOut bool) {
if a.Precond != nil {
a.Precond()
}
which, v, ok := reflect.Select([]reflect.SelectCase{{
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(a.Chan),
}, {
Dir: reflect.SelectRecv,
Chan: reflect.ValueOf(time.After(timeout)),
}})
switch which {
case 0:
a.C.Assert(ok, jc.IsTrue)
return v.Interface(), ok, false
case 1:
return nil, false, true
}
panic("unreachable")
}
// AssertReceive will ensure that we get an event on the channel and the
// channel is not closed. It will return the content received
func (a *ContentAsserterC) AssertReceive() interface{} {
v, ok, timedOut := a.recv(LongWait)
if timedOut {
a.C.Fatalf("timed out waiting for channel message")
}
a.C.Assert(ok, jc.IsTrue)
return v
}
// AssertOneReceive checks that we have exactly one message, and no more
func (a *ContentAsserterC) AssertOneReceive() interface{} {
res := a.AssertReceive()
a.AssertNoReceive()
return res
}
// AssertOneValue checks that exactly 1 message was sent, and that the content DeepEquals the value.
// It also returns the value in case further inspection is desired.
func (a *ContentAsserterC) AssertOneValue(val interface{}) interface{} {
res := a.AssertReceive()
a.C.Assert(val, gc.DeepEquals, res)
a.AssertNoReceive()
return res
}
// AssertClosed ensures that we get a closed event on the channel
func (a *ContentAsserterC) AssertClosed() {
_, ok, timedOut := a.recv(LongWait)
if timedOut {
a.C.Fatalf("timed out waiting for channel to close")
}
a.C.Assert(ok, jc.IsFalse)
}
// Assert that we fail to receive on the channel after a short wait.
func (a *ContentAsserterC) AssertNoReceive() {
content, _, timedOut := a.recv(ShortWait)
if timedOut {
return
}
a.C.Fatalf("unexpected receive: %#v", content)
}