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

Side by Side Diff: ipc/attachment_broker_mac_unittest.cc

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