OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 // This file tests the C wait set API (the functions declared in | |
6 // mojo/public/c/include/mojo/system/wait_set.h). | |
7 | |
8 #include <mojo/system/wait_set.h> | |
9 | |
10 #include <mojo/result.h> | |
11 #include <mojo/system/handle.h> | |
12 #include <mojo/system/message_pipe.h> | |
13 | |
14 #include "gtest/gtest.h" | |
15 | |
16 namespace { | |
17 | |
18 const MojoHandleRights kDefaultWaitSetHandleRights = | |
19 MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | | |
20 MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; | |
21 | |
22 TEST(WaitSetTest, InvalidHandle) { | |
23 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
24 MojoWaitSetAdd(MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID, | |
25 MOJO_HANDLE_SIGNAL_READABLE, 123u, nullptr)); | |
26 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
27 MojoWaitSetRemove(MOJO_HANDLE_INVALID, 123u)); | |
28 uint32_t num_results = 10u; | |
29 MojoWaitSetResult results[10] = {}; | |
30 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
31 MojoWaitSetWait(MOJO_HANDLE_INVALID, MOJO_DEADLINE_INDEFINITE, | |
32 &num_results, results, nullptr)); | |
33 | |
34 // Also check |MojoWaitSetAdd()| with a valid handle to be added. | |
35 MojoHandle mph0 = MOJO_HANDLE_INVALID; | |
36 MojoHandle mph1 = MOJO_HANDLE_INVALID; | |
37 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); | |
38 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
39 MojoWaitSetAdd(MOJO_HANDLE_INVALID, mph0, | |
40 MOJO_HANDLE_SIGNAL_READABLE, 123u, nullptr)); | |
41 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); | |
42 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); | |
43 } | |
44 | |
45 TEST(WaitSetTest, Create) { | |
46 // Invalid options. | |
47 { | |
48 static constexpr MojoCreateWaitSetOptions kOptions = {}; | |
49 MojoHandle h = MOJO_HANDLE_INVALID; | |
50 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCreateWaitSet(&kOptions, &h)); | |
51 EXPECT_EQ(MOJO_HANDLE_INVALID, h); | |
52 } | |
53 | |
54 // Options with unknown flags. | |
55 { | |
56 static constexpr MojoCreateWaitSetOptions kOptions = { | |
57 static_cast<uint32_t>(sizeof(MojoCreateWaitSetOptions)), | |
58 ~static_cast<MojoCreateWaitSetOptionsFlags>(0), | |
59 }; | |
60 MojoHandle h = MOJO_HANDLE_INVALID; | |
61 EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, MojoCreateWaitSet(&kOptions, &h)); | |
62 EXPECT_EQ(MOJO_HANDLE_INVALID, h); | |
63 } | |
64 | |
65 // With non-null options. | |
66 { | |
67 static constexpr MojoCreateWaitSetOptions kOptions = { | |
68 static_cast<uint32_t>(sizeof(MojoCreateWaitSetOptions)), | |
69 static_cast<MojoCreateWaitSetOptionsFlags>(0), | |
70 }; | |
71 MojoHandle h = MOJO_HANDLE_INVALID; | |
72 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(&kOptions, &h)); | |
73 EXPECT_NE(h, MOJO_HANDLE_INVALID); | |
74 | |
75 // Should have the correct rights. | |
76 MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; | |
77 EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h, &rights)); | |
78 EXPECT_EQ(kDefaultWaitSetHandleRights, rights); | |
79 | |
80 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); | |
81 } | |
82 | |
83 // With null options. | |
84 { | |
85 MojoHandle h = MOJO_HANDLE_INVALID; | |
86 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); | |
87 EXPECT_NE(h, MOJO_HANDLE_INVALID); | |
88 | |
89 // Should have the correct rights. | |
90 MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; | |
91 EXPECT_EQ(MOJO_RESULT_OK, MojoGetRights(h, &rights)); | |
92 EXPECT_EQ(kDefaultWaitSetHandleRights, rights); | |
93 | |
94 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); | |
95 } | |
96 } | |
97 | |
98 TEST(WaitSetTest, Add) { | |
99 MojoHandle h = MOJO_HANDLE_INVALID; | |
100 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); | |
101 EXPECT_NE(h, MOJO_HANDLE_INVALID); | |
102 | |
103 // Add invalid handle. | |
104 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
105 MojoWaitSetAdd(h, MOJO_HANDLE_INVALID, MOJO_HANDLE_SIGNAL_READABLE, | |
106 0u, nullptr)); | |
107 | |
108 // Some handles that we can add. | |
109 MojoHandle mph0 = MOJO_HANDLE_INVALID; | |
110 MojoHandle mph1 = MOJO_HANDLE_INVALID; | |
111 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); | |
112 | |
113 // Add with invalid options. | |
114 { | |
115 static constexpr MojoWaitSetAddOptions kOptions = {}; | |
116 EXPECT_EQ( | |
117 MOJO_RESULT_INVALID_ARGUMENT, | |
118 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 0u, &kOptions)); | |
119 } | |
120 | |
121 // Add with options with unknown flags. | |
122 { | |
123 static constexpr MojoWaitSetAddOptions kOptions = { | |
124 static_cast<uint32_t>(sizeof(MojoWaitSetAddOptions)), | |
125 ~static_cast<MojoWaitSetAddOptionsFlags>(0), | |
126 }; | |
127 EXPECT_EQ( | |
128 MOJO_RESULT_UNIMPLEMENTED, | |
129 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 0u, &kOptions)); | |
130 } | |
131 | |
132 // Add with options. | |
133 { | |
134 static constexpr MojoWaitSetAddOptions kOptions = { | |
135 static_cast<uint32_t>(sizeof(MojoWaitSetAddOptions)), | |
136 static_cast<MojoWaitSetAddOptionsFlags>(0), | |
137 }; | |
138 EXPECT_EQ( | |
139 MOJO_RESULT_OK, | |
140 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 0u, &kOptions)); | |
141 } | |
142 | |
143 // Add with null options. | |
144 EXPECT_EQ(MOJO_RESULT_OK, | |
145 MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_WRITABLE, 1u, nullptr)); | |
146 | |
147 // Add a handle that's already present, with a different cookie. | |
148 EXPECT_EQ(MOJO_RESULT_OK, | |
149 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 2u, nullptr)); | |
150 | |
151 // Try to add a cookie that's already present. | |
152 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, | |
153 MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_READABLE, 0u, nullptr)); | |
154 | |
155 // Can close things in a wait set. | |
156 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); | |
157 | |
158 // Can close a wait set with unclosed handles in it. | |
159 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); | |
160 | |
161 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); | |
162 } | |
163 | |
164 TEST(WaitSetTest, Remove) { | |
165 MojoHandle h = MOJO_HANDLE_INVALID; | |
166 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); | |
167 EXPECT_NE(h, MOJO_HANDLE_INVALID); | |
168 | |
169 // Some handles that we can add. | |
170 MojoHandle mph0 = MOJO_HANDLE_INVALID; | |
171 MojoHandle mph1 = MOJO_HANDLE_INVALID; | |
172 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); | |
173 | |
174 // Try to remove something that's not there. | |
175 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoWaitSetRemove(h, 12u)); | |
176 | |
177 EXPECT_EQ(MOJO_RESULT_OK, | |
178 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 12u, nullptr)); | |
179 EXPECT_EQ(MOJO_RESULT_OK, | |
180 MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_READABLE, 34u, nullptr)); | |
181 | |
182 // Remove something. | |
183 EXPECT_EQ(MOJO_RESULT_OK, MojoWaitSetRemove(h, 12u)); | |
184 | |
185 // Can't remove it again. | |
186 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoWaitSetRemove(h, 12u)); | |
187 | |
188 // Now can add it again. | |
189 EXPECT_EQ(MOJO_RESULT_OK, | |
190 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_WRITABLE, 12u, nullptr)); | |
191 | |
192 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); | |
193 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); | |
194 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); | |
195 } | |
196 | |
197 // Helper to check if an array of |MojoWaitSetResult|s has a result |r| for the | |
198 // given cookie, in which case: | |
199 // - |r.wait_result| must equal |wait_result|. | |
200 // - If |wait_result| is |MOJO_RESULT_OK| or | |
201 // |MOJO_RESULT_FAILED_PRECONDITION|, then | |
202 // - |r.signals_state.satisfied_signals & signals| must equal | |
203 // |signals_state.satisfied_signals & signals|, and | |
204 // - |r.signals_state.satisfiable & signals| must equal | |
205 // |signals_state.satisfiable_signals & signals|. | |
206 // - Otherwise, |r.signals_state| must equals |signals_state|. | |
207 // (This doesn't check that the result is unique; you should check |num_results| | |
208 // versus the expect number and exhaustively check every expected result.) | |
209 bool CheckHasResult(uint32_t num_results, | |
210 const MojoWaitSetResult* results, | |
211 uint64_t cookie, | |
212 MojoHandleSignals signals, | |
213 MojoResult wait_result, | |
214 const MojoHandleSignalsState& signals_state) { | |
215 for (uint32_t i = 0; i < num_results; i++) { | |
216 if (results[i].cookie == cookie) { | |
217 EXPECT_EQ(wait_result, results[i].wait_result) << cookie; | |
218 EXPECT_EQ(0u, results[i].reserved) << cookie; | |
219 if (wait_result == MOJO_RESULT_OK || | |
220 wait_result == MOJO_RESULT_FAILED_PRECONDITION) { | |
221 EXPECT_EQ(signals_state.satisfied_signals & signals, | |
222 results[i].signals_state.satisfied_signals & signals) | |
223 << cookie; | |
224 EXPECT_EQ(signals_state.satisfiable_signals & signals, | |
225 results[i].signals_state.satisfiable_signals & signals) | |
226 << cookie; | |
227 } else { | |
228 EXPECT_EQ(signals_state.satisfied_signals, | |
229 results[i].signals_state.satisfied_signals) | |
230 << cookie; | |
231 EXPECT_EQ(signals_state.satisfiable_signals, | |
232 results[i].signals_state.satisfiable_signals) | |
233 << cookie; | |
234 } | |
235 return true; | |
236 } | |
237 } | |
238 return false; | |
239 } | |
240 | |
241 TEST(WaitSetTest, Wait) { | |
242 MojoHandle h = MOJO_HANDLE_INVALID; | |
243 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWaitSet(nullptr, &h)); | |
244 EXPECT_NE(h, MOJO_HANDLE_INVALID); | |
245 | |
246 // Nothing in the wait set. | |
247 { | |
248 uint32_t num_results = 10u; | |
249 MojoWaitSetResult results[10] = {}; | |
250 uint32_t max_results = 1234u; | |
251 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
252 MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, | |
253 results, &max_results)); | |
254 EXPECT_EQ(10u, num_results); | |
255 EXPECT_EQ(1234u, max_results); | |
256 } | |
257 | |
258 // Ditto, with non-zero deadline and null |max_results|. | |
259 { | |
260 uint32_t num_results = 10u; | |
261 MojoWaitSetResult results[10] = {}; | |
262 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
263 MojoWaitSetWait(h, static_cast<MojoDeadline>(1000), &num_results, | |
264 results, nullptr)); | |
265 EXPECT_EQ(10u, num_results); | |
266 } | |
267 | |
268 // Some handles that we can add. | |
269 MojoHandle mph0 = MOJO_HANDLE_INVALID; | |
270 MojoHandle mph1 = MOJO_HANDLE_INVALID; | |
271 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mph0, &mph1)); | |
272 | |
273 EXPECT_EQ(MOJO_RESULT_OK, | |
274 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE, 1u, nullptr)); | |
275 EXPECT_EQ(MOJO_RESULT_OK, | |
276 MojoWaitSetAdd(h, mph1, MOJO_HANDLE_SIGNAL_READABLE, 2u, nullptr)); | |
277 | |
278 // Will still time out. | |
279 { | |
280 uint32_t num_results = 10u; | |
281 MojoWaitSetResult results[10] = {}; | |
282 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
283 MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, | |
284 results, nullptr)); | |
285 EXPECT_EQ(10u, num_results); | |
286 } | |
287 | |
288 // Write to |mph1|. | |
289 EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(mph1, nullptr, 0, nullptr, 0, | |
290 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
291 | |
292 // Should get cookie 1. | |
293 { | |
294 uint32_t num_results = 10u; | |
295 MojoWaitSetResult results[10] = {}; | |
296 uint32_t max_results = 1234u; | |
297 EXPECT_EQ(MOJO_RESULT_OK, | |
298 MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, | |
299 results, &max_results)); | |
300 EXPECT_EQ(1u, num_results); | |
301 EXPECT_TRUE(CheckHasResult( | |
302 num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, MOJO_RESULT_OK, | |
303 MojoHandleSignalsState{ | |
304 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
305 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); | |
306 EXPECT_EQ(1u, max_results); | |
307 } | |
308 | |
309 // Non-zero deadline, null |max_results|; should still get cookie 1. | |
310 { | |
311 uint32_t num_results = 10u; | |
312 MojoWaitSetResult results[10] = {}; | |
313 EXPECT_EQ(MOJO_RESULT_OK, | |
314 MojoWaitSetWait(h, static_cast<MojoDeadline>(1000), &num_results, | |
315 results, nullptr)); | |
316 EXPECT_EQ(1u, num_results); | |
317 EXPECT_TRUE(CheckHasResult( | |
318 num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, MOJO_RESULT_OK, | |
319 MojoHandleSignalsState{ | |
320 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
321 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); | |
322 } | |
323 | |
324 // Zero |num_results|. | |
325 { | |
326 uint32_t num_results = 0u; | |
327 uint32_t max_results = 1234u; | |
328 EXPECT_EQ(MOJO_RESULT_OK, | |
329 MojoWaitSetWait(h, static_cast<MojoDeadline>(0), &num_results, | |
330 nullptr, &max_results)); | |
331 EXPECT_EQ(0u, num_results); | |
332 EXPECT_EQ(1u, max_results); | |
333 } | |
334 | |
335 // Add another entry waiting for readability on |mph0|. | |
336 EXPECT_EQ(MOJO_RESULT_OK, | |
337 MojoWaitSetAdd(h, mph0, MOJO_HANDLE_SIGNAL_READABLE | | |
338 MOJO_HANDLE_SIGNAL_WRITABLE, | |
339 3u, nullptr)); | |
340 | |
341 { | |
342 uint32_t num_results = 10u; | |
343 uint32_t max_results = 1234u; | |
344 MojoWaitSetResult results[10] = {}; | |
345 EXPECT_EQ(MOJO_RESULT_OK, | |
346 MojoWaitSetWait(h, MOJO_DEADLINE_INDEFINITE, &num_results, | |
347 results, &max_results)); | |
348 EXPECT_EQ(2u, num_results); | |
349 EXPECT_TRUE(CheckHasResult( | |
350 num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, MOJO_RESULT_OK, | |
351 MojoHandleSignalsState{ | |
352 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
353 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); | |
354 EXPECT_TRUE(CheckHasResult( | |
355 num_results, results, 3u, | |
356 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
357 MOJO_RESULT_OK, | |
358 MojoHandleSignalsState{ | |
359 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
360 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE})); | |
361 EXPECT_EQ(2u, max_results); | |
362 } | |
363 | |
364 // Close |mph0|. | |
365 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph0)); | |
366 | |
367 { | |
368 uint32_t num_results = 10u; | |
369 MojoWaitSetResult results[10] = {}; | |
370 EXPECT_EQ(MOJO_RESULT_OK, MojoWaitSetWait(h, MOJO_DEADLINE_INDEFINITE, | |
371 &num_results, results, nullptr)); | |
372 EXPECT_EQ(3u, num_results); | |
373 EXPECT_TRUE( | |
374 CheckHasResult(num_results, results, 1u, MOJO_HANDLE_SIGNAL_READABLE, | |
375 MOJO_RESULT_CANCELLED, MojoHandleSignalsState())); | |
376 EXPECT_TRUE(CheckHasResult( | |
377 num_results, results, 2u, MOJO_HANDLE_SIGNAL_WRITABLE, | |
378 MOJO_RESULT_FAILED_PRECONDITION, MojoHandleSignalsState())); | |
379 EXPECT_TRUE(CheckHasResult( | |
380 num_results, results, 3u, | |
381 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
382 MOJO_RESULT_CANCELLED, MojoHandleSignalsState())); | |
383 } | |
384 | |
385 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); | |
386 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mph1)); | |
387 } | |
388 | |
389 // TODO(vtl): Add threaded tests, especially those that actually ... wait. | |
390 | |
391 } // namespace | |
OLD | NEW |