OLD | NEW |
---|---|
(Empty) | |
1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 * Use of this source code is governed by a BSD-style license that can be | |
3 * found in the LICENSE file. | |
4 */ | |
5 | |
6 #include <errno.h> | |
7 #include <fcntl.h> | |
8 #include <sys/stat.h> | |
9 #include <sys/time.h> | |
10 | |
11 #include "gtest/gtest.h" | |
12 | |
13 #include "nacl_io/event_emitter.h" | |
14 #include "nacl_io/event_listener.h" | |
15 | |
16 | |
17 class EventEmitterTester : public EventEmitter { | |
18 public: | |
19 EventEmitterTester() : event_status_(0), event_cnt_(0) {} | |
20 | |
21 void SetEventStatus(uint32_t bits) { event_status_ = bits; } | |
22 uint32_t GetEventStatus() { return event_status_; } | |
23 | |
24 int GetType() { return S_IFSOCK; } | |
25 | |
26 int NumEvents() { return event_cnt_; } | |
27 | |
28 public: | |
29 // Make this function public for testing | |
30 void RaiseEvent(uint32_t events) { | |
31 EventEmitter::RaiseEvent(events); | |
32 } | |
33 | |
34 // Called after registering locally, but while lock is still held. | |
35 void ChainRegister(const ScopedEventInfo& event) { | |
36 event_cnt_++; | |
37 } | |
38 | |
39 // Called before unregistering locally, but while lock is still held. | |
40 void ChainUnregister(const ScopedEventInfo& event) { | |
41 event_cnt_--; | |
42 } | |
43 | |
44 protected: | |
45 uint32_t event_status_; | |
46 uint32_t event_cnt_; | |
47 }; | |
48 | |
49 | |
50 const int MAX_EVENTS = 8; | |
51 | |
52 // IDs for Emitters | |
53 const int ID_EMITTER = 5; | |
54 const int ID_LISTENER = 6; | |
55 const int ID_EMITTER_DUP = 7; | |
56 | |
57 // Kernel Event values | |
58 const uint32_t KE_EXPECTED = 4; | |
59 const uint32_t KE_FILTERED = 2; | |
60 const uint32_t KE_NONE = 0; | |
61 | |
62 // User Data values | |
63 const uint64_t USER_DATA_A = 1; | |
64 const uint64_t USER_DATA_B = 5; | |
65 | |
66 // Timeout durations | |
67 const int TIMEOUT_IMMEDIATE = 0; | |
68 const int TIMEOUT_SHORT= 100; | |
69 const int TIMEOUT_LONG = 500; | |
70 const int TIMEOUT_NEVER = -1; | |
71 const int TIMEOUT_VERY_LONG = 1000; | |
72 | |
73 TEST(EventTest, EmitterBasic) { | |
74 ScopedRef<EventEmitterTester> emitter(new EventEmitterTester()); | |
75 ScopedRef<EventEmitter> null_emitter; | |
76 | |
77 ScopedEventListener listener(new EventListener); | |
78 | |
79 // Verify construction | |
80 EXPECT_EQ(0, emitter->NumEvents()); | |
81 EXPECT_EQ(0, emitter->GetEventStatus()); | |
82 | |
83 // Verify status | |
84 emitter->SetEventStatus(KE_EXPECTED); | |
85 EXPECT_EQ(KE_EXPECTED, emitter->GetEventStatus()); | |
86 | |
87 // Fail to update or free an ID not in the set | |
88 EXPECT_EQ(ENOENT, listener->Update(ID_EMITTER, KE_EXPECTED, USER_DATA_A)); | |
89 EXPECT_EQ(ENOENT, listener->Free(ID_EMITTER)); | |
90 | |
91 // Fail to Track self | |
92 EXPECT_EQ(EINVAL, listener->Track(ID_LISTENER, | |
93 listener, | |
94 KE_EXPECTED, | |
95 USER_DATA_A)); | |
96 | |
97 // Set the emitter filter and data | |
98 EXPECT_EQ(0, listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A)); | |
99 EXPECT_EQ(1, emitter->NumEvents()); | |
100 | |
101 // Fail to add the same ID | |
102 EXPECT_EQ(EEXIST, | |
103 listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A)); | |
104 EXPECT_EQ(1, emitter->NumEvents()); | |
105 | |
106 int event_cnt = 0; | |
107 EventData ev[MAX_EVENTS]; | |
108 | |
109 // Do not allow a wait with a zero events count. | |
110 EXPECT_EQ(EINVAL, listener->Wait(ev, 0, TIMEOUT_IMMEDIATE, &event_cnt)); | |
111 | |
112 // Do not allow a wait with a negative events count. | |
113 EXPECT_EQ(EINVAL, listener->Wait(ev, -1, TIMEOUT_IMMEDIATE, &event_cnt)); | |
114 | |
115 // Do not allow a wait with a NULL EventData pointer | |
116 EXPECT_EQ(EFAULT, | |
117 listener->Wait(NULL, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
118 | |
119 // Return with no events if the Emitter has no signals set. | |
120 memset(ev, 0, sizeof(ev)); | |
121 event_cnt = 100; | |
122 emitter->SetEventStatus(KE_NONE); | |
123 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
124 EXPECT_EQ(0, event_cnt); | |
125 | |
126 // Return with no events if the Emitter has a filtered signals set. | |
127 memset(ev, 0, sizeof(ev)); | |
128 event_cnt = 100; | |
129 emitter->SetEventStatus(KE_FILTERED); | |
130 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
131 EXPECT_EQ(0, event_cnt); | |
132 | |
133 // Return with one event if the Emitter has the expected signal set. | |
134 memset(ev, 0, sizeof(ev)); | |
135 event_cnt = 100; | |
136 emitter->SetEventStatus(KE_EXPECTED); | |
137 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
138 EXPECT_EQ(1, event_cnt); | |
139 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
140 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
141 | |
142 // Return with one event containing only the expected signal. | |
143 memset(ev, 0, sizeof(ev)); | |
144 event_cnt = 100; | |
145 emitter->SetEventStatus(KE_EXPECTED | KE_FILTERED); | |
146 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
147 EXPECT_EQ(1, event_cnt); | |
148 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
149 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
150 | |
151 // Change the USER_DATA on an existing event | |
152 EXPECT_EQ(0, listener->Update(ID_EMITTER, KE_EXPECTED, USER_DATA_B)); | |
153 | |
154 // Return with one event signaled with the alternate USER DATA | |
155 memset(ev, 0, sizeof(ev)); | |
156 event_cnt = 100; | |
157 emitter->SetEventStatus(KE_EXPECTED | KE_FILTERED); | |
158 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, 0, &event_cnt)); | |
159 EXPECT_EQ(1, event_cnt); | |
160 EXPECT_EQ(USER_DATA_B, ev[0].user_data); | |
161 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
162 | |
163 // Reset the USER_DATA. | |
164 EXPECT_EQ(0, listener->Update(ID_EMITTER, KE_EXPECTED, USER_DATA_A)); | |
165 | |
166 // Support adding a DUP. | |
167 EXPECT_EQ(0, listener->Track(ID_EMITTER_DUP, | |
168 emitter, | |
169 KE_EXPECTED, | |
170 USER_DATA_A)); | |
171 EXPECT_EQ(2, emitter->NumEvents()); | |
172 | |
173 // Return unsignaled. | |
174 memset(ev, 0, sizeof(ev)); | |
175 emitter->SetEventStatus(KE_NONE); | |
176 event_cnt = 100; | |
177 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
178 EXPECT_EQ(0, event_cnt); | |
179 | |
180 // Return with two event signaled with expected data. | |
181 memset(ev, 0, sizeof(ev)); | |
182 emitter->SetEventStatus(KE_EXPECTED); | |
183 event_cnt = 100; | |
184 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_IMMEDIATE, &event_cnt)); | |
185 EXPECT_EQ(2, event_cnt); | |
186 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
187 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
188 EXPECT_EQ(USER_DATA_A, ev[1].user_data); | |
189 EXPECT_EQ(KE_EXPECTED, ev[1].events); | |
190 } | |
191 | |
192 long Duration(struct timeval* start, struct timeval* end) { | |
193 if (start->tv_usec > end->tv_usec) { | |
194 end->tv_sec -= 1; | |
195 end->tv_usec += 1000000; | |
196 } | |
197 long cur_time = 1000 * (end->tv_sec - start->tv_sec); | |
198 cur_time += (end->tv_usec - start->tv_usec) / 1000; | |
199 return cur_time; | |
200 } | |
201 | |
202 | |
203 // Run a timed wait, and return the average of 8 iterations to reduce | |
204 // chance of false negative on outlier. | |
205 const int TRIES_TO_AVERAGE = 8; | |
206 bool TimedListen(ScopedEventListener& listen, | |
207 EventData* ev, | |
208 int ev_max, | |
209 int ev_expect, | |
210 int ms_wait, | |
211 long* duration) { | |
212 | |
213 struct timeval start; | |
214 struct timeval end; | |
215 long total_time = 0; | |
216 | |
217 for (int a=0; a < TRIES_TO_AVERAGE; a++) { | |
218 gettimeofday(&start, NULL); | |
219 | |
220 int signaled; | |
221 | |
222 EXPECT_EQ(0, listen->Wait(ev, ev_max, ms_wait, &signaled)); | |
223 EXPECT_EQ(signaled, ev_expect); | |
224 | |
225 if (signaled != ev_expect) { | |
226 return false; | |
227 } | |
228 | |
229 gettimeofday(&end, NULL); | |
230 | |
231 long cur_time = Duration(&start, &end); | |
232 total_time += cur_time; | |
233 } | |
234 | |
235 *duration = total_time / TRIES_TO_AVERAGE; | |
236 return true; | |
237 } | |
238 | |
239 | |
240 // NOTE: These timing tests are potentially flaky, the real test is | |
241 // for the zero timeout should be, has the ConditionVariable been waited on? | |
242 // Once we provide a debuggable SimpleCond and SimpleLock we can actually test | |
243 // the correct thing. | |
244 | |
245 // Normal scheduling would expect us to see ~10ms accuracy, but we'll | |
246 // use a much bigger number (yet smaller than the MAX_MS_TIMEOUT). | |
247 const int SCHEDULING_GRANUALRITY = 100; | |
binji
2013/07/19 20:47:18
sp: GRANULARITY
noelallen1
2013/07/19 21:35:43
Done.
| |
248 | |
249 const int EXPECT_ONE_EVENT = 1; | |
250 const int EXPECT_NO_EVENT = 0; | |
251 | |
252 TEST(EventTest, EmitterTimeout) { | |
253 ScopedRef<EventEmitterTester> emitter(new EventEmitterTester()); | |
254 ScopedEventListener listener(new EventListener()); | |
255 long duration; | |
256 | |
257 EventData ev[MAX_EVENTS]; | |
258 memset(ev, 0, sizeof(ev)); | |
259 EXPECT_EQ(0, listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A)); | |
260 | |
261 // Return immediately when emitter is signaled, with no timeout | |
262 emitter->SetEventStatus(KE_EXPECTED); | |
263 memset(ev, 0, sizeof(ev)); | |
264 EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_ONE_EVENT, | |
265 TIMEOUT_IMMEDIATE, &duration)); | |
266 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
267 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
268 EXPECT_EQ(0, duration); | |
269 | |
270 // Return immediately when emitter is signaled, even with timeout | |
271 emitter->SetEventStatus(KE_EXPECTED); | |
272 memset(ev, 0, sizeof(ev)); | |
273 EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_ONE_EVENT, | |
274 TIMEOUT_LONG, &duration)); | |
275 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
276 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
277 EXPECT_GT(SCHEDULING_GRANUALRITY, duration); | |
278 | |
279 // Return immediately if Emiiter is already signaled when blocking forever. | |
280 emitter->SetEventStatus(KE_EXPECTED); | |
281 memset(ev, 0, sizeof(ev)); | |
282 EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_ONE_EVENT, | |
283 TIMEOUT_NEVER, &duration)); | |
284 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
285 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
286 EXPECT_GT(SCHEDULING_GRANUALRITY, duration); | |
287 | |
288 // Return immediately if Emitter is no signaled when not blocking. | |
289 emitter->SetEventStatus(KE_NONE); | |
290 memset(ev, 0, sizeof(ev)); | |
291 EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_NO_EVENT, | |
292 TIMEOUT_IMMEDIATE, &duration)); | |
293 EXPECT_EQ(0, duration); | |
294 | |
295 // Wait TIMEOUT_LONG in another thread to signal, and verify we waited | |
binji
2013/07/19 20:47:18
This isn't waiting for another thread, that's the
noelallen1
2013/07/19 21:35:43
Done.
| |
296 // at least "TIMEOUT_LONG" time. | |
297 emitter->SetEventStatus(KE_NONE); | |
298 memset(ev, 0, sizeof(ev)); | |
299 EXPECT_TRUE(TimedListen(listener, ev, MAX_EVENTS, EXPECT_NO_EVENT, | |
300 TIMEOUT_LONG, &duration)); | |
301 EXPECT_LT(TIMEOUT_LONG - 1, duration); | |
302 EXPECT_GT(TIMEOUT_LONG + SCHEDULING_GRANUALRITY, duration); | |
303 } | |
304 | |
305 struct SignalInfo { | |
306 EventEmitterTester* em; | |
307 unsigned int ms_wait; | |
308 uint32_t events; | |
309 }; | |
310 | |
311 void *SignalEmitter(void *ptr) { | |
312 SignalInfo* info = (SignalInfo*) ptr; | |
313 struct timespec ts; | |
314 ts.tv_sec = 0; | |
315 ts.tv_nsec = info->ms_wait * 1000000; | |
316 | |
317 nanosleep(&ts, NULL); | |
318 | |
319 info->em->RaiseEvent(info->events); | |
320 return NULL; | |
321 } | |
322 | |
323 TEST(EventTest, EmitterSignalling) { | |
324 ScopedRef<EventEmitterTester> emitter(new EventEmitterTester()); | |
325 ScopedEventListener listener(new EventListener); | |
326 | |
327 SignalInfo siginfo; | |
328 struct timeval start; | |
329 struct timeval end; | |
330 long duration; | |
331 | |
332 EventData ev[MAX_EVENTS]; | |
333 memset(ev, 0, sizeof(ev)); | |
334 EXPECT_EQ(0, listener->Track(ID_EMITTER, emitter, KE_EXPECTED, USER_DATA_A)); | |
335 | |
336 // Setup another thread to wait 1/4 of the max time, and signal both | |
337 // an expected, and unexpected value. | |
338 siginfo.em = emitter.get(); | |
339 siginfo.ms_wait = TIMEOUT_SHORT; | |
340 siginfo.events = KE_EXPECTED | KE_FILTERED; | |
341 pthread_t tid; | |
342 pthread_create(&tid, NULL, SignalEmitter, &siginfo); | |
343 | |
344 // Wait for the signal from the other thread and time it. | |
345 gettimeofday(&start, NULL); | |
346 int cnt = 0; | |
347 EXPECT_EQ(0, listener->Wait(ev, MAX_EVENTS, TIMEOUT_VERY_LONG, &cnt)); | |
348 EXPECT_EQ(1, cnt); | |
349 gettimeofday(&end, NULL); | |
350 | |
351 // Verify the wait duration, and that we only recieved the expected signal. | |
352 duration = Duration(&start, &end); | |
353 EXPECT_GT(TIMEOUT_SHORT + SCHEDULING_GRANUALRITY, duration); | |
354 EXPECT_LT(TIMEOUT_SHORT - 1, duration); | |
355 EXPECT_EQ(USER_DATA_A, ev[0].user_data); | |
356 EXPECT_EQ(KE_EXPECTED, ev[0].events); | |
357 } | |
OLD | NEW |