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