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 |