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

Side by Side Diff: ipc/attachment_broker_mac_unittest.cc

Issue 1465623002: ipc: Add basic memory usage tests for attachment brokering. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <mach/mach_vm.h>
8 #include <sys/mman.h> 9 #include <sys/mman.h>
9 10
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
12 #include "base/files/scoped_file.h" 13 #include "base/files/scoped_file.h"
13 #include "base/files/scoped_temp_dir.h" 14 #include "base/files/scoped_temp_dir.h"
14 #include "base/mac/mac_util.h" 15 #include "base/mac/mac_util.h"
15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/shared_memory.h" 17 #include "base/memory/shared_memory.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/synchronization/spin_wait.h"
20 #include "base/time/time.h"
17 #include "ipc/attachment_broker_messages.h" 21 #include "ipc/attachment_broker_messages.h"
18 #include "ipc/attachment_broker_privileged_mac.h" 22 #include "ipc/attachment_broker_privileged_mac.h"
19 #include "ipc/attachment_broker_unprivileged_mac.h" 23 #include "ipc/attachment_broker_unprivileged_mac.h"
20 #include "ipc/ipc_listener.h" 24 #include "ipc/ipc_listener.h"
21 #include "ipc/ipc_message.h" 25 #include "ipc/ipc_message.h"
22 #include "ipc/ipc_test_base.h" 26 #include "ipc/ipc_test_base.h"
23 #include "ipc/ipc_test_messages.h" 27 #include "ipc/ipc_test_messages.h"
24 #include "ipc/test_util_mac.h" 28 #include "ipc/test_util_mac.h"
25 29
26 namespace { 30 namespace {
27 31
28 const char kDataBuffer1[] = "This is some test data to write to the file."; 32 const char kDataBuffer1[] = "This is some test data to write to the file.";
29 const char kDataBuffer2[] = "The lazy dog and a fox."; 33 const char kDataBuffer2[] = "The lazy dog and a fox.";
30 const char kDataBuffer3[] = "Two green bears but not a potato."; 34 const char kDataBuffer3[] = "Two green bears but not a potato.";
31 const char kDataBuffer4[] = "Red potato is best potato."; 35 const char kDataBuffer4[] = "Red potato is best potato.";
32 const std::string g_service_switch_name = "service_name"; 36 const std::string g_service_switch_name = "service_name";
33 37
34 enum TestResult { 38 enum TestResult {
35 RESULT_UNKNOWN, 39 RESULT_UNKNOWN,
36 RESULT_SUCCESS, 40 RESULT_SUCCESS,
37 RESULT_FAILURE, 41 RESULT_FAILURE,
38 }; 42 };
39 43
44 mach_vm_size_t GetResidentSize() {
45 task_basic_info_64 info;
46 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
47 kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO_64,
48 reinterpret_cast<task_info_t>(&info), &count);
49 if (kr != KERN_SUCCESS)
50 LOG(FATAL) << "Couldn't get resident size.";
Mark Mentovai 2015/11/19 22:54:34 Basically just CHECK(kr == KERN_SUCCESS), or even
erikchen 2015/11/20 00:37:59 Done.
51
52 return info.resident_size;
53 }
54
40 base::mac::ScopedMachSendRight GetMachPortFromBrokeredAttachment( 55 base::mac::ScopedMachSendRight GetMachPortFromBrokeredAttachment(
41 const scoped_refptr<IPC::BrokerableAttachment>& attachment) { 56 const scoped_refptr<IPC::BrokerableAttachment>& attachment) {
42 if (attachment->GetType() != 57 if (attachment->GetType() !=
43 IPC::BrokerableAttachment::TYPE_BROKERABLE_ATTACHMENT) { 58 IPC::BrokerableAttachment::TYPE_BROKERABLE_ATTACHMENT) {
44 LOG(INFO) << "Attachment type not TYPE_BROKERABLE_ATTACHMENT."; 59 LOG(INFO) << "Attachment type not TYPE_BROKERABLE_ATTACHMENT.";
45 return base::mac::ScopedMachSendRight(MACH_PORT_NULL); 60 return base::mac::ScopedMachSendRight(MACH_PORT_NULL);
46 } 61 }
47 62
48 if (attachment->GetBrokerableType() != IPC::BrokerableAttachment::MACH_PORT) { 63 if (attachment->GetBrokerableType() != IPC::BrokerableAttachment::MACH_PORT) {
49 LOG(INFO) << "Brokerable type not MACH_PORT."; 64 LOG(INFO) << "Brokerable type not MACH_PORT.";
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 } 426 }
412 427
413 void CheckChildResult() { 428 void CheckChildResult() {
414 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, 429 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED,
415 get_proxy_listener()->get_reason()); 430 get_proxy_listener()->get_reason());
416 ASSERT_EQ(get_result_listener()->get_result(), RESULT_SUCCESS); 431 ASSERT_EQ(get_result_listener()->get_result(), RESULT_SUCCESS);
417 } 432 }
418 433
419 void FinalCleanUp() { 434 void FinalCleanUp() {
420 // There should be no leaked names. 435 // There should be no leaked names.
436 SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(
437 base::TimeDelta::FromSeconds(10),
438 active_names_at_start_ == IPC::GetActiveNameCount());
421 EXPECT_EQ(active_names_at_start_, IPC::GetActiveNameCount()); 439 EXPECT_EQ(active_names_at_start_, IPC::GetActiveNameCount());
422 440
423 // Close the channel so the client's OnChannelError() gets fired. 441 // Close the channel so the client's OnChannelError() gets fired.
424 channel()->Close(); 442 channel()->Close();
425 443
426 EXPECT_TRUE(WaitForClientShutdown()); 444 EXPECT_TRUE(WaitForClientShutdown());
427 DestroyChannel(); 445 DestroyChannel();
428 broker_.reset(); 446 broker_.reset();
429 } 447 }
430 448
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 // Channels. 492 // Channels.
475 struct ChildProcessGlobals { 493 struct ChildProcessGlobals {
476 MockPortProvider port_provider; 494 MockPortProvider port_provider;
477 495
478 // The broker must be destroyed before the port_provider, so that the broker 496 // The broker must be destroyed before the port_provider, so that the broker
479 // gets a chance to unregister itself as an observer. This doesn't matter 497 // gets a chance to unregister itself as an observer. This doesn't matter
480 // outside of tests, since neither port_provider nor broker will ever be 498 // outside of tests, since neither port_provider nor broker will ever be
481 // destroyed. 499 // destroyed.
482 scoped_ptr<IPC::AttachmentBrokerPrivilegedMac> broker; 500 scoped_ptr<IPC::AttachmentBrokerPrivilegedMac> broker;
483 base::mac::ScopedMachSendRight server_task_port; 501 base::mac::ScopedMachSendRight server_task_port;
502
503 // Total resident memory before running the message loop.
504 mach_vm_size_t initial_resident_size;
505
506 // Whether to emit log statements while processing messages.
507 bool message_logging;
484 }; 508 };
485 509
486 using OnMessageReceivedCallback = void (*)(IPC::Sender* sender, 510 using OnMessageReceivedCallback = void (*)(IPC::Sender* sender,
487 const IPC::Message& message, 511 const IPC::Message& message,
488 ChildProcessGlobals* globals); 512 ChildProcessGlobals* globals);
489 513
490 // Sets up the Mach communication ports with the server. Returns a set of 514 // Sets up the Mach communication ports with the server. Returns a set of
491 // globals that must live at least as long as the test. 515 // globals that must live at least as long as the test.
492 scoped_ptr<ChildProcessGlobals> CommonChildProcessSetUp() { 516 scoped_ptr<ChildProcessGlobals> CommonChildProcessSetUp() {
493 base::CommandLine cmd_line = *base::CommandLine::ForCurrentProcess(); 517 base::CommandLine cmd_line = *base::CommandLine::ForCurrentProcess();
494 std::string service_name = 518 std::string service_name =
495 cmd_line.GetSwitchValueASCII(g_service_switch_name); 519 cmd_line.GetSwitchValueASCII(g_service_switch_name);
496 base::mac::ScopedMachSendRight server_port( 520 base::mac::ScopedMachSendRight server_port(
497 IPC::LookupServer(service_name.c_str())); 521 IPC::LookupServer(service_name.c_str()));
498 base::mac::ScopedMachReceiveRight client_port(IPC::MakeReceivingPort()); 522 base::mac::ScopedMachReceiveRight client_port(IPC::MakeReceivingPort());
499 523
500 // Send the port that this process is listening on to the server. 524 // Send the port that this process is listening on to the server.
501 IPC::SendMachPort( 525 IPC::SendMachPort(
502 server_port.get(), client_port.get(), MACH_MSG_TYPE_MAKE_SEND); 526 server_port.get(), client_port.get(), MACH_MSG_TYPE_MAKE_SEND);
503 527
504 // Receive the task port of the server process. 528 // Receive the task port of the server process.
505 base::mac::ScopedMachSendRight server_task_port( 529 base::mac::ScopedMachSendRight server_task_port(
506 IPC::ReceiveMachPort(client_port.get())); 530 IPC::ReceiveMachPort(client_port.get()));
507 531
508 scoped_ptr<ChildProcessGlobals> globals(new ChildProcessGlobals); 532 scoped_ptr<ChildProcessGlobals> globals(new ChildProcessGlobals);
509 globals->broker.reset( 533 globals->broker.reset(
510 new IPC::AttachmentBrokerPrivilegedMac(&globals->port_provider)); 534 new IPC::AttachmentBrokerPrivilegedMac(&globals->port_provider));
511 globals->port_provider.InsertEntry(getppid(), server_task_port.get()); 535 globals->port_provider.InsertEntry(getppid(), server_task_port.get());
512 globals->server_task_port.reset(server_task_port.release()); 536 globals->server_task_port.reset(server_task_port.release());
537 globals->message_logging = true;
513 return globals; 538 return globals;
514 } 539 }
515 540
516 int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback, 541 int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback,
517 const char* channel_name) { 542 const char* channel_name) {
518 LOG(INFO) << "Privileged process start."; 543 LOG(INFO) << "Privileged process start.";
519 scoped_ptr<ChildProcessGlobals> globals(CommonChildProcessSetUp()); 544 scoped_ptr<ChildProcessGlobals> globals(CommonChildProcessSetUp());
520 545
521 mach_msg_type_number_t active_names_at_start = IPC::GetActiveNameCount(); 546 mach_msg_type_number_t active_names_at_start = IPC::GetActiveNameCount();
522 547
523 base::MessageLoopForIO main_message_loop; 548 base::MessageLoopForIO main_message_loop;
524 ProxyListener listener; 549 ProxyListener listener;
525 550
526 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( 551 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
527 IPCTestBase::GetChannelName(channel_name), &listener)); 552 IPCTestBase::GetChannelName(channel_name), &listener));
528 globals->broker->RegisterCommunicationChannel(channel.get()); 553 globals->broker->RegisterCommunicationChannel(channel.get());
529 CHECK(channel->Connect()); 554 CHECK(channel->Connect());
530 555
556 globals->initial_resident_size = GetResidentSize();
557
531 while (true) { 558 while (true) {
532 LOG(INFO) << "Privileged process spinning run loop."; 559 if (globals->message_logging)
560 LOG(INFO) << "Privileged process spinning run loop.";
533 base::MessageLoop::current()->Run(); 561 base::MessageLoop::current()->Run();
534 ProxyListener::Reason reason = listener.get_reason(); 562 ProxyListener::Reason reason = listener.get_reason();
535 if (reason == ProxyListener::CHANNEL_ERROR) 563 if (reason == ProxyListener::CHANNEL_ERROR)
536 break; 564 break;
537 565
538 while (listener.has_message()) { 566 while (listener.has_message()) {
539 LOG(INFO) << "Privileged process running callback."; 567 if (globals->message_logging)
568 LOG(INFO) << "Privileged process running callback.";
540 callback(channel.get(), listener.get_first_message(), globals.get()); 569 callback(channel.get(), listener.get_first_message(), globals.get());
541 LOG(INFO) << "Privileged process finishing callback."; 570 if (globals->message_logging)
571 LOG(INFO) << "Privileged process finishing callback.";
542 listener.pop_first_message(); 572 listener.pop_first_message();
543 } 573 }
544 } 574 }
545 575
546 if (active_names_at_start != IPC::GetActiveNameCount()) { 576 if (active_names_at_start != IPC::GetActiveNameCount()) {
547 LOG(INFO) << "Memory leak!."; 577 LOG(INFO) << "Memory leak!.";
548 } 578 }
549 LOG(INFO) << "Privileged process end."; 579 LOG(INFO) << "Privileged process end.";
550 return 0; 580 return 0;
551 } 581 }
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 globals->port_provider.InsertEntry(pid, task_port); 1175 globals->port_provider.InsertEntry(pid, task_port);
1146 } 1176 }
1147 } 1177 }
1148 1178
1149 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleToSelfDelayedPort) { 1179 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleToSelfDelayedPort) {
1150 return CommonPrivilegedProcessMain( 1180 return CommonPrivilegedProcessMain(
1151 &SendSharedMemoryHandleToSelfDelayedPortCallback, 1181 &SendSharedMemoryHandleToSelfDelayedPortCallback,
1152 "SendSharedMemoryHandleToSelfDelayedPort"); 1182 "SendSharedMemoryHandleToSelfDelayedPort");
1153 } 1183 }
1154 1184
1185 // Tests the memory usage characteristics of attachment brokering a single
1186 // large message.
1187 TEST_F(IPCAttachmentBrokerMacTest, MemoryUsageLargeMessage) {
1188 // Mach-based SharedMemory isn't support on OSX 10.6.
1189 if (base::mac::IsOSSnowLeopard())
1190 return;
1191
1192 CommonSetUp("MemoryUsageLargeMessage");
1193
1194 size_t message_size = 1024 * 1024 * 8;
1195 std::string test_string(message_size, 'a');
1196 SendMessage1(test_string);
1197 base::MessageLoop::current()->Run();
1198 CommonTearDown();
1199 }
1200
1201 void MemoryUsageLargeMessageCallback(IPC::Sender* sender,
1202 const IPC::Message& message,
1203 ChildProcessGlobals* globals) {
1204 size_t message_size = 1024 * 1024 * 8;
Mark Mentovai 2015/11/19 22:54:34 Share with message_size in the TEST_F above? Same
erikchen 2015/11/20 00:37:59 Done.
1205 EXPECT_LE(GetResidentSize(), globals->initial_resident_size + message_size);
Tom Sepez 2015/11/19 22:17:58 I worry about these kinds of tests being flakey ba
Mark Mentovai 2015/11/19 22:54:34 I don’t know if we can really strictly say that th
erikchen 2015/11/20 00:37:59 you're right, I was using message_size for two dif
1206
1207 base::SharedMemoryHandle shm(GetSharedMemoryHandleFromMsg1(message));
1208 scoped_ptr<base::SharedMemory> shared_memory(
1209 MapSharedMemoryHandle(shm, false));
1210 EXPECT_LE(GetResidentSize(), globals->initial_resident_size + message_size);
1211
1212 // Volatile prevents the compiler from optimizing out |c|.
1213 volatile char c = '\0';
1214 void* addr = shared_memory->memory();
1215 for (size_t i = 0; i < message_size; i += 1024) {
1216 c += static_cast<char*>(addr)[i];
1217 }
1218 EXPECT_GE(GetResidentSize(), globals->initial_resident_size + message_size);
1219
1220 shared_memory.reset();
1221 EXPECT_LE(GetResidentSize(), globals->initial_resident_size + message_size);
1222
1223 SendControlMessage(sender, true);
1224 }
1225
1226 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(MemoryUsageLargeMessage) {
1227 return CommonPrivilegedProcessMain(&MemoryUsageLargeMessageCallback,
1228 "MemoryUsageLargeMessage");
1229 }
1230
1231 // Tests the memory usage characteristics of attachment brokering many small
1232 // messages.
1233 TEST_F(IPCAttachmentBrokerMacTest, MemoryUsageManyMessages) {
1234 // Mach-based SharedMemory isn't support on OSX 10.6.
1235 if (base::mac::IsOSSnowLeopard())
1236 return;
1237
1238 CommonSetUp("MemoryUsageManyMessages");
1239
1240 int message_count = 1000;
1241 size_t message_size = 512 * 1024;
1242
1243 for (int i = 0; i < message_count; ++i) {
1244 std::string message = base::IntToString(i);
1245 message += '\0';
1246 size_t end = message.size();
1247 message.resize(message_size);
1248 std::fill(message.begin() + end, message.end(), 'a');
1249 SendMessage1(message);
1250
1251 base::MessageLoop::current()->RunUntilIdle();
1252 }
1253
1254 if (get_result_listener()->get_result() == RESULT_UNKNOWN)
1255 base::MessageLoop::current()->Run();
1256
1257 CommonTearDown();
1258 }
1259
1260 void MemoryUsageManyMessagesCallback(IPC::Sender* sender,
1261 const IPC::Message& message,
1262 ChildProcessGlobals* globals) {
1263 // Volatile prevents the compiler from optimizing out |c|.
1264 static volatile char c = '\0';
1265 static int message_index = 0;
1266 size_t message_size = 512 * 1024;
1267 int message_count = 1000;
1268
1269 {
1270 // Map the shared memory, and make sure that its pages are counting towards
1271 // resident size.
1272 base::SharedMemoryHandle shm(GetSharedMemoryHandleFromMsg1(message));
1273 scoped_ptr<base::SharedMemory> shared_memory(
1274 MapSharedMemoryHandle(shm, false));
1275
1276 char* addr = static_cast<char*>(shared_memory->memory());
1277 std::string message_string(addr);
1278 int message_int;
1279 ASSERT_TRUE(base::StringToInt(message_string, &message_int));
1280 ASSERT_EQ(message_index, message_int);
1281 for (size_t i = 0; i < message_size; i += 1024) {
1282 c += static_cast<char*>(addr)[i];
1283 }
1284 }
1285
1286 ++message_index;
1287
1288 if (message_index == 1) {
1289 // Disable message logging, since it significantly contributes towards total
1290 // memory usage.
1291 LOG(INFO) << "Disable privileged process message logging.";
1292 globals->message_logging = false;
1293 }
1294
1295 if (message_index == message_count) {
1296 size_t memory_increase_kb =
1297 (GetResidentSize() - globals->initial_resident_size) / 1024;
1298 LOG(INFO) << "Increase in memory usage in KB: " << memory_increase_kb;
1299
1300 // The total increase in resident size should be less than 1MB. The exact
1301 // amount is not deterministic.
1302 bool success = memory_increase_kb < 1024;
1303 SendControlMessage(sender, success);
1304 }
1305 }
1306
1307 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(MemoryUsageManyMessages) {
1308 return CommonPrivilegedProcessMain(&MemoryUsageManyMessagesCallback,
1309 "MemoryUsageManyMessages");
1310 }
1311
1155 } // namespace 1312 } // 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