@@ -21,8 +21,8 @@ func TestNewNotificationQuery(t *testing.T) {
21
21
{& T {}, true },
22
22
{make ([]T , 0 ), true },
23
23
{make ([]* T , 0 ), true },
24
- {make (map [interface {}]T , 0 ), true },
25
- {make (map [interface {}]* T , 0 ), true },
24
+ {make (map [interface {}]T ), true },
25
+ {make (map [interface {}]* T ), true },
26
26
}
27
27
for _ , test := range cases {
28
28
_ , err := NewNotificationQuery (test .ch , "any" )
@@ -68,14 +68,7 @@ func TestNotificationQuery(t *testing.T) {
68
68
69
69
// Stop the query and confirm routine is dead.
70
70
query .Stop ()
71
- done := make (chan struct {})
72
- go func () {
73
- wg .Wait ()
74
- close (done )
75
- }()
76
- select {
77
- case <- done :
78
- case <- time .After (500 * time .Millisecond ):
71
+ if stopped := wgWaitTimeout (& wg , 500 * time .Millisecond ); ! stopped {
79
72
t .Errorf ("Failed to stop query in 5x NotificationTimeout's" )
80
73
}
81
74
@@ -122,14 +115,7 @@ func TestNotificationQuery_StartStop(t *testing.T) {
122
115
// Do not get the event!
123
116
// Stop the query and confirm routine is dead.
124
117
query .Stop ()
125
- done := make (chan struct {})
126
- go func () {
127
- wg .Wait ()
128
- close (done )
129
- }()
130
- select {
131
- case <- done :
132
- case <- time .After (500 * time .Millisecond ):
118
+ if stopped := wgWaitTimeout (& wg , 500 * time .Millisecond ); ! stopped {
133
119
t .Errorf ("Failed to stop query in 5x NotificationTimeout's" )
134
120
}
135
121
}
@@ -170,14 +156,69 @@ WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = 25` // Shou
170
156
171
157
// Stop the query and confirm routine is dead.
172
158
query .Stop ()
159
+ if stopped := wgWaitTimeout (& wg , 500 * time .Millisecond ); ! stopped {
160
+ t .Errorf ("Failed to stop query in 5x NotificationTimeout's" )
161
+ }
162
+ }
163
+
164
+ func TestNotificationQuery_StopWithError (t * testing.T ) {
165
+ // A struct with incorrect fields that can't be unmarshaled.
166
+ type event struct {
167
+ StrangeField uint64 `wmi:"me_should_not_be_in_event"`
168
+ }
169
+
170
+ // Create a query that will receive an event in a short time.
171
+ resultCh := make (chan event )
172
+ queryString := `
173
+ SELECT * FROM __InstanceModificationEvent
174
+ WHERE TargetInstance ISA 'Win32_LocalTime'`
175
+
176
+ query , err := NewNotificationQuery (resultCh , queryString )
177
+ if err != nil {
178
+ t .Fatalf ("Failed to create NotificationQuery; %s" , err )
179
+ }
180
+ query .SetNotificationTimeout (20 * time .Millisecond )
181
+ const deadline = 1500 * time .Millisecond
182
+
183
+ var wg sync.WaitGroup
184
+ wg .Add (1 )
185
+ go func () {
186
+ if err := query .StartNotifications (); err == nil { // Here!
187
+ t .Error ("Failed to report an error from StartNotifications call" )
188
+ }
189
+ wg .Done ()
190
+ }()
191
+
192
+ // Wait some time to get the error from StartNotifications about inability to
193
+ // parse the received object.
194
+ if stopped := wgWaitTimeout (& wg , deadline ); ! stopped {
195
+ t .Errorf ("Failed to receive an event in %s" , deadline )
196
+ }
197
+
198
+ // Stop the query and confirm routine is dead.
199
+ var stopWG sync.WaitGroup
200
+ stopWG .Add (1 )
201
+ go func () {
202
+ query .Stop ()
203
+ stopWG .Done ()
204
+ }()
205
+ if stopped := wgWaitTimeout (& stopWG , deadline ); ! stopped {
206
+ t .Errorf ("Failed to stop query in %s" , deadline )
207
+ }
208
+ }
209
+
210
+ // Waits for wg.Wait() no more than timeout. Returns true if wg.Wait returned
211
+ // before timeout.
212
+ func wgWaitTimeout (wg * sync.WaitGroup , timeout time.Duration ) bool {
173
213
done := make (chan struct {})
174
214
go func () {
175
215
wg .Wait ()
176
216
close (done )
177
217
}()
178
218
select {
179
219
case <- done :
180
- case <- time .After (500 * time .Millisecond ):
181
- t .Errorf ("Failed to stop query in 5x NotificationTimeout's" )
220
+ return true
221
+ case <- time .After (timeout ):
222
+ return false
182
223
}
183
224
}
0 commit comments