| OLD | NEW |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include "util/mach/mach_message_server.h" | 15 #include "util/mach/mach_message_server.h" |
| 16 | 16 |
| 17 #include <mach/mach.h> | 17 #include <mach/mach.h> |
| 18 #include <string.h> | 18 #include <string.h> |
| 19 | 19 |
| 20 #include <set> | 20 #include <set> |
| 21 | 21 |
| 22 #include "base/basictypes.h" | 22 #include "base/basictypes.h" |
| 23 #include "base/mac/scoped_mach_port.h" | 23 #include "base/mac/scoped_mach_port.h" |
| 24 #include "gtest/gtest.h" | 24 #include "gtest/gtest.h" |
| 25 #include "util/file/fd_io.h" | 25 #include "util/file/fd_io.h" |
| 26 #include "util/mach/mach_extensions.h" | 26 #include "util/mach/mach_extensions.h" |
| 27 #include "util/mach/mach_message.h" |
| 27 #include "util/test/mac/mach_errors.h" | 28 #include "util/test/mac/mach_errors.h" |
| 28 #include "util/test/mac/mach_multiprocess.h" | 29 #include "util/test/mac/mach_multiprocess.h" |
| 29 | 30 |
| 30 namespace crashpad { | 31 namespace crashpad { |
| 31 namespace test { | 32 namespace test { |
| 32 namespace { | 33 namespace { |
| 33 | 34 |
| 34 class TestMachMessageServer : public MachMessageServer::Interface, | 35 class TestMachMessageServer : public MachMessageServer::Interface, |
| 35 public MachMultiprocess { | 36 public MachMultiprocess { |
| 36 public: | 37 public: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 52 // server processes the request. The server should return | 53 // server processes the request. The server should return |
| 53 // MACH_SEND_INVALID_DEST, and the client will not expect a reply. | 54 // MACH_SEND_INVALID_DEST, and the client will not expect a reply. |
| 54 kReplyPortDead, | 55 kReplyPortDead, |
| 55 }; | 56 }; |
| 56 | 57 |
| 57 Options() | 58 Options() |
| 58 : expect_server_interface_method_called(true), | 59 : expect_server_interface_method_called(true), |
| 59 parent_wait_for_child_pipe(false), | 60 parent_wait_for_child_pipe(false), |
| 60 server_options(MACH_MSG_OPTION_NONE), | 61 server_options(MACH_MSG_OPTION_NONE), |
| 61 server_persistent(MachMessageServer::kOneShot), | 62 server_persistent(MachMessageServer::kOneShot), |
| 62 server_nonblocking(MachMessageServer::kBlocking), | |
| 63 server_receive_large(MachMessageServer::kReceiveLargeError), | 63 server_receive_large(MachMessageServer::kReceiveLargeError), |
| 64 server_timeout_ms(MACH_MSG_TIMEOUT_NONE), | 64 server_timeout_ms(kMachMessageTimeoutWaitIndefinitely), |
| 65 server_mig_retcode(KERN_SUCCESS), | 65 server_mig_retcode(KERN_SUCCESS), |
| 66 server_destroy_complex(true), | 66 server_destroy_complex(true), |
| 67 expect_server_destroyed_complex(true), | 67 expect_server_destroyed_complex(true), |
| 68 expect_server_result(KERN_SUCCESS), | 68 expect_server_result(KERN_SUCCESS), |
| 69 expect_server_transaction_count(1), | 69 expect_server_transaction_count(1), |
| 70 child_wait_for_parent_pipe_early(false), | 70 child_wait_for_parent_pipe_early(false), |
| 71 client_send_request_count(1), | 71 client_send_request_count(1), |
| 72 client_send_complex(false), | 72 client_send_complex(false), |
| 73 client_send_large(false), | 73 client_send_large(false), |
| 74 client_reply_port_type(kReplyPortNormal), | 74 client_reply_port_type(kReplyPortNormal), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 86 // be something in the server’s queue before attempting a nonblocking | 86 // be something in the server’s queue before attempting a nonblocking |
| 87 // receive if the receive is to be successful. | 87 // receive if the receive is to be successful. |
| 88 bool parent_wait_for_child_pipe; | 88 bool parent_wait_for_child_pipe; |
| 89 | 89 |
| 90 // Options to pass to MachMessageServer::Run() as the |options| parameter. | 90 // Options to pass to MachMessageServer::Run() as the |options| parameter. |
| 91 mach_msg_options_t server_options; | 91 mach_msg_options_t server_options; |
| 92 | 92 |
| 93 // Whether the server should run in one-shot or persistent mode. | 93 // Whether the server should run in one-shot or persistent mode. |
| 94 MachMessageServer::Persistent server_persistent; | 94 MachMessageServer::Persistent server_persistent; |
| 95 | 95 |
| 96 // Whether the server should run in blocking or nonblocking mode. | |
| 97 MachMessageServer::Nonblocking server_nonblocking; | |
| 98 | |
| 99 // The strategy for handling large messages. | 96 // The strategy for handling large messages. |
| 100 MachMessageServer::ReceiveLarge server_receive_large; | 97 MachMessageServer::ReceiveLarge server_receive_large; |
| 101 | 98 |
| 102 // The server’s timeout. | 99 // The server’s timeout in milliseconds, or kMachMessageTimeoutNonblocking |
| 100 // or kMachMessageTimeoutWaitIndefinitely. |
| 103 mach_msg_timeout_t server_timeout_ms; | 101 mach_msg_timeout_t server_timeout_ms; |
| 104 | 102 |
| 105 // The return code that the server returns to the client via the | 103 // The return code that the server returns to the client via the |
| 106 // mig_reply_error_t::RetCode field. A client would normally see this as | 104 // mig_reply_error_t::RetCode field. A client would normally see this as |
| 107 // a Mach RPC return value. | 105 // a Mach RPC return value. |
| 108 kern_return_t server_mig_retcode; | 106 kern_return_t server_mig_retcode; |
| 109 | 107 |
| 110 // The value that the server function should set its destroy_complex_request | 108 // The value that the server function should set its destroy_complex_request |
| 111 // parameter to. This is true if resources sent in complex request messages | 109 // parameter to. This is true if resources sent in complex request messages |
| 112 // should be destroyed, and false if they should not be destroyed, assuming | 110 // should be destroyed, and false if they should not be destroyed, assuming |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 char c; | 343 char c; |
| 346 CheckedReadFD(ReadPipeFD(), &c, 1); | 344 CheckedReadFD(ReadPipeFD(), &c, 1); |
| 347 EXPECT_EQ('\0', c); | 345 EXPECT_EQ('\0', c); |
| 348 } | 346 } |
| 349 | 347 |
| 350 ASSERT_EQ(options_.expect_server_result, | 348 ASSERT_EQ(options_.expect_server_result, |
| 351 (kr = MachMessageServer::Run(this, | 349 (kr = MachMessageServer::Run(this, |
| 352 local_port, | 350 local_port, |
| 353 options_.server_options, | 351 options_.server_options, |
| 354 options_.server_persistent, | 352 options_.server_persistent, |
| 355 options_.server_nonblocking, | |
| 356 options_.server_receive_large, | 353 options_.server_receive_large, |
| 357 options_.server_timeout_ms))) | 354 options_.server_timeout_ms))) |
| 358 << MachErrorMessage(kr, "MachMessageServer"); | 355 << MachErrorMessage(kr, "MachMessageServer"); |
| 359 | 356 |
| 360 if (options_.client_send_complex) { | 357 if (options_.client_send_complex) { |
| 361 EXPECT_NE(kMachPortNull, parent_complex_message_port_); | 358 EXPECT_NE(kMachPortNull, parent_complex_message_port_); |
| 362 mach_port_type_t type; | 359 mach_port_type_t type; |
| 363 | 360 |
| 364 if (!options_.expect_server_destroyed_complex) { | 361 if (!options_.expect_server_destroyed_complex) { |
| 365 // MachMessageServer should not have destroyed the resources sent in the | 362 // MachMessageServer should not have destroyed the resources sent in the |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 TestMachMessageServer::Options options; | 606 TestMachMessageServer::Options options; |
| 610 TestMachMessageServer test_mach_message_server(options); | 607 TestMachMessageServer test_mach_message_server(options); |
| 611 test_mach_message_server.Test(); | 608 test_mach_message_server.Test(); |
| 612 } | 609 } |
| 613 | 610 |
| 614 TEST(MachMessageServer, NonblockingNoMessage) { | 611 TEST(MachMessageServer, NonblockingNoMessage) { |
| 615 // The server waits in nonblocking mode and the client sends nothing, so the | 612 // The server waits in nonblocking mode and the client sends nothing, so the |
| 616 // server should return immediately without processing any message. | 613 // server should return immediately without processing any message. |
| 617 TestMachMessageServer::Options options; | 614 TestMachMessageServer::Options options; |
| 618 options.expect_server_interface_method_called = false; | 615 options.expect_server_interface_method_called = false; |
| 619 options.server_nonblocking = MachMessageServer::kNonblocking; | 616 options.server_timeout_ms = kMachMessageTimeoutNonblocking; |
| 620 options.expect_server_result = MACH_RCV_TIMED_OUT; | 617 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 621 options.expect_server_transaction_count = 0; | 618 options.expect_server_transaction_count = 0; |
| 622 options.client_send_request_count = 0; | 619 options.client_send_request_count = 0; |
| 623 TestMachMessageServer test_mach_message_server(options); | 620 TestMachMessageServer test_mach_message_server(options); |
| 624 test_mach_message_server.Test(); | 621 test_mach_message_server.Test(); |
| 625 } | 622 } |
| 626 | 623 |
| 627 TEST(MachMessageServer, TimeoutNoMessage) { | 624 TEST(MachMessageServer, TimeoutNoMessage) { |
| 628 // The server waits in blocking mode for one message, but with a timeout. The | 625 // The server waits in blocking mode for one message, but with a timeout. The |
| 629 // client sends no message, so the server returns after the timeout. | 626 // client sends no message, so the server returns after the timeout. |
| 630 TestMachMessageServer::Options options; | 627 TestMachMessageServer::Options options; |
| 631 options.expect_server_interface_method_called = false; | 628 options.expect_server_interface_method_called = false; |
| 632 options.server_timeout_ms = 10; | 629 options.server_timeout_ms = 10; |
| 633 options.expect_server_result = MACH_RCV_TIMED_OUT; | 630 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 634 options.expect_server_transaction_count = 0; | 631 options.expect_server_transaction_count = 0; |
| 635 options.client_send_request_count = 0; | 632 options.client_send_request_count = 0; |
| 636 TestMachMessageServer test_mach_message_server(options); | 633 TestMachMessageServer test_mach_message_server(options); |
| 637 test_mach_message_server.Test(); | 634 test_mach_message_server.Test(); |
| 638 } | 635 } |
| 639 | 636 |
| 640 TEST(MachMessageServer, Nonblocking) { | 637 TEST(MachMessageServer, Nonblocking) { |
| 641 // The client sends one message to the server and then signals the server that | 638 // The client sends one message to the server and then signals the server that |
| 642 // it’s safe to start waiting for it in nonblocking mode. The message is in | 639 // it’s safe to start waiting for it in nonblocking mode. The message is in |
| 643 // the server’s queue, so it’s able to receive it when it begins listening in | 640 // the server’s queue, so it’s able to receive it when it begins listening in |
| 644 // nonblocking mode. | 641 // nonblocking mode. |
| 645 TestMachMessageServer::Options options; | 642 TestMachMessageServer::Options options; |
| 646 options.parent_wait_for_child_pipe = true; | 643 options.parent_wait_for_child_pipe = true; |
| 647 options.server_nonblocking = MachMessageServer::kNonblocking; | 644 options.server_timeout_ms = kMachMessageTimeoutNonblocking; |
| 648 TestMachMessageServer test_mach_message_server(options); | 645 TestMachMessageServer test_mach_message_server(options); |
| 649 test_mach_message_server.Test(); | 646 test_mach_message_server.Test(); |
| 650 } | 647 } |
| 651 | 648 |
| 652 TEST(MachMessageServer, Timeout) { | 649 TEST(MachMessageServer, Timeout) { |
| 653 // The client sends one message to the server, which will wait in blocking | 650 // The client sends one message to the server, which will wait in blocking |
| 654 // mode for it up to a specific timeout. | 651 // mode for it up to a specific timeout. |
| 655 TestMachMessageServer::Options options; | 652 TestMachMessageServer::Options options; |
| 656 options.server_timeout_ms = 10; | 653 options.server_timeout_ms = 10; |
| 657 TestMachMessageServer test_mach_message_server(options); | 654 TestMachMessageServer test_mach_message_server(options); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 // child is allowed to begin sending messages, so | 688 // child is allowed to begin sending messages, so |
| 692 // child_wait_for_parent_pipe_early is used to make the child wait until the | 689 // child_wait_for_parent_pipe_early is used to make the child wait until the |
| 693 // parent is ready. | 690 // parent is ready. |
| 694 const size_t kTransactionCount = 4; | 691 const size_t kTransactionCount = 4; |
| 695 static_assert(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT, | 692 static_assert(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT, |
| 696 "must not exceed queue limit"); | 693 "must not exceed queue limit"); |
| 697 | 694 |
| 698 TestMachMessageServer::Options options; | 695 TestMachMessageServer::Options options; |
| 699 options.parent_wait_for_child_pipe = true; | 696 options.parent_wait_for_child_pipe = true; |
| 700 options.server_persistent = MachMessageServer::kPersistent; | 697 options.server_persistent = MachMessageServer::kPersistent; |
| 701 options.server_nonblocking = MachMessageServer::kNonblocking; | 698 options.server_timeout_ms = kMachMessageTimeoutNonblocking; |
| 702 options.expect_server_result = MACH_RCV_TIMED_OUT; | 699 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 703 options.expect_server_transaction_count = kTransactionCount; | 700 options.expect_server_transaction_count = kTransactionCount; |
| 704 options.child_wait_for_parent_pipe_early = true; | 701 options.child_wait_for_parent_pipe_early = true; |
| 705 options.client_send_request_count = kTransactionCount; | 702 options.client_send_request_count = kTransactionCount; |
| 706 options.child_send_all_requests_before_receiving_any_replies = true; | 703 options.child_send_all_requests_before_receiving_any_replies = true; |
| 707 TestMachMessageServer test_mach_message_server(options); | 704 TestMachMessageServer test_mach_message_server(options); |
| 708 test_mach_message_server.Test(); | 705 test_mach_message_server.Test(); |
| 709 } | 706 } |
| 710 | 707 |
| 711 TEST(MachMessageServer, ReturnCodeInvalidArgument) { | 708 TEST(MachMessageServer, ReturnCodeInvalidArgument) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 options.expect_server_transaction_count = 0; | 850 options.expect_server_transaction_count = 0; |
| 854 options.client_send_large = true; | 851 options.client_send_large = true; |
| 855 options.client_expect_reply = false; | 852 options.client_expect_reply = false; |
| 856 TestMachMessageServer test_mach_message_server(options); | 853 TestMachMessageServer test_mach_message_server(options); |
| 857 test_mach_message_server.Test(); | 854 test_mach_message_server.Test(); |
| 858 } | 855 } |
| 859 | 856 |
| 860 } // namespace | 857 } // namespace |
| 861 } // namespace test | 858 } // namespace test |
| 862 } // namespace crashpad | 859 } // namespace crashpad |
| OLD | NEW |