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