| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a | 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 | 6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to |
| 7 // tolerance and reduce observed flakiness. | 7 // increase tolerance and reduce observed flakiness (though doing so reduces the |
| 8 // meaningfulness of the test). |
| 8 | 9 |
| 9 #include "mojo/system/message_pipe_dispatcher.h" | 10 #include "mojo/system/message_pipe_dispatcher.h" |
| 10 | 11 |
| 11 #include <string.h> | 12 #include <string.h> |
| 12 | 13 |
| 13 #include <limits> | 14 #include <limits> |
| 14 | 15 |
| 15 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
| 16 #include "base/memory/scoped_vector.h" | 17 #include "base/memory/scoped_vector.h" |
| 17 #include "base/rand_util.h" | 18 #include "base/rand_util.h" |
| 18 #include "base/threading/platform_thread.h" // For |Sleep()|. | 19 #include "base/threading/platform_thread.h" // For |Sleep()|. |
| 19 #include "base/threading/simple_thread.h" | 20 #include "base/threading/simple_thread.h" |
| 20 #include "base/time/time.h" | 21 #include "base/time/time.h" |
| 21 #include "mojo/system/message_pipe.h" | 22 #include "mojo/system/message_pipe.h" |
| 22 #include "mojo/system/test_utils.h" | 23 #include "mojo/system/test_utils.h" |
| 23 #include "mojo/system/waiter.h" | 24 #include "mojo/system/waiter.h" |
| 24 #include "mojo/system/waiter_test_utils.h" | 25 #include "mojo/system/waiter_test_utils.h" |
| 25 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 26 | 27 |
| 27 namespace mojo { | 28 namespace mojo { |
| 28 namespace system { | 29 namespace system { |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 const int64_t kMicrosPerMs = 1000; | |
| 32 const int64_t kEpsilonMicros = 30 * kMicrosPerMs; // 30 ms. | |
| 33 | |
| 34 TEST(MessagePipeDispatcherTest, Basic) { | 32 TEST(MessagePipeDispatcherTest, Basic) { |
| 35 test::Stopwatch stopwatch; | 33 test::Stopwatch stopwatch; |
| 36 int32_t buffer[1]; | 34 int32_t buffer[1]; |
| 37 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 35 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 38 uint32_t buffer_size; | 36 uint32_t buffer_size; |
| 39 int64_t elapsed_micros; | |
| 40 | 37 |
| 41 // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. | 38 // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. |
| 42 for (unsigned i = 0; i < 2; i++) { | 39 for (unsigned i = 0; i < 2; i++) { |
| 43 scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher()); | 40 scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher()); |
| 44 scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher()); | 41 scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher()); |
| 45 { | 42 { |
| 46 scoped_refptr<MessagePipe> mp(new MessagePipe()); | 43 scoped_refptr<MessagePipe> mp(new MessagePipe()); |
| 47 d0->Init(mp, i); // 0, 1. | 44 d0->Init(mp, i); // 0, 1. |
| 48 d1->Init(mp, i ^ 1); // 1, 0. | 45 d1->Init(mp, i ^ 1); // 1, 0. |
| 49 } | 46 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 60 w.Init(); | 57 w.Init(); |
| 61 EXPECT_EQ(MOJO_RESULT_OK, | 58 EXPECT_EQ(MOJO_RESULT_OK, |
| 62 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 1)); | 59 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 1)); |
| 63 buffer[0] = 123456789; | 60 buffer[0] = 123456789; |
| 64 EXPECT_EQ(MOJO_RESULT_OK, | 61 EXPECT_EQ(MOJO_RESULT_OK, |
| 65 d1->WriteMessage(buffer, kBufferSize, | 62 d1->WriteMessage(buffer, kBufferSize, |
| 66 NULL, | 63 NULL, |
| 67 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 64 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 68 stopwatch.Start(); | 65 stopwatch.Start(); |
| 69 EXPECT_EQ(1, w.Wait(MOJO_DEADLINE_INDEFINITE)); | 66 EXPECT_EQ(1, w.Wait(MOJO_DEADLINE_INDEFINITE)); |
| 70 elapsed_micros = stopwatch.Elapsed(); | 67 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); |
| 71 EXPECT_LT(elapsed_micros, kEpsilonMicros); | |
| 72 d0->RemoveWaiter(&w); | 68 d0->RemoveWaiter(&w); |
| 73 | 69 |
| 74 // Try adding a readable waiter when already readable (from above). | 70 // Try adding a readable waiter when already readable (from above). |
| 75 w.Init(); | 71 w.Init(); |
| 76 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, | 72 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
| 77 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 2)); | 73 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 2)); |
| 78 // Shouldn't need to remove the waiter (it was not added). | 74 // Shouldn't need to remove the waiter (it was not added). |
| 79 | 75 |
| 80 // Make |d0| no longer readable (by reading from it). | 76 // Make |d0| no longer readable (by reading from it). |
| 81 buffer[0] = 0; | 77 buffer[0] = 0; |
| 82 buffer_size = kBufferSize; | 78 buffer_size = kBufferSize; |
| 83 EXPECT_EQ(MOJO_RESULT_OK, | 79 EXPECT_EQ(MOJO_RESULT_OK, |
| 84 d0->ReadMessage(buffer, &buffer_size, | 80 d0->ReadMessage(buffer, &buffer_size, |
| 85 0, NULL, | 81 0, NULL, |
| 86 MOJO_READ_MESSAGE_FLAG_NONE)); | 82 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 87 EXPECT_EQ(kBufferSize, buffer_size); | 83 EXPECT_EQ(kBufferSize, buffer_size); |
| 88 EXPECT_EQ(123456789, buffer[0]); | 84 EXPECT_EQ(123456789, buffer[0]); |
| 89 | 85 |
| 90 // Wait for zero time for readability on |d0| (will time out). | 86 // Wait for zero time for readability on |d0| (will time out). |
| 91 w.Init(); | 87 w.Init(); |
| 92 EXPECT_EQ(MOJO_RESULT_OK, | 88 EXPECT_EQ(MOJO_RESULT_OK, |
| 93 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3)); | 89 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3)); |
| 94 stopwatch.Start(); | 90 stopwatch.Start(); |
| 95 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0)); | 91 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0)); |
| 96 elapsed_micros = stopwatch.Elapsed(); | 92 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); |
| 97 EXPECT_LT(elapsed_micros, kEpsilonMicros); | |
| 98 d0->RemoveWaiter(&w); | 93 d0->RemoveWaiter(&w); |
| 99 | 94 |
| 100 // Wait for non-zero, finite time for readability on |d0| (will time out). | 95 // Wait for non-zero, finite time for readability on |d0| (will time out). |
| 101 w.Init(); | 96 w.Init(); |
| 102 EXPECT_EQ(MOJO_RESULT_OK, | 97 EXPECT_EQ(MOJO_RESULT_OK, |
| 103 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3)); | 98 d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3)); |
| 104 stopwatch.Start(); | 99 stopwatch.Start(); |
| 105 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(2 * kEpsilonMicros)); | 100 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, |
| 106 elapsed_micros = stopwatch.Elapsed(); | 101 w.Wait(2 * test::EpsilonTimeout().InMicroseconds())); |
| 107 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros); | 102 base::TimeDelta elapsed = stopwatch.Elapsed(); |
| 108 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros); | 103 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); |
| 104 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); |
| 109 d0->RemoveWaiter(&w); | 105 d0->RemoveWaiter(&w); |
| 110 | 106 |
| 111 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); | 107 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); |
| 112 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); | 108 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); |
| 113 } | 109 } |
| 114 } | 110 } |
| 115 | 111 |
| 116 TEST(MessagePipeDispatcherTest, InvalidParams) { | 112 TEST(MessagePipeDispatcherTest, InvalidParams) { |
| 117 char buffer[1]; | 113 char buffer[1]; |
| 118 | 114 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 | 247 |
| 252 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); | 248 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); |
| 253 } | 249 } |
| 254 } | 250 } |
| 255 | 251 |
| 256 TEST(MessagePipeDispatcherTest, BasicThreaded) { | 252 TEST(MessagePipeDispatcherTest, BasicThreaded) { |
| 257 test::Stopwatch stopwatch; | 253 test::Stopwatch stopwatch; |
| 258 int32_t buffer[1]; | 254 int32_t buffer[1]; |
| 259 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 255 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 260 uint32_t buffer_size; | 256 uint32_t buffer_size; |
| 257 base::TimeDelta elapsed; |
| 261 bool did_wait; | 258 bool did_wait; |
| 262 MojoResult result; | 259 MojoResult result; |
| 263 int64_t elapsed_micros; | |
| 264 | 260 |
| 265 // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. | 261 // Run this test both with |d0| as port 0, |d1| as port 1 and vice versa. |
| 266 for (unsigned i = 0; i < 2; i++) { | 262 for (unsigned i = 0; i < 2; i++) { |
| 267 scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher()); | 263 scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher()); |
| 268 scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher()); | 264 scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher()); |
| 269 { | 265 { |
| 270 scoped_refptr<MessagePipe> mp(new MessagePipe()); | 266 scoped_refptr<MessagePipe> mp(new MessagePipe()); |
| 271 d0->Init(mp, i); // 0, 1. | 267 d0->Init(mp, i); // 0, 1. |
| 272 d1->Init(mp, i ^ 1); // 1, 0. | 268 d1->Init(mp, i ^ 1); // 1, 0. |
| 273 } | 269 } |
| 274 | 270 |
| 275 // Wait for readable on |d1|, which will become readable after some time. | 271 // Wait for readable on |d1|, which will become readable after some time. |
| 276 { | 272 { |
| 277 test::WaiterThread thread(d1, | 273 test::WaiterThread thread(d1, |
| 278 MOJO_WAIT_FLAG_READABLE, | 274 MOJO_WAIT_FLAG_READABLE, |
| 279 MOJO_DEADLINE_INDEFINITE, | 275 MOJO_DEADLINE_INDEFINITE, |
| 280 0, | 276 0, |
| 281 &did_wait, &result); | 277 &did_wait, &result); |
| 282 stopwatch.Start(); | 278 stopwatch.Start(); |
| 283 thread.Start(); | 279 thread.Start(); |
| 284 base::PlatformThread::Sleep( | 280 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
| 285 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); | |
| 286 // Wake it up by writing to |d0|. | 281 // Wake it up by writing to |d0|. |
| 287 buffer[0] = 123456789; | 282 buffer[0] = 123456789; |
| 288 EXPECT_EQ(MOJO_RESULT_OK, | 283 EXPECT_EQ(MOJO_RESULT_OK, |
| 289 d0->WriteMessage(buffer, kBufferSize, | 284 d0->WriteMessage(buffer, kBufferSize, |
| 290 NULL, | 285 NULL, |
| 291 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 286 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 292 } // Joins the thread. | 287 } // Joins the thread. |
| 293 elapsed_micros = stopwatch.Elapsed(); | 288 elapsed = stopwatch.Elapsed(); |
| 289 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); |
| 290 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); |
| 294 EXPECT_TRUE(did_wait); | 291 EXPECT_TRUE(did_wait); |
| 295 EXPECT_EQ(0, result); | 292 EXPECT_EQ(0, result); |
| 296 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros); | |
| 297 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros); | |
| 298 | 293 |
| 299 // Now |d1| is already readable. Try waiting for it again. | 294 // Now |d1| is already readable. Try waiting for it again. |
| 300 { | 295 { |
| 301 test::WaiterThread thread(d1, | 296 test::WaiterThread thread(d1, |
| 302 MOJO_WAIT_FLAG_READABLE, | 297 MOJO_WAIT_FLAG_READABLE, |
| 303 MOJO_DEADLINE_INDEFINITE, | 298 MOJO_DEADLINE_INDEFINITE, |
| 304 1, | 299 1, |
| 305 &did_wait, &result); | 300 &did_wait, &result); |
| 306 stopwatch.Start(); | 301 stopwatch.Start(); |
| 307 thread.Start(); | 302 thread.Start(); |
| 308 } // Joins the thread. | 303 } // Joins the thread. |
| 309 elapsed_micros = stopwatch.Elapsed(); | 304 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); |
| 310 EXPECT_FALSE(did_wait); | 305 EXPECT_FALSE(did_wait); |
| 311 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); | 306 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); |
| 312 EXPECT_LT(elapsed_micros, kEpsilonMicros); | |
| 313 | 307 |
| 314 // Consume what we wrote to |d0|. | 308 // Consume what we wrote to |d0|. |
| 315 buffer[0] = 0; | 309 buffer[0] = 0; |
| 316 buffer_size = kBufferSize; | 310 buffer_size = kBufferSize; |
| 317 EXPECT_EQ(MOJO_RESULT_OK, | 311 EXPECT_EQ(MOJO_RESULT_OK, |
| 318 d1->ReadMessage(buffer, &buffer_size, | 312 d1->ReadMessage(buffer, &buffer_size, |
| 319 0, NULL, | 313 0, NULL, |
| 320 MOJO_READ_MESSAGE_FLAG_NONE)); | 314 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 321 EXPECT_EQ(kBufferSize, buffer_size); | 315 EXPECT_EQ(kBufferSize, buffer_size); |
| 322 EXPECT_EQ(123456789, buffer[0]); | 316 EXPECT_EQ(123456789, buffer[0]); |
| 323 | 317 |
| 324 // Wait for readable on |d1| and close |d0| after some time, which should | 318 // Wait for readable on |d1| and close |d0| after some time, which should |
| 325 // cancel that wait. | 319 // cancel that wait. |
| 326 { | 320 { |
| 327 test::WaiterThread thread(d1, | 321 test::WaiterThread thread(d1, |
| 328 MOJO_WAIT_FLAG_READABLE, | 322 MOJO_WAIT_FLAG_READABLE, |
| 329 MOJO_DEADLINE_INDEFINITE, | 323 MOJO_DEADLINE_INDEFINITE, |
| 330 0, | 324 0, |
| 331 &did_wait, &result); | 325 &did_wait, &result); |
| 332 stopwatch.Start(); | 326 stopwatch.Start(); |
| 333 thread.Start(); | 327 thread.Start(); |
| 334 base::PlatformThread::Sleep( | 328 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
| 335 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); | |
| 336 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); | 329 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); |
| 337 } // Joins the thread. | 330 } // Joins the thread. |
| 338 elapsed_micros = stopwatch.Elapsed(); | 331 elapsed = stopwatch.Elapsed(); |
| 332 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); |
| 333 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); |
| 339 EXPECT_TRUE(did_wait); | 334 EXPECT_TRUE(did_wait); |
| 340 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | 335 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
| 341 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros); | |
| 342 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros); | |
| 343 | 336 |
| 344 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); | 337 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); |
| 345 } | 338 } |
| 346 | 339 |
| 347 for (unsigned i = 0; i < 2; i++) { | 340 for (unsigned i = 0; i < 2; i++) { |
| 348 scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher()); | 341 scoped_refptr<MessagePipeDispatcher> d0(new MessagePipeDispatcher()); |
| 349 scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher()); | 342 scoped_refptr<MessagePipeDispatcher> d1(new MessagePipeDispatcher()); |
| 350 { | 343 { |
| 351 scoped_refptr<MessagePipe> mp(new MessagePipe()); | 344 scoped_refptr<MessagePipe> mp(new MessagePipe()); |
| 352 d0->Init(mp, i); // 0, 1. | 345 d0->Init(mp, i); // 0, 1. |
| 353 d1->Init(mp, i ^ 1); // 1, 0. | 346 d1->Init(mp, i ^ 1); // 1, 0. |
| 354 } | 347 } |
| 355 | 348 |
| 356 // Wait for readable on |d1| and close |d1| after some time, which should | 349 // Wait for readable on |d1| and close |d1| after some time, which should |
| 357 // cancel that wait. | 350 // cancel that wait. |
| 358 { | 351 { |
| 359 test::WaiterThread thread(d1, | 352 test::WaiterThread thread(d1, |
| 360 MOJO_WAIT_FLAG_READABLE, | 353 MOJO_WAIT_FLAG_READABLE, |
| 361 MOJO_DEADLINE_INDEFINITE, | 354 MOJO_DEADLINE_INDEFINITE, |
| 362 0, | 355 0, |
| 363 &did_wait, &result); | 356 &did_wait, &result); |
| 364 stopwatch.Start(); | 357 stopwatch.Start(); |
| 365 thread.Start(); | 358 thread.Start(); |
| 366 base::PlatformThread::Sleep( | 359 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); |
| 367 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); | |
| 368 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); | 360 EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); |
| 369 } // Joins the thread. | 361 } // Joins the thread. |
| 370 elapsed_micros = stopwatch.Elapsed(); | 362 elapsed = stopwatch.Elapsed(); |
| 363 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout()); |
| 364 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout()); |
| 371 EXPECT_TRUE(did_wait); | 365 EXPECT_TRUE(did_wait); |
| 372 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | 366 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
| 373 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros); | |
| 374 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros); | |
| 375 | 367 |
| 376 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); | 368 EXPECT_EQ(MOJO_RESULT_OK, d0->Close()); |
| 377 } | 369 } |
| 378 } | 370 } |
| 379 | 371 |
| 380 // Stress test ----------------------------------------------------------------- | 372 // Stress test ----------------------------------------------------------------- |
| 381 | 373 |
| 382 const size_t kMaxMessageSize = 2000; | 374 const size_t kMaxMessageSize = 2000; |
| 383 | 375 |
| 384 class WriterThread : public base::SimpleThread { | 376 class WriterThread : public base::SimpleThread { |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 EXPECT_EQ(total_messages_written, total_messages_read); | 570 EXPECT_EQ(total_messages_written, total_messages_read); |
| 579 EXPECT_EQ(total_bytes_written, total_bytes_read); | 571 EXPECT_EQ(total_bytes_written, total_bytes_read); |
| 580 | 572 |
| 581 EXPECT_EQ(MOJO_RESULT_OK, d_write->Close()); | 573 EXPECT_EQ(MOJO_RESULT_OK, d_write->Close()); |
| 582 EXPECT_EQ(MOJO_RESULT_OK, d_read->Close()); | 574 EXPECT_EQ(MOJO_RESULT_OK, d_read->Close()); |
| 583 } | 575 } |
| 584 | 576 |
| 585 } // namespace | 577 } // namespace |
| 586 } // namespace system | 578 } // namespace system |
| 587 } // namespace mojo | 579 } // namespace mojo |
| OLD | NEW |