| 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 #include "mojo/edk/system/message_pipe.h" | 5 #include "mojo/edk/system/message_pipe.h" |
| 6 | 6 |
| 7 #include "base/memory/ref_counted.h" | |
| 8 #include "mojo/edk/system/waiter.h" | 7 #include "mojo/edk/system/waiter.h" |
| 9 #include "mojo/edk/system/waiter_test_utils.h" | 8 #include "mojo/edk/system/waiter_test_utils.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 10 |
| 12 namespace mojo { | 11 namespace mojo { |
| 13 namespace system { | 12 namespace system { |
| 14 namespace { | 13 namespace { |
| 15 | 14 |
| 16 const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | | 15 const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | |
| 17 MOJO_HANDLE_SIGNAL_WRITABLE | | 16 MOJO_HANDLE_SIGNAL_WRITABLE | |
| 18 MOJO_HANDLE_SIGNAL_PEER_CLOSED; | 17 MOJO_HANDLE_SIGNAL_PEER_CLOSED; |
| 19 | 18 |
| 20 // Tests: | 19 // Tests: |
| 21 // - only default flags | 20 // - only default flags |
| 22 // - reading messages from a port | 21 // - reading messages from a port |
| 23 // - when there are no/one/two messages available for that port | 22 // - when there are no/one/two messages available for that port |
| 24 // - with buffer size 0 (and null buffer) -- should get size | 23 // - with buffer size 0 (and null buffer) -- should get size |
| 25 // - with too-small buffer -- should get size | 24 // - with too-small buffer -- should get size |
| 26 // - also verify that buffers aren't modified when/where they shouldn't be | 25 // - also verify that buffers aren't modified when/where they shouldn't be |
| 27 // - writing messages to a port | 26 // - writing messages to a port |
| 28 // - in the obvious scenarios (as above) | 27 // - in the obvious scenarios (as above) |
| 29 // - to a port that's been closed | 28 // - to a port that's been closed |
| 30 // - writing a message to a port, closing the other (would be the source) port, | 29 // - writing a message to a port, closing the other (would be the source) port, |
| 31 // and reading it | 30 // and reading it |
| 32 TEST(MessagePipeTest, Basic) { | 31 TEST(MessagePipeTest, Basic) { |
| 33 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 32 auto mp = MessagePipe::CreateLocalLocal(); |
| 34 | 33 |
| 35 int32_t buffer[2]; | 34 int32_t buffer[2]; |
| 36 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 35 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 37 uint32_t buffer_size; | 36 uint32_t buffer_size; |
| 38 | 37 |
| 39 // Nothing to read yet on port 0. | 38 // Nothing to read yet on port 0. |
| 40 buffer[0] = 123; | 39 buffer[0] = 123; |
| 41 buffer[1] = 456; | 40 buffer[1] = 456; |
| 42 buffer_size = kBufferSize; | 41 buffer_size = kBufferSize; |
| 43 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 42 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 buffer_size = kBufferSize; | 184 buffer_size = kBufferSize; |
| 186 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 185 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| 187 mp->ReadMessage(1, UserPointer<void>(buffer), | 186 mp->ReadMessage(1, UserPointer<void>(buffer), |
| 188 MakeUserPointer(&buffer_size), 0, nullptr, | 187 MakeUserPointer(&buffer_size), 0, nullptr, |
| 189 MOJO_READ_MESSAGE_FLAG_NONE)); | 188 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 190 | 189 |
| 191 mp->Close(1); | 190 mp->Close(1); |
| 192 } | 191 } |
| 193 | 192 |
| 194 TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) { | 193 TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) { |
| 195 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 194 auto mp = MessagePipe::CreateLocalLocal(); |
| 196 | 195 |
| 197 int32_t buffer[1]; | 196 int32_t buffer[1]; |
| 198 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 197 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 199 uint32_t buffer_size; | 198 uint32_t buffer_size; |
| 200 | 199 |
| 201 // Write some messages from port 1 (to port 0). | 200 // Write some messages from port 1 (to port 0). |
| 202 for (int32_t i = 0; i < 5; i++) { | 201 for (int32_t i = 0; i < 5; i++) { |
| 203 buffer[0] = i; | 202 buffer[0] = i; |
| 204 EXPECT_EQ(MOJO_RESULT_OK, | 203 EXPECT_EQ(MOJO_RESULT_OK, |
| 205 mp->WriteMessage(1, UserPointer<const void>(buffer), kBufferSize, | 204 mp->WriteMessage(1, UserPointer<const void>(buffer), kBufferSize, |
| 206 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 205 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 207 } | 206 } |
| 208 | 207 |
| 209 // Port 0 shouldn't be empty. | 208 // Port 0 shouldn't be empty. |
| 210 buffer_size = 0; | 209 buffer_size = 0; |
| 211 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 210 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
| 212 mp->ReadMessage(0, NullUserPointer(), MakeUserPointer(&buffer_size), | 211 mp->ReadMessage(0, NullUserPointer(), MakeUserPointer(&buffer_size), |
| 213 0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | 212 0, nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); |
| 214 EXPECT_EQ(kBufferSize, buffer_size); | 213 EXPECT_EQ(kBufferSize, buffer_size); |
| 215 | 214 |
| 216 // Close port 0 first, which should have outstanding (incoming) messages. | 215 // Close port 0 first, which should have outstanding (incoming) messages. |
| 217 mp->Close(0); | 216 mp->Close(0); |
| 218 mp->Close(1); | 217 mp->Close(1); |
| 219 } | 218 } |
| 220 | 219 |
| 221 TEST(MessagePipeTest, DiscardMode) { | 220 TEST(MessagePipeTest, DiscardMode) { |
| 222 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 221 auto mp = MessagePipe::CreateLocalLocal(); |
| 223 | 222 |
| 224 int32_t buffer[2]; | 223 int32_t buffer[2]; |
| 225 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 224 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 226 uint32_t buffer_size; | 225 uint32_t buffer_size; |
| 227 | 226 |
| 228 // Write from port 1 (to port 0). | 227 // Write from port 1 (to port 0). |
| 229 buffer[0] = 789012345; | 228 buffer[0] = 789012345; |
| 230 buffer[1] = 0; | 229 buffer[1] = 0; |
| 231 EXPECT_EQ(MOJO_RESULT_OK, | 230 EXPECT_EQ(MOJO_RESULT_OK, |
| 232 mp->WriteMessage(1, UserPointer<const void>(buffer), | 231 mp->WriteMessage(1, UserPointer<const void>(buffer), |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 315 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
| 317 mp->ReadMessage(0, UserPointer<void>(buffer), | 316 mp->ReadMessage(0, UserPointer<void>(buffer), |
| 318 MakeUserPointer(&buffer_size), 0, nullptr, | 317 MakeUserPointer(&buffer_size), 0, nullptr, |
| 319 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 318 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
| 320 | 319 |
| 321 mp->Close(0); | 320 mp->Close(0); |
| 322 mp->Close(1); | 321 mp->Close(1); |
| 323 } | 322 } |
| 324 | 323 |
| 325 TEST(MessagePipeTest, BasicWaiting) { | 324 TEST(MessagePipeTest, BasicWaiting) { |
| 326 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 325 auto mp = MessagePipe::CreateLocalLocal(); |
| 327 Waiter waiter; | 326 Waiter waiter; |
| 328 HandleSignalsState hss; | 327 HandleSignalsState hss; |
| 329 | 328 |
| 330 int32_t buffer[1]; | 329 int32_t buffer[1]; |
| 331 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 330 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 332 uint32_t buffer_size; | 331 uint32_t buffer_size; |
| 333 | 332 |
| 334 // Always writable (until the other port is closed). | 333 // Always writable (until the other port is closed). |
| 335 waiter.Init(); | 334 waiter.Init(); |
| 336 hss = HandleSignalsState(); | 335 hss = HandleSignalsState(); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 | 457 |
| 459 TEST(MessagePipeTest, ThreadedWaiting) { | 458 TEST(MessagePipeTest, ThreadedWaiting) { |
| 460 int32_t buffer[1]; | 459 int32_t buffer[1]; |
| 461 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 460 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
| 462 | 461 |
| 463 MojoResult result; | 462 MojoResult result; |
| 464 uint32_t context; | 463 uint32_t context; |
| 465 | 464 |
| 466 // Write to wake up waiter waiting for read. | 465 // Write to wake up waiter waiting for read. |
| 467 { | 466 { |
| 468 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 467 auto mp = MessagePipe::CreateLocalLocal(); |
| 469 test::SimpleWaiterThread thread(&result, &context); | 468 test::SimpleWaiterThread thread(&result, &context); |
| 470 | 469 |
| 471 thread.waiter()->Init(); | 470 thread.waiter()->Init(); |
| 472 ASSERT_EQ(MOJO_RESULT_OK, | 471 ASSERT_EQ(MOJO_RESULT_OK, |
| 473 mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, | 472 mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, |
| 474 1, nullptr)); | 473 1, nullptr)); |
| 475 thread.Start(); | 474 thread.Start(); |
| 476 | 475 |
| 477 buffer[0] = 123456789; | 476 buffer[0] = 123456789; |
| 478 // Write from port 0 (to port 1), which should wake up the waiter. | 477 // Write from port 0 (to port 1), which should wake up the waiter. |
| 479 EXPECT_EQ(MOJO_RESULT_OK, | 478 EXPECT_EQ(MOJO_RESULT_OK, |
| 480 mp->WriteMessage(0, UserPointer<const void>(buffer), kBufferSize, | 479 mp->WriteMessage(0, UserPointer<const void>(buffer), kBufferSize, |
| 481 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 480 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 482 | 481 |
| 483 HandleSignalsState hss; | 482 HandleSignalsState hss; |
| 484 mp->RemoveAwakable(1, thread.waiter(), &hss); | 483 mp->RemoveAwakable(1, thread.waiter(), &hss); |
| 485 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 484 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
| 486 hss.satisfied_signals); | 485 hss.satisfied_signals); |
| 487 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | 486 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); |
| 488 | 487 |
| 489 mp->Close(0); | 488 mp->Close(0); |
| 490 mp->Close(1); | 489 mp->Close(1); |
| 491 } // Joins |thread|. | 490 } // Joins |thread|. |
| 492 // The waiter should have woken up successfully. | 491 // The waiter should have woken up successfully. |
| 493 EXPECT_EQ(MOJO_RESULT_OK, result); | 492 EXPECT_EQ(MOJO_RESULT_OK, result); |
| 494 EXPECT_EQ(1u, context); | 493 EXPECT_EQ(1u, context); |
| 495 | 494 |
| 496 // Close to cancel waiter. | 495 // Close to cancel waiter. |
| 497 { | 496 { |
| 498 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 497 auto mp = MessagePipe::CreateLocalLocal(); |
| 499 test::SimpleWaiterThread thread(&result, &context); | 498 test::SimpleWaiterThread thread(&result, &context); |
| 500 | 499 |
| 501 thread.waiter()->Init(); | 500 thread.waiter()->Init(); |
| 502 ASSERT_EQ(MOJO_RESULT_OK, | 501 ASSERT_EQ(MOJO_RESULT_OK, |
| 503 mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, | 502 mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, |
| 504 2, nullptr)); | 503 2, nullptr)); |
| 505 thread.Start(); | 504 thread.Start(); |
| 506 | 505 |
| 507 // Close port 1 first -- this should result in the waiter being cancelled. | 506 // Close port 1 first -- this should result in the waiter being cancelled. |
| 508 mp->CancelAllAwakables(1); | 507 mp->CancelAllAwakables(1); |
| 509 mp->Close(1); | 508 mp->Close(1); |
| 510 | 509 |
| 511 // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into | 510 // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into |
| 512 // the |MessagePipe| to remove any waiter. | 511 // the |MessagePipe| to remove any waiter. |
| 513 | 512 |
| 514 mp->Close(0); | 513 mp->Close(0); |
| 515 } // Joins |thread|. | 514 } // Joins |thread|. |
| 516 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | 515 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
| 517 EXPECT_EQ(2u, context); | 516 EXPECT_EQ(2u, context); |
| 518 | 517 |
| 519 // Close to cancel waiter using peer closed signal. | 518 // Close to cancel waiter using peer closed signal. |
| 520 { | 519 { |
| 521 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 520 auto mp = MessagePipe::CreateLocalLocal(); |
| 522 test::SimpleWaiterThread thread(&result, &context); | 521 test::SimpleWaiterThread thread(&result, &context); |
| 523 | 522 |
| 524 thread.waiter()->Init(); | 523 thread.waiter()->Init(); |
| 525 ASSERT_EQ(MOJO_RESULT_OK, | 524 ASSERT_EQ(MOJO_RESULT_OK, |
| 526 mp->AddAwakable(1, thread.waiter(), | 525 mp->AddAwakable(1, thread.waiter(), |
| 527 MOJO_HANDLE_SIGNAL_PEER_CLOSED, 3, nullptr)); | 526 MOJO_HANDLE_SIGNAL_PEER_CLOSED, 3, nullptr)); |
| 528 thread.Start(); | 527 thread.Start(); |
| 529 | 528 |
| 530 // Close port 1 first -- this should result in the waiter being cancelled. | 529 // Close port 1 first -- this should result in the waiter being cancelled. |
| 531 mp->CancelAllAwakables(1); | 530 mp->CancelAllAwakables(1); |
| 532 mp->Close(1); | 531 mp->Close(1); |
| 533 | 532 |
| 534 // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into | 533 // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into |
| 535 // the |MessagePipe| to remove any waiter. | 534 // the |MessagePipe| to remove any waiter. |
| 536 | 535 |
| 537 mp->Close(0); | 536 mp->Close(0); |
| 538 } // Joins |thread|. | 537 } // Joins |thread|. |
| 539 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | 538 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
| 540 EXPECT_EQ(3u, context); | 539 EXPECT_EQ(3u, context); |
| 541 | 540 |
| 542 // Close to make waiter un-wake-up-able. | 541 // Close to make waiter un-wake-up-able. |
| 543 { | 542 { |
| 544 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 543 auto mp = MessagePipe::CreateLocalLocal(); |
| 545 test::SimpleWaiterThread thread(&result, &context); | 544 test::SimpleWaiterThread thread(&result, &context); |
| 546 | 545 |
| 547 thread.waiter()->Init(); | 546 thread.waiter()->Init(); |
| 548 ASSERT_EQ(MOJO_RESULT_OK, | 547 ASSERT_EQ(MOJO_RESULT_OK, |
| 549 mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, | 548 mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, |
| 550 4, nullptr)); | 549 4, nullptr)); |
| 551 thread.Start(); | 550 thread.Start(); |
| 552 | 551 |
| 553 // Close port 0 first -- this should wake the waiter up, since port 1 will | 552 // Close port 0 first -- this should wake the waiter up, since port 1 will |
| 554 // never be readable. | 553 // never be readable. |
| 555 mp->CancelAllAwakables(0); | 554 mp->CancelAllAwakables(0); |
| 556 mp->Close(0); | 555 mp->Close(0); |
| 557 | 556 |
| 558 HandleSignalsState hss; | 557 HandleSignalsState hss; |
| 559 mp->RemoveAwakable(1, thread.waiter(), &hss); | 558 mp->RemoveAwakable(1, thread.waiter(), &hss); |
| 560 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | 559 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |
| 561 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | 560 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |
| 562 | 561 |
| 563 mp->CancelAllAwakables(1); | 562 mp->CancelAllAwakables(1); |
| 564 mp->Close(1); | 563 mp->Close(1); |
| 565 } // Joins |thread|. | 564 } // Joins |thread|. |
| 566 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | 565 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
| 567 EXPECT_EQ(4u, context); | 566 EXPECT_EQ(4u, context); |
| 568 } | 567 } |
| 569 | 568 |
| 570 } // namespace | 569 } // namespace |
| 571 } // namespace system | 570 } // namespace system |
| 572 } // namespace mojo | 571 } // namespace mojo |
| OLD | NEW |