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 |