1 // Copyright 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 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a 6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to 7 // increase tolerance and reduce observed flakiness (though doing so reduces the 8 // meaningfulness of the test). 9 10 #include "mojo/system/simple_dispatcher.h" 11 12 #include "base/basictypes.h" 13 #include "base/logging.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_vector.h" 16 #include "base/synchronization/lock.h" 17 #include "base/threading/platform_thread.h" // For |Sleep()|. 18 #include "base/time/time.h" 19 #include "mojo/system/test_utils.h" 20 #include "mojo/system/waiter.h" 21 #include "mojo/system/waiter_test_utils.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 namespace mojo { 25 namespace system { 26 namespace { 27 28 class MockSimpleDispatcher : public SimpleDispatcher { 29 public: 30 MockSimpleDispatcher() 31 : state_(MOJO_HANDLE_SIGNAL_NONE, 32 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {} 33 34 void SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals) { 35 base::AutoLock locker(lock()); 36 37 // Any new signals that are set should be satisfiable. 38 CHECK_EQ(new_satisfied_signals & ~state_.satisfied_signals, 39 new_satisfied_signals & ~state_.satisfied_signals & 40 state_.satisfiable_signals); 41 42 if (new_satisfied_signals == state_.satisfied_signals) 43 return; 44 45 state_.satisfied_signals = new_satisfied_signals; 46 HandleSignalsStateChangedNoLock(); 47 } 48 49 void SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals) { 50 base::AutoLock locker(lock()); 51 52 // Satisfied implies satisfiable. 53 CHECK_EQ(new_satisfiable_signals & state_.satisfied_signals, 54 state_.satisfied_signals); 55 56 if (new_satisfiable_signals == state_.satisfiable_signals) 57 return; 58 59 state_.satisfiable_signals = new_satisfiable_signals; 60 HandleSignalsStateChangedNoLock(); 61 } 62 63 virtual Type GetType() const OVERRIDE { 64 return kTypeUnknown; 65 } 66 67 private: 68 friend class base::RefCountedThreadSafe<MockSimpleDispatcher>; 69 virtual ~MockSimpleDispatcher() {} 70 71 virtual scoped_refptr<Dispatcher> 72 CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE { 73 scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher()); 74 rv->state_ = state_; 75 return scoped_refptr<Dispatcher>(rv.get()); 76 } 77 78 // |SimpleDispatcher| implementation: 79 virtual HandleSignalsState GetHandleSignalsStateNoLock() const OVERRIDE { 80 lock().AssertAcquired(); 81 return state_; 82 } 83 84 // Protected by |lock()|: 85 HandleSignalsState state_; 86 87 DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher); 88 }; 89 90 TEST(SimpleDispatcherTest, Basic) { 91 test::Stopwatch stopwatch; 92 93 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 94 Waiter w; 95 uint32_t context = 0; 96 97 // Try adding a readable waiter when already readable. 98 w.Init(); 99 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 100 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, 101 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0)); 102 // Shouldn't need to remove the waiter (it was not added). 103 104 // Wait (forever) for writable when already writable. 105 w.Init(); 106 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 107 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1)); 108 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); 109 stopwatch.Start(); 110 EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); 111 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 112 EXPECT_EQ(1u, context); 113 d->RemoveWaiter(&w); 114 115 // Wait for zero time for writable when already writable. 116 w.Init(); 117 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 118 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2)); 119 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); 120 stopwatch.Start(); 121 EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context)); 122 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 123 EXPECT_EQ(2u, context); 124 d->RemoveWaiter(&w); 125 126 // Wait for non-zero, finite time for writable when already writable. 127 w.Init(); 128 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 129 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3)); 130 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); 131 stopwatch.Start(); 132 EXPECT_EQ(MOJO_RESULT_OK, 133 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); 134 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 135 EXPECT_EQ(3u, context); 136 d->RemoveWaiter(&w); 137 138 // Wait for zero time for writable when not writable (will time out). 139 w.Init(); 140 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 141 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4)); 142 stopwatch.Start(); 143 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, NULL)); 144 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 145 d->RemoveWaiter(&w); 146 147 // Wait for non-zero, finite time for writable when not writable (will time 148 // out). 149 w.Init(); 150 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 151 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5)); 152 stopwatch.Start(); 153 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, 154 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), NULL)); 155 base::TimeDelta elapsed = stopwatch.Elapsed(); 156 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); 157 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); 158 d->RemoveWaiter(&w); 159 160 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 161 } 162 163 TEST(SimpleDispatcherTest, BasicUnsatisfiable) { 164 test::Stopwatch stopwatch; 165 166 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 167 Waiter w; 168 uint32_t context = 0; 169 170 // Try adding a writable waiter when it can never be writable. 171 w.Init(); 172 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); 173 d->SetSatisfiedSignals(0); 174 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, 175 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1)); 176 // Shouldn't need to remove the waiter (it was not added). 177 178 // Wait (forever) for writable and then it becomes never writable. 179 w.Init(); 180 d->SetSatisfiableSignals( 181 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); 182 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2)); 183 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); 184 stopwatch.Start(); 185 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, 186 w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); 187 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 188 EXPECT_EQ(2u, context); 189 d->RemoveWaiter(&w); 190 191 // Wait for zero time for writable and then it becomes never writable. 192 w.Init(); 193 d->SetSatisfiableSignals( 194 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); 195 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3)); 196 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); 197 stopwatch.Start(); 198 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context)); 199 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 200 EXPECT_EQ(3u, context); 201 d->RemoveWaiter(&w); 202 203 // Wait for non-zero, finite time for writable and then it becomes never 204 // writable. 205 w.Init(); 206 d->SetSatisfiableSignals( 207 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); 208 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4)); 209 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); 210 stopwatch.Start(); 211 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, 212 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); 213 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 214 EXPECT_EQ(4u, context); 215 d->RemoveWaiter(&w); 216 217 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 218 } 219 220 TEST(SimpleDispatcherTest, BasicClosed) { 221 test::Stopwatch stopwatch; 222 223 scoped_refptr<MockSimpleDispatcher> d; 224 Waiter w; 225 uint32_t context = 0; 226 227 // Try adding a writable waiter when the dispatcher has been closed. 228 d = new MockSimpleDispatcher(); 229 w.Init(); 230 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 231 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, 232 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1)); 233 // Shouldn't need to remove the waiter (it was not added). 234 235 // Wait (forever) for writable and then the dispatcher is closed. 236 d = new MockSimpleDispatcher(); 237 w.Init(); 238 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2)); 239 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 240 stopwatch.Start(); 241 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); 242 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 243 EXPECT_EQ(2u, context); 244 // Don't need to remove waiters from closed dispatchers. 245 246 // Wait for zero time for writable and then the dispatcher is closed. 247 d = new MockSimpleDispatcher(); 248 w.Init(); 249 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3)); 250 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 251 stopwatch.Start(); 252 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context)); 253 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 254 EXPECT_EQ(3u, context); 255 // Don't need to remove waiters from closed dispatchers. 256 257 // Wait for non-zero, finite time for writable and then the dispatcher is 258 // closed. 259 d = new MockSimpleDispatcher(); 260 w.Init(); 261 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4)); 262 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 263 stopwatch.Start(); 264 EXPECT_EQ(MOJO_RESULT_CANCELLED, 265 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); 266 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 267 EXPECT_EQ(4u, context); 268 // Don't need to remove waiters from closed dispatchers. 269 } 270 271 TEST(SimpleDispatcherTest, BasicThreaded) { 272 test::Stopwatch stopwatch; 273 bool did_wait; 274 MojoResult result; 275 uint32_t context; 276 277 // Wait for readable (already readable). 278 { 279 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 280 { 281 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 282 test::WaiterThread thread(d, 283 MOJO_HANDLE_SIGNAL_READABLE, 284 MOJO_DEADLINE_INDEFINITE, 285 1, 286 &did_wait, &result, &context); 287 stopwatch.Start(); 288 thread.Start(); 289 } // Joins the thread. 290 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. 291 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 292 } 293 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); 294 EXPECT_FALSE(did_wait); 295 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); 296 297 // Wait for readable and becomes readable after some time. 298 { 299 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 300 test::WaiterThread thread(d, 301 MOJO_HANDLE_SIGNAL_READABLE, 302 MOJO_DEADLINE_INDEFINITE, 303 2, 304 &did_wait, &result, &context); 305 stopwatch.Start(); 306 thread.Start(); 307 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); 308 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 309 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 310 } // Joins the thread. 311 base::TimeDelta elapsed = stopwatch.Elapsed(); 312 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); 313 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); 314 EXPECT_TRUE(did_wait); 315 EXPECT_EQ(MOJO_RESULT_OK, result); 316 EXPECT_EQ(2u, context); 317 318 // Wait for readable and becomes never-readable after some time. 319 { 320 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 321 test::WaiterThread thread(d, 322 MOJO_HANDLE_SIGNAL_READABLE, 323 MOJO_DEADLINE_INDEFINITE, 324 3, 325 &did_wait, &result, &context); 326 stopwatch.Start(); 327 thread.Start(); 328 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); 329 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE); 330 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 331 } // Joins the thread. 332 elapsed = stopwatch.Elapsed(); 333 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); 334 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); 335 EXPECT_TRUE(did_wait); 336 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); 337 EXPECT_EQ(3u, context); 338 339 // Wait for readable and dispatcher gets closed. 340 { 341 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 342 test::WaiterThread thread(d, 343 MOJO_HANDLE_SIGNAL_READABLE, 344 MOJO_DEADLINE_INDEFINITE, 345 4, 346 &did_wait, &result, &context); 347 stopwatch.Start(); 348 thread.Start(); 349 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); 350 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 351 } // Joins the thread. 352 elapsed = stopwatch.Elapsed(); 353 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); 354 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); 355 EXPECT_TRUE(did_wait); 356 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); 357 EXPECT_EQ(4u, context); 358 359 // Wait for readable and times out. 360 { 361 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 362 { 363 test::WaiterThread thread(d, 364 MOJO_HANDLE_SIGNAL_READABLE, 365 2 * test::EpsilonTimeout().InMicroseconds(), 366 5, 367 &did_wait, &result, &context); 368 stopwatch.Start(); 369 thread.Start(); 370 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); 371 // Not what we're waiting for. 372 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); 373 } // Joins the thread (after its wait times out). 374 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. 375 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 376 } 377 elapsed = stopwatch.Elapsed(); 378 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); 379 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); 380 EXPECT_TRUE(did_wait); 381 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); 382 } 383 384 TEST(SimpleDispatcherTest, MultipleWaiters) { 385 static const uint32_t kNumWaiters = 20; 386 387 bool did_wait[kNumWaiters]; 388 MojoResult result[kNumWaiters]; 389 uint32_t context[kNumWaiters]; 390 391 // All wait for readable and becomes readable after some time. 392 { 393 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 394 ScopedVector<test::WaiterThread> threads; 395 for (uint32_t i = 0; i < kNumWaiters; i++) { 396 threads.push_back(new test::WaiterThread(d, 397 MOJO_HANDLE_SIGNAL_READABLE, 398 MOJO_DEADLINE_INDEFINITE, 399 i, 400 &did_wait[i], 401 &result[i], 402 &context[i])); 403 threads.back()->Start(); 404 } 405 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); 406 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 407 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 408 } // Joins the threads. 409 for (uint32_t i = 0; i < kNumWaiters; i++) { 410 EXPECT_TRUE(did_wait[i]); 411 EXPECT_EQ(MOJO_RESULT_OK, result[i]); 412 EXPECT_EQ(i, context[i]); 413 } 414 415 // Some wait for readable, some for writable, and becomes readable after some 416 // time. 417 { 418 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 419 ScopedVector<test::WaiterThread> threads; 420 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { 421 threads.push_back(new test::WaiterThread(d, 422 MOJO_HANDLE_SIGNAL_READABLE, 423 MOJO_DEADLINE_INDEFINITE, 424 i, 425 &did_wait[i], 426 &result[i], 427 &context[i])); 428 threads.back()->Start(); 429 } 430 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { 431 threads.push_back(new test::WaiterThread(d, 432 MOJO_HANDLE_SIGNAL_WRITABLE, 433 MOJO_DEADLINE_INDEFINITE, 434 i, 435 &did_wait[i], 436 &result[i], 437 &context[i])); 438 threads.back()->Start(); 439 } 440 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); 441 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 442 // This will wake up the ones waiting to write. 443 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 444 } // Joins the threads. 445 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { 446 EXPECT_TRUE(did_wait[i]); 447 EXPECT_EQ(MOJO_RESULT_OK, result[i]); 448 EXPECT_EQ(i, context[i]); 449 } 450 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { 451 EXPECT_TRUE(did_wait[i]); 452 EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]); 453 EXPECT_EQ(i, context[i]); 454 } 455 456 // Some wait for readable, some for writable, and becomes readable and 457 // never-writable after some time. 458 { 459 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 460 ScopedVector<test::WaiterThread> threads; 461 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { 462 threads.push_back(new test::WaiterThread(d, 463 MOJO_HANDLE_SIGNAL_READABLE, 464 MOJO_DEADLINE_INDEFINITE, 465 i, 466 &did_wait[i], 467 &result[i], 468 &context[i])); 469 threads.back()->Start(); 470 } 471 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { 472 threads.push_back(new test::WaiterThread(d, 473 MOJO_HANDLE_SIGNAL_WRITABLE, 474 MOJO_DEADLINE_INDEFINITE, 475 i, 476 &did_wait[i], 477 &result[i], 478 &context[i])); 479 threads.back()->Start(); 480 } 481 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); 482 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); 483 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); 484 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 485 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 486 } // Joins the threads. 487 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { 488 EXPECT_TRUE(did_wait[i]); 489 EXPECT_EQ(MOJO_RESULT_OK, result[i]); 490 EXPECT_EQ(i, context[i]); 491 } 492 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { 493 EXPECT_TRUE(did_wait[i]); 494 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]); 495 EXPECT_EQ(i, context[i]); 496 } 497 498 // Some wait for readable, some for writable, and becomes readable after some 499 // time. 500 { 501 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); 502 ScopedVector<test::WaiterThread> threads; 503 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { 504 threads.push_back( 505 new test::WaiterThread(d, 506 MOJO_HANDLE_SIGNAL_READABLE, 507 3 * test::EpsilonTimeout().InMicroseconds(), 508 i, 509 &did_wait[i], &result[i], &context[i])); 510 threads.back()->Start(); 511 } 512 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { 513 threads.push_back( 514 new test::WaiterThread(d, 515 MOJO_HANDLE_SIGNAL_WRITABLE, 516 1 * test::EpsilonTimeout().InMicroseconds(), 517 i, 518 &did_wait[i], &result[i], &context[i])); 519 threads.back()->Start(); 520 } 521 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); 522 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); 523 // All those waiting for writable should have timed out. 524 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); 525 } // Joins the threads. 526 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { 527 EXPECT_TRUE(did_wait[i]); 528 EXPECT_EQ(MOJO_RESULT_OK, result[i]); 529 EXPECT_EQ(i, context[i]); 530 } 531 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { 532 EXPECT_TRUE(did_wait[i]); 533 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]); 534 } 535 } 536 537 // TODO(vtl): Stress test? 538 539 } // namespace 540 } // namespace system 541 } // namespace mojo 542