1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/mac/mach_port_broker.h" 6 7 #include "base/command_line.h" 8 #include "base/synchronization/lock.h" 9 #include "base/synchronization/waitable_event.h" 10 #include "base/test/multiprocess_test.h" 11 #include "base/test/test_timeouts.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/multiprocess_func_list.h" 14 15 namespace base { 16 17 namespace { 18 const char kBootstrapPortName[] = "thisisatest"; 19 } 20 21 class MachPortBrokerTest : public testing::Test, 22 public base::PortProvider::Observer { 23 public: 24 MachPortBrokerTest() 25 : broker_(kBootstrapPortName), 26 event_(base::WaitableEvent::ResetPolicy::MANUAL, 27 base::WaitableEvent::InitialState::NOT_SIGNALED), 28 received_process_(kNullProcessHandle) { 29 broker_.AddObserver(this); 30 } 31 ~MachPortBrokerTest() override { 32 broker_.RemoveObserver(this); 33 } 34 35 // Helper function to acquire/release locks and call |PlaceholderForPid()|. 36 void AddPlaceholderForPid(base::ProcessHandle pid) { 37 base::AutoLock lock(broker_.GetLock()); 38 broker_.AddPlaceholderForPid(pid); 39 } 40 41 // Helper function to acquire/release locks and call |FinalizePid()|. 42 void FinalizePid(base::ProcessHandle pid, 43 mach_port_t task_port) { 44 base::AutoLock lock(broker_.GetLock()); 45 broker_.FinalizePid(pid, task_port); 46 } 47 48 void WaitForTaskPort() { 49 event_.Wait(); 50 } 51 52 // base::PortProvider::Observer: 53 void OnReceivedTaskPort(ProcessHandle process) override { 54 received_process_ = process; 55 event_.Signal(); 56 } 57 58 protected: 59 MachPortBroker broker_; 60 WaitableEvent event_; 61 ProcessHandle received_process_; 62 }; 63 64 TEST_F(MachPortBrokerTest, Locks) { 65 // Acquire and release the locks. Nothing bad should happen. 66 base::AutoLock lock(broker_.GetLock()); 67 } 68 69 TEST_F(MachPortBrokerTest, AddPlaceholderAndFinalize) { 70 // Add a placeholder for PID 1. 71 AddPlaceholderForPid(1); 72 EXPECT_EQ(0u, broker_.TaskForPid(1)); 73 74 // Finalize PID 1. 75 FinalizePid(1, 100u); 76 EXPECT_EQ(100u, broker_.TaskForPid(1)); 77 78 // Should be no entry for PID 2. 79 EXPECT_EQ(0u, broker_.TaskForPid(2)); 80 } 81 82 TEST_F(MachPortBrokerTest, FinalizeUnknownPid) { 83 // Finalizing an entry for an unknown pid should not add it to the map. 84 FinalizePid(1u, 100u); 85 EXPECT_EQ(0u, broker_.TaskForPid(1u)); 86 } 87 88 MULTIPROCESS_TEST_MAIN(MachPortBrokerTestChild) { 89 CHECK(base::MachPortBroker::ChildSendTaskPortToParent(kBootstrapPortName)); 90 return 0; 91 } 92 93 TEST_F(MachPortBrokerTest, ReceivePortFromChild) { 94 ASSERT_TRUE(broker_.Init()); 95 CommandLine command_line( 96 base::GetMultiProcessTestChildBaseCommandLine()); 97 broker_.GetLock().Acquire(); 98 base::Process test_child_process = base::SpawnMultiProcessTestChild( 99 "MachPortBrokerTestChild", command_line, LaunchOptions()); 100 broker_.AddPlaceholderForPid(test_child_process.Handle()); 101 broker_.GetLock().Release(); 102 103 WaitForTaskPort(); 104 EXPECT_EQ(test_child_process.Handle(), received_process_); 105 106 int rv = -1; 107 ASSERT_TRUE(test_child_process.WaitForExitWithTimeout( 108 TestTimeouts::action_timeout(), &rv)); 109 EXPECT_EQ(0, rv); 110 111 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), 112 broker_.TaskForPid(test_child_process.Handle())); 113 } 114 115 TEST_F(MachPortBrokerTest, ReceivePortFromChildWithoutAdding) { 116 ASSERT_TRUE(broker_.Init()); 117 CommandLine command_line( 118 base::GetMultiProcessTestChildBaseCommandLine()); 119 broker_.GetLock().Acquire(); 120 base::Process test_child_process = base::SpawnMultiProcessTestChild( 121 "MachPortBrokerTestChild", command_line, LaunchOptions()); 122 broker_.GetLock().Release(); 123 124 int rv = -1; 125 ASSERT_TRUE(test_child_process.WaitForExitWithTimeout( 126 TestTimeouts::action_timeout(), &rv)); 127 EXPECT_EQ(0, rv); 128 129 EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL), 130 broker_.TaskForPid(test_child_process.Handle())); 131 } 132 133 } // namespace base 134