| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // These tests are POSIX only. | 5 // These tests are POSIX only. |
| 6 | 6 |
| 7 #include "ipc/ipc_channel_posix.h" | 7 #include "ipc/ipc_channel_posix.h" |
| 8 | 8 |
| 9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| 11 #include <stddef.h> | 11 #include <stddef.h> |
| 12 #include <stdint.h> | 12 #include <stdint.h> |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
| 15 #include <sys/un.h> | 15 #include <sys/un.h> |
| 16 #include <unistd.h> | 16 #include <unistd.h> |
| 17 | 17 |
| 18 #include <memory> | 18 #include <memory> |
| 19 | 19 |
| 20 #include "base/command_line.h" |
| 20 #include "base/files/file_path.h" | 21 #include "base/files/file_path.h" |
| 21 #include "base/files/file_util.h" | 22 #include "base/files/file_util.h" |
| 22 #include "base/location.h" | 23 #include "base/location.h" |
| 23 #include "base/path_service.h" | 24 #include "base/path_service.h" |
| 24 #include "base/posix/eintr_wrapper.h" | 25 #include "base/posix/eintr_wrapper.h" |
| 25 #include "base/process/process.h" | 26 #include "base/process/process.h" |
| 27 #include "base/rand_util.h" |
| 26 #include "base/run_loop.h" | 28 #include "base/run_loop.h" |
| 27 #include "base/single_thread_task_runner.h" | 29 #include "base/single_thread_task_runner.h" |
| 30 #include "base/strings/string_number_conversions.h" |
| 28 #include "base/test/multiprocess_test.h" | 31 #include "base/test/multiprocess_test.h" |
| 29 #include "base/test/test_timeouts.h" | 32 #include "base/test/test_timeouts.h" |
| 30 #include "build/build_config.h" | 33 #include "build/build_config.h" |
| 31 #include "ipc/ipc_listener.h" | 34 #include "ipc/ipc_listener.h" |
| 32 #include "ipc/unix_domain_socket_util.h" | 35 #include "ipc/unix_domain_socket_util.h" |
| 33 #include "testing/multiprocess_func_list.h" | 36 #include "testing/multiprocess_func_list.h" |
| 34 | 37 |
| 35 namespace { | 38 namespace { |
| 36 | 39 |
| 40 const char kSocketNameSwitch[] = "connection-socket-name"; |
| 41 |
| 37 static const uint32_t kQuitMessage = 47; | 42 static const uint32_t kQuitMessage = 47; |
| 38 | 43 |
| 39 class IPCChannelPosixTestListener : public IPC::Listener { | 44 class IPCChannelPosixTestListener : public IPC::Listener { |
| 40 public: | 45 public: |
| 41 enum STATUS { | 46 enum STATUS { |
| 42 DISCONNECTED, | 47 DISCONNECTED, |
| 43 MESSAGE_RECEIVED, | 48 MESSAGE_RECEIVED, |
| 44 CHANNEL_ERROR, | 49 CHANNEL_ERROR, |
| 45 CONNECTED, | 50 CONNECTED, |
| 46 DENIED, | 51 DENIED, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 // If |quit_only_on_message_| then the listener will only break out of | 110 // If |quit_only_on_message_| then the listener will only break out of |
| 106 // the run loop when kQuitMessage is received. | 111 // the run loop when kQuitMessage is received. |
| 107 bool quit_only_on_message_; | 112 bool quit_only_on_message_; |
| 108 }; | 113 }; |
| 109 | 114 |
| 110 class IPCChannelPosixTest : public base::MultiProcessTest { | 115 class IPCChannelPosixTest : public base::MultiProcessTest { |
| 111 public: | 116 public: |
| 112 static void SetUpSocket(IPC::ChannelHandle *handle, | 117 static void SetUpSocket(IPC::ChannelHandle *handle, |
| 113 IPC::Channel::Mode mode); | 118 IPC::Channel::Mode mode); |
| 114 static void SpinRunLoop(base::TimeDelta delay); | 119 static void SpinRunLoop(base::TimeDelta delay); |
| 115 static const std::string GetConnectionSocketName(); | |
| 116 static const std::string GetChannelDirName(); | 120 static const std::string GetChannelDirName(); |
| 121 static std::string GetClientConnectionSocketName(); |
| 122 |
| 123 const std::string& GetConnectionSocketName(); |
| 124 |
| 125 base::Process SpawnChild(const std::string& procname) { |
| 126 base::CommandLine command_line = MakeCmdLine(procname); |
| 127 command_line.AppendSwitchASCII( |
| 128 kSocketNameSwitch, GetConnectionSocketName()); |
| 129 return base::SpawnMultiProcessTestChild( |
| 130 procname, command_line, base::LaunchOptions()); |
| 131 } |
| 117 | 132 |
| 118 bool WaitForExit(base::Process& process, int* exit_code) { | 133 bool WaitForExit(base::Process& process, int* exit_code) { |
| 119 #if defined(OS_ANDROID) | 134 #if defined(OS_ANDROID) |
| 120 return AndroidWaitForChildExitWithTimeout( | 135 return AndroidWaitForChildExitWithTimeout( |
| 121 process, base::TimeDelta::Max(), exit_code); | 136 process, base::TimeDelta::Max(), exit_code); |
| 122 #else | 137 #else |
| 123 return process.WaitForExit(exit_code); | 138 return process.WaitForExit(exit_code); |
| 124 #endif // defined(OS_ANDROID) | 139 #endif // defined(OS_ANDROID) |
| 125 } | 140 } |
| 126 | 141 |
| 127 protected: | 142 protected: |
| 128 void SetUp() override; | 143 void SetUp() override; |
| 129 void TearDown() override; | 144 void TearDown() override; |
| 130 | 145 |
| 131 private: | 146 private: |
| 132 std::unique_ptr<base::MessageLoopForIO> message_loop_; | 147 std::unique_ptr<base::MessageLoopForIO> message_loop_; |
| 148 std::string socket_name_; |
| 133 }; | 149 }; |
| 134 | 150 |
| 135 const std::string IPCChannelPosixTest::GetChannelDirName() { | 151 const std::string IPCChannelPosixTest::GetChannelDirName() { |
| 136 base::FilePath tmp_dir; | 152 base::FilePath tmp_dir; |
| 137 PathService::Get(base::DIR_TEMP, &tmp_dir); | 153 PathService::Get(base::DIR_TEMP, &tmp_dir); |
| 138 return tmp_dir.value(); | 154 return tmp_dir.value(); |
| 139 } | 155 } |
| 140 | 156 |
| 141 const std::string IPCChannelPosixTest::GetConnectionSocketName() { | 157 const std::string& IPCChannelPosixTest::GetConnectionSocketName() { |
| 142 return GetChannelDirName() + "/chrome_IPCChannelPosixTest__ConnectionSocket"; | 158 if (socket_name_.empty()) { |
| 159 uint64_t id = base::RandUint64(); |
| 160 socket_name_ = GetChannelDirName() + |
| 161 "/chrome_IPCChannelPosixTest_" + |
| 162 base::HexEncode(&id, sizeof(id)); |
| 163 } |
| 164 return socket_name_; |
| 165 } |
| 166 |
| 167 std::string IPCChannelPosixTest::GetClientConnectionSocketName() { |
| 168 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(kSocketNameSwitch)); |
| 169 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 170 kSocketNameSwitch); |
| 143 } | 171 } |
| 144 | 172 |
| 145 void IPCChannelPosixTest::SetUp() { | 173 void IPCChannelPosixTest::SetUp() { |
| 146 MultiProcessTest::SetUp(); | 174 MultiProcessTest::SetUp(); |
| 147 // Construct a fresh IO Message loop for the duration of each test. | 175 // Construct a fresh IO Message loop for the duration of each test. |
| 148 message_loop_.reset(new base::MessageLoopForIO()); | 176 message_loop_.reset(new base::MessageLoopForIO()); |
| 149 } | 177 } |
| 150 | 178 |
| 151 void IPCChannelPosixTest::TearDown() { | 179 void IPCChannelPosixTest::TearDown() { |
| 152 message_loop_.reset(NULL); | 180 message_loop_.reset(NULL); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 channel->Close(); | 460 channel->Close(); |
| 433 ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized( | 461 ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized( |
| 434 connection_socket_name)); | 462 connection_socket_name)); |
| 435 unlink(chan_handle.name.c_str()); | 463 unlink(chan_handle.name.c_str()); |
| 436 } | 464 } |
| 437 | 465 |
| 438 // A long running process that connects to us | 466 // A long running process that connects to us |
| 439 MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) { | 467 MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) { |
| 440 base::MessageLoopForIO message_loop; | 468 base::MessageLoopForIO message_loop; |
| 441 IPCChannelPosixTestListener listener(true); | 469 IPCChannelPosixTestListener listener(true); |
| 442 IPC::ChannelHandle handle(IPCChannelPosixTest::GetConnectionSocketName()); | 470 IPC::ChannelHandle handle( |
| 471 IPCChannelPosixTest::GetClientConnectionSocketName()); |
| 443 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); | 472 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); |
| 444 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | 473 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( |
| 445 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); | 474 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); |
| 446 EXPECT_TRUE(channel->Connect()); | 475 EXPECT_TRUE(channel->Connect()); |
| 447 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | 476 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); |
| 448 EXPECT_EQ(IPCChannelPosixTestListener::MESSAGE_RECEIVED, listener.status()); | 477 EXPECT_EQ(IPCChannelPosixTestListener::MESSAGE_RECEIVED, listener.status()); |
| 449 return 0; | 478 return 0; |
| 450 } | 479 } |
| 451 | 480 |
| 452 // Simple external process that shouldn't be able to connect to us. | 481 // Simple external process that shouldn't be able to connect to us. |
| 453 MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) { | 482 MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) { |
| 454 base::MessageLoopForIO message_loop; | 483 base::MessageLoopForIO message_loop; |
| 455 IPCChannelPosixTestListener listener(false); | 484 IPCChannelPosixTestListener listener(false); |
| 456 IPC::ChannelHandle handle(IPCChannelPosixTest::GetConnectionSocketName()); | 485 IPC::ChannelHandle handle( |
| 486 IPCChannelPosixTest::GetClientConnectionSocketName()); |
| 457 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); | 487 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); |
| 458 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | 488 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( |
| 459 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); | 489 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); |
| 460 | 490 |
| 461 // In this case connect may succeed or fail depending on if the packet | 491 // In this case connect may succeed or fail depending on if the packet |
| 462 // actually gets sent at sendmsg. Since we never delay on send, we may not | 492 // actually gets sent at sendmsg. Since we never delay on send, we may not |
| 463 // see the error. However even if connect succeeds, eventually we will get an | 493 // see the error. However even if connect succeeds, eventually we will get an |
| 464 // error back since the channel will be closed when we attempt to read from | 494 // error back since the channel will be closed when we attempt to read from |
| 465 // it. | 495 // it. |
| 466 bool connected = channel->Connect(); | 496 bool connected = channel->Connect(); |
| 467 if (connected) { | 497 if (connected) { |
| 468 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | 498 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); |
| 469 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | 499 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); |
| 470 } else { | 500 } else { |
| 471 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); | 501 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); |
| 472 } | 502 } |
| 473 return 0; | 503 return 0; |
| 474 } | 504 } |
| 475 | 505 |
| 476 } // namespace | 506 } // namespace |
| OLD | NEW |