| 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 |