Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(662)

Side by Side Diff: util/mach/mach_message_server_test.cc

Issue 584293003: MachMessageServer test: deal with short receive queue lengths on 10.10 (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Rebase Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 parent_wait_for_child_pipe(false), 58 parent_wait_for_child_pipe(false),
59 server_options(MACH_MSG_OPTION_NONE), 59 server_options(MACH_MSG_OPTION_NONE),
60 server_persistent(MachMessageServer::kOneShot), 60 server_persistent(MachMessageServer::kOneShot),
61 server_nonblocking(MachMessageServer::kBlocking), 61 server_nonblocking(MachMessageServer::kBlocking),
62 server_timeout_ms(MACH_MSG_TIMEOUT_NONE), 62 server_timeout_ms(MACH_MSG_TIMEOUT_NONE),
63 server_mig_retcode(KERN_SUCCESS), 63 server_mig_retcode(KERN_SUCCESS),
64 server_destroy_complex(true), 64 server_destroy_complex(true),
65 expect_server_destroyed_complex(true), 65 expect_server_destroyed_complex(true),
66 expect_server_result(KERN_SUCCESS), 66 expect_server_result(KERN_SUCCESS),
67 expect_server_transaction_count(1), 67 expect_server_transaction_count(1),
68 child_wait_for_parent_pipe_early(false),
68 client_send_request_count(1), 69 client_send_request_count(1),
69 client_send_complex(false), 70 client_send_complex(false),
70 client_send_large(false), 71 client_send_large(false),
71 client_reply_port_type(kReplyPortNormal), 72 client_reply_port_type(kReplyPortNormal),
72 client_expect_reply(true), 73 client_expect_reply(true),
73 child_send_all_requests_before_receiving_any_replies(false), 74 child_send_all_requests_before_receiving_any_replies(false),
74 child_wait_for_parent_pipe(false) { 75 child_wait_for_parent_pipe_late(false) {
75 } 76 }
76 77
77 // true if MachMessageServerFunction() is expected to be called. 78 // true if MachMessageServerFunction() is expected to be called.
78 bool expect_server_interface_method_called; 79 bool expect_server_interface_method_called;
79 80
80 // true if the parent should wait for the child to write a byte to the pipe 81 // true if the parent should wait for the child to write a byte to the pipe
81 // as a signal that the child is ready for the parent to begin its side of 82 // as a signal that the child is ready for the parent to begin its side of
82 // the test. This is used for nonblocking tests, which require that there 83 // the test. This is used for nonblocking tests, which require that there
83 // be something in the server’s queue before attempting a nonblocking 84 // be something in the server’s queue before attempting a nonblocking
84 // receive if the receive is to be successful. 85 // receive if the receive is to be successful.
(...skipping 26 matching lines...) Expand all
111 // server_destroy_complex is false, a complex message will be destroyed if 112 // server_destroy_complex is false, a complex message will be destroyed if
112 // the MIG return code was unsuccessful. 113 // the MIG return code was unsuccessful.
113 bool expect_server_destroyed_complex; 114 bool expect_server_destroyed_complex;
114 115
115 // The expected return value from MachMessageServer::Run(). 116 // The expected return value from MachMessageServer::Run().
116 kern_return_t expect_server_result; 117 kern_return_t expect_server_result;
117 118
118 // The number of transactions that the server is expected to handle. 119 // The number of transactions that the server is expected to handle.
119 size_t expect_server_transaction_count; 120 size_t expect_server_transaction_count;
120 121
122 // true if the child should wait for the parent to signal that it’s ready
123 // for the child to begin sending requests via the pipe. This is done if the
124 // parent needs to perform operations on its receive port before the child
125 // should be permitted to send anything to it. Currently, this is used to
126 // allow the parent to ensure that the receive port’s queue length is high
127 // enough before the child begins attempting to fill it.
128 bool child_wait_for_parent_pipe_early;
129
121 // The number of requests that the client should send to the server. 130 // The number of requests that the client should send to the server.
122 size_t client_send_request_count; 131 size_t client_send_request_count;
123 132
124 // true if the client should send a complex message, one that carries a port 133 // true if the client should send a complex message, one that carries a port
125 // descriptor in its body. Normally false. 134 // descriptor in its body. Normally false.
126 bool client_send_complex; 135 bool client_send_complex;
127 136
128 // true if the client should send a larger message than the server has 137 // true if the client should send a larger message than the server has
129 // allocated space to receive. If server_options contains MACH_RCV_LARGE, 138 // allocated space to receive. If server_options contains MACH_RCV_LARGE,
130 // the server will resize its buffer to receive the message. Otherwise, the 139 // the server will resize its buffer to receive the message. Otherwise, the
(...skipping 17 matching lines...) Expand all
148 // test, which requires the client to fill the server’s queue before the 157 // test, which requires the client to fill the server’s queue before the
149 // server can attempt processing it. 158 // server can attempt processing it.
150 bool child_send_all_requests_before_receiving_any_replies; 159 bool child_send_all_requests_before_receiving_any_replies;
151 160
152 // true if the child should wait to receive a byte from the parent before 161 // true if the child should wait to receive a byte from the parent before
153 // exiting. This can be used to keep a receive right in the child alive 162 // exiting. This can be used to keep a receive right in the child alive
154 // until the parent has a chance to verify that it’s holding a send right. 163 // until the parent has a chance to verify that it’s holding a send right.
155 // Otherwise, the right might appear in the parent as a dead name if the 164 // Otherwise, the right might appear in the parent as a dead name if the
156 // child exited before the parent had a chance to examine it. This would be 165 // child exited before the parent had a chance to examine it. This would be
157 // a race. 166 // a race.
158 bool child_wait_for_parent_pipe; 167 bool child_wait_for_parent_pipe_late;
159 }; 168 };
160 169
161 explicit TestMachMessageServer(const Options& options) 170 explicit TestMachMessageServer(const Options& options)
162 : MachMessageServer::Interface(), 171 : MachMessageServer::Interface(),
163 MachMultiprocess(), 172 MachMultiprocess(),
164 options_(options), 173 options_(options),
165 child_complex_message_port_(), 174 child_complex_message_port_(),
166 parent_complex_message_port_(MACH_PORT_NULL) { 175 parent_complex_message_port_(MACH_PORT_NULL) {
167 } 176 }
168 177
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 uint8_t data[4 * PAGE_SIZE]; 299 uint8_t data[4 * PAGE_SIZE];
291 }; 300 };
292 301
293 struct ReplyMessage : public mig_reply_error_t { 302 struct ReplyMessage : public mig_reply_error_t {
294 uint32_t number; 303 uint32_t number;
295 }; 304 };
296 305
297 // MachMultiprocess: 306 // MachMultiprocess:
298 307
299 virtual void MachMultiprocessParent() override { 308 virtual void MachMultiprocessParent() override {
309 mach_port_t local_port = LocalPort();
310
311 kern_return_t kr;
312 if (options_.child_send_all_requests_before_receiving_any_replies) {
313 // On Mac OS X 10.10, the queue limit of a new Mach port seems to be 2
314 // by default, which is below the value of MACH_PORT_QLIMIT_DEFAULT. Set
315 // the port’s queue limit explicitly here.
316 mach_port_limits limits = {};
317 limits.mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT;
318 kr = mach_port_set_attributes(mach_task_self(),
319 local_port,
320 MACH_PORT_LIMITS_INFO,
321 reinterpret_cast<mach_port_info_t>(&limits),
322 MACH_PORT_LIMITS_INFO_COUNT);
323 ASSERT_EQ(KERN_SUCCESS, kr)
324 << MachErrorMessage(kr, "mach_port_set_attributes");
325 }
326
327 if (options_.child_wait_for_parent_pipe_early) {
328 // Tell the child to begin sending messages.
329 char c = '\0';
330 CheckedWriteFD(WritePipeFD(), &c, 1);
331 }
332
300 if (options_.parent_wait_for_child_pipe) { 333 if (options_.parent_wait_for_child_pipe) {
301 // Wait until the child is done sending what it’s going to send. 334 // Wait until the child is done sending what it’s going to send.
302 char c; 335 char c;
303 CheckedReadFD(ReadPipeFD(), &c, 1); 336 CheckedReadFD(ReadPipeFD(), &c, 1);
304 EXPECT_EQ('\0', c); 337 EXPECT_EQ('\0', c);
305 } 338 }
306 339
307 kern_return_t kr;
308 ASSERT_EQ(options_.expect_server_result, 340 ASSERT_EQ(options_.expect_server_result,
309 (kr = MachMessageServer::Run(this, 341 (kr = MachMessageServer::Run(this,
310 LocalPort(), 342 local_port,
311 options_.server_options, 343 options_.server_options,
312 options_.server_persistent, 344 options_.server_persistent,
313 options_.server_nonblocking, 345 options_.server_nonblocking,
314 options_.server_timeout_ms))) 346 options_.server_timeout_ms)))
315 << MachErrorMessage(kr, "MachMessageServer"); 347 << MachErrorMessage(kr, "MachMessageServer");
316 348
317 if (options_.client_send_complex) { 349 if (options_.client_send_complex) {
318 EXPECT_NE(kMachPortNull, parent_complex_message_port_); 350 EXPECT_NE(kMachPortNull, parent_complex_message_port_);
319 mach_port_type_t type; 351 mach_port_type_t type;
320 352
(...skipping 15 matching lines...) Expand all
336 // The kernel won’t have reused the same name for another Mach port in 368 // The kernel won’t have reused the same name for another Mach port in
337 // this task so soon. It’s possible that something else in this task could 369 // this task so soon. It’s possible that something else in this task could
338 // have reused the name, but it’s unlikely for that to have happened in 370 // have reused the name, but it’s unlikely for that to have happened in
339 // this test environment. 371 // this test environment.
340 kr = mach_port_type( 372 kr = mach_port_type(
341 mach_task_self(), parent_complex_message_port_, &type); 373 mach_task_self(), parent_complex_message_port_, &type);
342 EXPECT_EQ(KERN_INVALID_NAME, kr) 374 EXPECT_EQ(KERN_INVALID_NAME, kr)
343 << MachErrorMessage(kr, "mach_port_type"); 375 << MachErrorMessage(kr, "mach_port_type");
344 } 376 }
345 377
346 if (options_.child_wait_for_parent_pipe) { 378 if (options_.child_wait_for_parent_pipe_late) {
347 // Let the child know it’s safe to exit. 379 // Let the child know it’s safe to exit.
348 char c = '\0'; 380 char c = '\0';
349 CheckedWriteFD(WritePipeFD(), &c, 1); 381 CheckedWriteFD(WritePipeFD(), &c, 1);
350 } 382 }
351 } 383 }
352 384
353 virtual void MachMultiprocessChild() override { 385 virtual void MachMultiprocessChild() override {
386 if (options_.child_wait_for_parent_pipe_early) {
387 // Wait until the parent is done setting things up on its end.
388 char c;
389 CheckedReadFD(ReadPipeFD(), &c, 1);
390 EXPECT_EQ('\0', c);
391 }
392
354 for (size_t index = 0; 393 for (size_t index = 0;
355 index < options_.client_send_request_count; 394 index < options_.client_send_request_count;
356 ++index) { 395 ++index) {
357 if (options_.child_send_all_requests_before_receiving_any_replies) { 396 if (options_.child_send_all_requests_before_receiving_any_replies) {
358 // For this test, all of the messages need to go into the queue before 397 // For this test, all of the messages need to go into the queue before
359 // the parent is allowed to start processing them. Don’t attempt to 398 // the parent is allowed to start processing them. Don’t attempt to
360 // process replies before all of the requests are sent, because the 399 // process replies before all of the requests are sent, because the
361 // server won’t have sent any replies until all of the requests are in 400 // server won’t have sent any replies until all of the requests are in
362 // its queue. 401 // its queue.
363 ChildSendRequest(); 402 ChildSendRequest();
(...skipping 17 matching lines...) Expand all
381 for (size_t index = 0; 420 for (size_t index = 0;
382 index < options_.client_send_request_count; 421 index < options_.client_send_request_count;
383 ++index) { 422 ++index) {
384 ChildWaitForReply(); 423 ChildWaitForReply();
385 if (testing::Test::HasFatalFailure()) { 424 if (testing::Test::HasFatalFailure()) {
386 return; 425 return;
387 } 426 }
388 } 427 }
389 } 428 }
390 429
391 if (options_.child_wait_for_parent_pipe) { 430 if (options_.child_wait_for_parent_pipe_late) {
392 char c; 431 char c;
393 CheckedReadFD(ReadPipeFD(), &c, 1); 432 CheckedReadFD(ReadPipeFD(), &c, 1);
394 ASSERT_EQ('\0', c); 433 ASSERT_EQ('\0', c);
395 } 434 }
396 } 435 }
397 436
398 // In the child process, sends a request message to the server. 437 // In the child process, sends a request message to the server.
399 void ChildSendRequest() { 438 void ChildSendRequest() {
400 // local_receive_port_owner will the receive right that is created in this 439 // local_receive_port_owner will the receive right that is created in this
401 // scope and intended to be destroyed when leaving this scope, after it has 440 // scope and intended to be destroyed when leaving this scope, after it has
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 // that it’s safe to start waiting for them in nonblocking mode. The server 681 // that it’s safe to start waiting for them in nonblocking mode. The server
643 // then listens for them in nonblocking persistent mode, and receives all of 682 // then listens for them in nonblocking persistent mode, and receives all of
644 // them because they’ve been queued up. The client doesn’t wait for the 683 // them because they’ve been queued up. The client doesn’t wait for the
645 // replies until after it’s put all of its requests into the server’s queue. 684 // replies until after it’s put all of its requests into the server’s queue.
646 // 685 //
647 // This test is sensitive to the length of the IPC queue limit. Mach ports 686 // This test is sensitive to the length of the IPC queue limit. Mach ports
648 // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is 687 // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is
649 // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test 688 // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test
650 // must be below this, because the server does not begin dequeueing request 689 // must be below this, because the server does not begin dequeueing request
651 // messages until the client has finished sending them. 690 // messages until the client has finished sending them.
691 //
692 // The queue limit on new ports has been seen to be below
693 // MACH_PORT_QLIMIT_DEFAULT, so it will explicitly be set by
694 // mach_port_set_attributes() for this test. This needs to happen before the
695 // child is allowed to begin sending messages, so
696 // child_wait_for_parent_pipe_early is used to make the child wait until the
697 // parent is ready.
652 const size_t kTransactionCount = 4; 698 const size_t kTransactionCount = 4;
653 COMPILE_ASSERT(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT, 699 COMPILE_ASSERT(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT,
654 must_not_exceed_queue_limit); 700 must_not_exceed_queue_limit);
655 701
656 TestMachMessageServer::Options options; 702 TestMachMessageServer::Options options;
657 options.parent_wait_for_child_pipe = true; 703 options.parent_wait_for_child_pipe = true;
658 options.server_persistent = MachMessageServer::kPersistent; 704 options.server_persistent = MachMessageServer::kPersistent;
659 options.server_nonblocking = MachMessageServer::kNonblocking; 705 options.server_nonblocking = MachMessageServer::kNonblocking;
660 options.expect_server_result = MACH_RCV_TIMED_OUT; 706 options.expect_server_result = MACH_RCV_TIMED_OUT;
661 options.expect_server_transaction_count = kTransactionCount; 707 options.expect_server_transaction_count = kTransactionCount;
708 options.child_wait_for_parent_pipe_early = true;
662 options.client_send_request_count = kTransactionCount; 709 options.client_send_request_count = kTransactionCount;
663 options.child_send_all_requests_before_receiving_any_replies = true; 710 options.child_send_all_requests_before_receiving_any_replies = true;
664 TestMachMessageServer test_mach_message_server(options); 711 TestMachMessageServer test_mach_message_server(options);
665 test_mach_message_server.Test(); 712 test_mach_message_server.Test();
666 } 713 }
667 714
668 TEST(MachMessageServer, ReturnCodeInvalidArgument) { 715 TEST(MachMessageServer, ReturnCodeInvalidArgument) {
669 // This tests that the mig_reply_error_t::RetCode field is properly returned 716 // This tests that the mig_reply_error_t::RetCode field is properly returned
670 // to the client. 717 // to the client.
671 TestMachMessageServer::Options options; 718 TestMachMessageServer::Options options;
672 options.server_mig_retcode = KERN_INVALID_ARGUMENT; 719 options.server_mig_retcode = KERN_INVALID_ARGUMENT;
673 TestMachMessageServer test_mach_message_server(options); 720 TestMachMessageServer test_mach_message_server(options);
674 test_mach_message_server.Test(); 721 test_mach_message_server.Test();
675 } 722 }
676 723
677 TEST(MachMessageServer, ReturnCodeNoReply) { 724 TEST(MachMessageServer, ReturnCodeNoReply) {
678 // This tests that when mig_reply_error_t::RetCode is set to MIG_NO_REPLY, no 725 // This tests that when mig_reply_error_t::RetCode is set to MIG_NO_REPLY, no
679 // response is sent to the client. 726 // response is sent to the client.
680 TestMachMessageServer::Options options; 727 TestMachMessageServer::Options options;
681 options.server_mig_retcode = MIG_NO_REPLY; 728 options.server_mig_retcode = MIG_NO_REPLY;
682 options.client_expect_reply = false; 729 options.client_expect_reply = false;
683 options.child_wait_for_parent_pipe = true; 730 options.child_wait_for_parent_pipe_late = true;
684 TestMachMessageServer test_mach_message_server(options); 731 TestMachMessageServer test_mach_message_server(options);
685 test_mach_message_server.Test(); 732 test_mach_message_server.Test();
686 } 733 }
687 734
688 TEST(MachMessageServer, ReplyPortNull) { 735 TEST(MachMessageServer, ReplyPortNull) {
689 // The client sets its reply port to MACH_PORT_NULL. The server should see 736 // The client sets its reply port to MACH_PORT_NULL. The server should see
690 // this and avoid sending a message to the null port. No reply message is 737 // this and avoid sending a message to the null port. No reply message is
691 // sent and the server returns success. 738 // sent and the server returns success.
692 TestMachMessageServer::Options options; 739 TestMachMessageServer::Options options;
693 options.client_reply_port_type = 740 options.client_reply_port_type =
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 TEST(MachMessageServer, ComplexNotDestroyedNoReply) { 806 TEST(MachMessageServer, ComplexNotDestroyedNoReply) {
760 // As in MachMessageServer.ComplexNotDestroyed, but the server does not send 807 // As in MachMessageServer.ComplexNotDestroyed, but the server does not send
761 // a reply message and is expected to retain the send right in the server 808 // a reply message and is expected to retain the send right in the server
762 // task. 809 // task.
763 TestMachMessageServer::Options options; 810 TestMachMessageServer::Options options;
764 options.server_mig_retcode = MIG_NO_REPLY; 811 options.server_mig_retcode = MIG_NO_REPLY;
765 options.server_destroy_complex = false; 812 options.server_destroy_complex = false;
766 options.expect_server_destroyed_complex = false; 813 options.expect_server_destroyed_complex = false;
767 options.client_send_complex = true; 814 options.client_send_complex = true;
768 options.client_expect_reply = false; 815 options.client_expect_reply = false;
769 options.child_wait_for_parent_pipe = true; 816 options.child_wait_for_parent_pipe_late = true;
770 TestMachMessageServer test_mach_message_server(options); 817 TestMachMessageServer test_mach_message_server(options);
771 test_mach_message_server.Test(); 818 test_mach_message_server.Test();
772 } 819 }
773 820
774 TEST(MachMessageServer, LargeUnexpected) { 821 TEST(MachMessageServer, LargeUnexpected) {
775 // The client sends a request to the server that is larger than the server is 822 // The client sends a request to the server that is larger than the server is
776 // expecting. The server did not specify MACH_RCV_LARGE in its options, so the 823 // expecting. The server did not specify MACH_RCV_LARGE in its options, so the
777 // request is destroyed and the server returns a MACH_RCV_TOO_LARGE error. The 824 // request is destroyed and the server returns a MACH_RCV_TOO_LARGE error. The
778 // client does not receive a reply. 825 // client does not receive a reply.
779 TestMachMessageServer::Options options; 826 TestMachMessageServer::Options options;
(...skipping 11 matching lines...) Expand all
791 // so a new buffer is allocated to receive the message. The server receives 838 // so a new buffer is allocated to receive the message. The server receives
792 // the large request message, processes it, and returns a reply to the client. 839 // the large request message, processes it, and returns a reply to the client.
793 TestMachMessageServer::Options options; 840 TestMachMessageServer::Options options;
794 options.server_options = MACH_RCV_LARGE; 841 options.server_options = MACH_RCV_LARGE;
795 options.client_send_large = true; 842 options.client_send_large = true;
796 TestMachMessageServer test_mach_message_server(options); 843 TestMachMessageServer test_mach_message_server(options);
797 test_mach_message_server.Test(); 844 test_mach_message_server.Test();
798 } 845 }
799 846
800 } // namespace 847 } // namespace
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698