| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // These tests are POSIX only. | |
| 6 | |
| 7 #include "ipc/ipc_channel_posix.h" | |
| 8 | |
| 9 #include <errno.h> | |
| 10 #include <fcntl.h> | |
| 11 #include <stddef.h> | |
| 12 #include <stdint.h> | |
| 13 #include <string.h> | |
| 14 #include <sys/socket.h> | |
| 15 #include <sys/un.h> | |
| 16 #include <unistd.h> | |
| 17 | |
| 18 #include <memory> | |
| 19 | |
| 20 #include "base/command_line.h" | |
| 21 #include "base/files/file_path.h" | |
| 22 #include "base/files/file_util.h" | |
| 23 #include "base/location.h" | |
| 24 #include "base/path_service.h" | |
| 25 #include "base/posix/eintr_wrapper.h" | |
| 26 #include "base/process/process.h" | |
| 27 #include "base/rand_util.h" | |
| 28 #include "base/run_loop.h" | |
| 29 #include "base/single_thread_task_runner.h" | |
| 30 #include "base/strings/string_number_conversions.h" | |
| 31 #include "base/test/multiprocess_test.h" | |
| 32 #include "base/test/test_timeouts.h" | |
| 33 #include "build/build_config.h" | |
| 34 #include "ipc/ipc_listener.h" | |
| 35 #include "ipc/unix_domain_socket_util.h" | |
| 36 #include "testing/multiprocess_func_list.h" | |
| 37 | |
| 38 namespace { | |
| 39 | |
| 40 const char kSocketNameSwitch[] = "connection-socket-name"; | |
| 41 | |
| 42 static const uint32_t kQuitMessage = 47; | |
| 43 | |
| 44 class IPCChannelPosixTestListener : public IPC::Listener { | |
| 45 public: | |
| 46 enum STATUS { | |
| 47 DISCONNECTED, | |
| 48 MESSAGE_RECEIVED, | |
| 49 CHANNEL_ERROR, | |
| 50 CONNECTED, | |
| 51 DENIED, | |
| 52 LISTEN_ERROR | |
| 53 }; | |
| 54 | |
| 55 IPCChannelPosixTestListener(bool quit_only_on_message) | |
| 56 : status_(DISCONNECTED), | |
| 57 quit_only_on_message_(quit_only_on_message) { | |
| 58 } | |
| 59 | |
| 60 ~IPCChannelPosixTestListener() override {} | |
| 61 | |
| 62 bool OnMessageReceived(const IPC::Message& message) override { | |
| 63 EXPECT_EQ(message.type(), kQuitMessage); | |
| 64 status_ = MESSAGE_RECEIVED; | |
| 65 QuitRunLoop(); | |
| 66 return true; | |
| 67 } | |
| 68 | |
| 69 void OnChannelConnected(int32_t peer_pid) override { | |
| 70 status_ = CONNECTED; | |
| 71 if (!quit_only_on_message_) { | |
| 72 QuitRunLoop(); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 void OnChannelError() override { | |
| 77 status_ = CHANNEL_ERROR; | |
| 78 QuitRunLoop(); | |
| 79 } | |
| 80 | |
| 81 void OnChannelDenied() override { | |
| 82 status_ = DENIED; | |
| 83 if (!quit_only_on_message_) { | |
| 84 QuitRunLoop(); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 void OnChannelListenError() override { | |
| 89 status_ = LISTEN_ERROR; | |
| 90 if (!quit_only_on_message_) { | |
| 91 QuitRunLoop(); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 STATUS status() { return status_; } | |
| 96 | |
| 97 void QuitRunLoop() { | |
| 98 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); | |
| 99 if (loop->is_running()) { | |
| 100 loop->QuitNow(); | |
| 101 } else { | |
| 102 // Die as soon as Run is called. | |
| 103 loop->task_runner()->PostTask(FROM_HERE, loop->QuitWhenIdleClosure()); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 private: | |
| 108 // The current status of the listener. | |
| 109 STATUS status_; | |
| 110 // If |quit_only_on_message_| then the listener will only break out of | |
| 111 // the run loop when kQuitMessage is received. | |
| 112 bool quit_only_on_message_; | |
| 113 }; | |
| 114 | |
| 115 class IPCChannelPosixTest : public base::MultiProcessTest { | |
| 116 public: | |
| 117 static void SetUpSocket(IPC::ChannelHandle *handle, | |
| 118 IPC::Channel::Mode mode); | |
| 119 static void SpinRunLoop(base::TimeDelta delay); | |
| 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 } | |
| 132 | |
| 133 bool WaitForExit(base::Process& process, int* exit_code) { | |
| 134 #if defined(OS_ANDROID) | |
| 135 return AndroidWaitForChildExitWithTimeout( | |
| 136 process, base::TimeDelta::Max(), exit_code); | |
| 137 #else | |
| 138 return process.WaitForExit(exit_code); | |
| 139 #endif // defined(OS_ANDROID) | |
| 140 } | |
| 141 | |
| 142 protected: | |
| 143 void SetUp() override; | |
| 144 void TearDown() override; | |
| 145 | |
| 146 private: | |
| 147 std::unique_ptr<base::MessageLoopForIO> message_loop_; | |
| 148 std::string socket_name_; | |
| 149 }; | |
| 150 | |
| 151 const std::string IPCChannelPosixTest::GetChannelDirName() { | |
| 152 base::FilePath tmp_dir; | |
| 153 PathService::Get(base::DIR_TEMP, &tmp_dir); | |
| 154 return tmp_dir.value(); | |
| 155 } | |
| 156 | |
| 157 const std::string& IPCChannelPosixTest::GetConnectionSocketName() { | |
| 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); | |
| 171 } | |
| 172 | |
| 173 void IPCChannelPosixTest::SetUp() { | |
| 174 MultiProcessTest::SetUp(); | |
| 175 // Construct a fresh IO Message loop for the duration of each test. | |
| 176 message_loop_.reset(new base::MessageLoopForIO()); | |
| 177 } | |
| 178 | |
| 179 void IPCChannelPosixTest::TearDown() { | |
| 180 message_loop_.reset(NULL); | |
| 181 MultiProcessTest::TearDown(); | |
| 182 } | |
| 183 | |
| 184 // Create up a socket and bind and listen to it, or connect it | |
| 185 // depending on the |mode|. | |
| 186 void IPCChannelPosixTest::SetUpSocket(IPC::ChannelHandle *handle, | |
| 187 IPC::Channel::Mode mode) { | |
| 188 const std::string& name = handle->name; | |
| 189 | |
| 190 int socket_fd = 0; | |
| 191 if (mode == IPC::Channel::MODE_NAMED_SERVER) { | |
| 192 IPC::CreateServerUnixDomainSocket(base::FilePath(name), &socket_fd); | |
| 193 } else if (mode == IPC::Channel::MODE_NAMED_CLIENT) { | |
| 194 IPC::CreateClientUnixDomainSocket(base::FilePath(name), &socket_fd); | |
| 195 } else { | |
| 196 FAIL() << "Unknown mode " << mode; | |
| 197 } | |
| 198 handle->socket.fd = socket_fd; | |
| 199 } | |
| 200 | |
| 201 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) { | |
| 202 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); | |
| 203 // Post a quit task so that this loop eventually ends and we don't hang | |
| 204 // in the case of a bad test. Usually, the run loop will quit sooner than | |
| 205 // that because all tests use a IPCChannelPosixTestListener which quits the | |
| 206 // current run loop on any channel activity. | |
| 207 loop->task_runner()->PostDelayedTask(FROM_HERE, loop->QuitWhenIdleClosure(), | |
| 208 delay); | |
| 209 base::RunLoop().Run(); | |
| 210 } | |
| 211 | |
| 212 TEST_F(IPCChannelPosixTest, BasicListen) { | |
| 213 const std::string kChannelName = | |
| 214 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen"; | |
| 215 | |
| 216 // Test creating a socket that is listening. | |
| 217 IPC::ChannelHandle handle(kChannelName); | |
| 218 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); | |
| 219 unlink(handle.name.c_str()); | |
| 220 std::unique_ptr<IPC::ChannelPosix> channel( | |
| 221 new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); | |
| 222 ASSERT_TRUE(channel->Connect()); | |
| 223 ASSERT_TRUE(channel->AcceptsConnections()); | |
| 224 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 225 channel->ResetToAcceptingConnectionState(); | |
| 226 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 227 unlink(handle.name.c_str()); | |
| 228 } | |
| 229 | |
| 230 TEST_F(IPCChannelPosixTest, BasicConnected) { | |
| 231 // Test creating a socket that is connected. | |
| 232 int pipe_fds[2]; | |
| 233 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds)); | |
| 234 std::string socket_name("/var/tmp/IPCChannelPosixTest_BasicConnected"); | |
| 235 ASSERT_GE(fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK), 0); | |
| 236 | |
| 237 base::FileDescriptor fd(pipe_fds[0], false); | |
| 238 IPC::ChannelHandle handle(socket_name, fd); | |
| 239 std::unique_ptr<IPC::ChannelPosix> channel( | |
| 240 new IPC::ChannelPosix(handle, IPC::Channel::MODE_SERVER, NULL)); | |
| 241 ASSERT_TRUE(channel->Connect()); | |
| 242 ASSERT_FALSE(channel->AcceptsConnections()); | |
| 243 channel->Close(); | |
| 244 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0); | |
| 245 | |
| 246 // Make sure that we can use the socket that is created for us by | |
| 247 // a standard channel. | |
| 248 std::unique_ptr<IPC::ChannelPosix> channel2( | |
| 249 new IPC::ChannelPosix(socket_name, IPC::Channel::MODE_SERVER, NULL)); | |
| 250 ASSERT_TRUE(channel2->Connect()); | |
| 251 ASSERT_FALSE(channel2->AcceptsConnections()); | |
| 252 } | |
| 253 | |
| 254 // If a connection closes right before a Send() call, we may end up closing | |
| 255 // the connection without notifying the listener, which can cause hangs in | |
| 256 // sync_message_filter and others. Make sure the listener is notified. | |
| 257 TEST_F(IPCChannelPosixTest, SendHangTest) { | |
| 258 IPCChannelPosixTestListener out_listener(true); | |
| 259 IPCChannelPosixTestListener in_listener(true); | |
| 260 IPC::ChannelHandle in_handle("IN"); | |
| 261 std::unique_ptr<IPC::ChannelPosix> in_chan(new IPC::ChannelPosix( | |
| 262 in_handle, IPC::Channel::MODE_SERVER, &in_listener)); | |
| 263 IPC::ChannelHandle out_handle( | |
| 264 "OUT", base::FileDescriptor(in_chan->TakeClientFileDescriptor())); | |
| 265 std::unique_ptr<IPC::ChannelPosix> out_chan(new IPC::ChannelPosix( | |
| 266 out_handle, IPC::Channel::MODE_CLIENT, &out_listener)); | |
| 267 ASSERT_TRUE(in_chan->Connect()); | |
| 268 ASSERT_TRUE(out_chan->Connect()); | |
| 269 in_chan->Close(); // simulate remote process dying at an unfortunate time. | |
| 270 // Send will fail, because it cannot write the message. | |
| 271 ASSERT_FALSE(out_chan->Send(new IPC::Message( | |
| 272 0, // routing_id | |
| 273 kQuitMessage, // message type | |
| 274 IPC::Message::PRIORITY_NORMAL))); | |
| 275 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 276 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status()); | |
| 277 } | |
| 278 | |
| 279 // If a connection closes right before a Connect() call, we may end up closing | |
| 280 // the connection without notifying the listener, which can cause hangs in | |
| 281 // sync_message_filter and others. Make sure the listener is notified. | |
| 282 TEST_F(IPCChannelPosixTest, AcceptHangTest) { | |
| 283 IPCChannelPosixTestListener out_listener(true); | |
| 284 IPCChannelPosixTestListener in_listener(true); | |
| 285 IPC::ChannelHandle in_handle("IN"); | |
| 286 std::unique_ptr<IPC::ChannelPosix> in_chan(new IPC::ChannelPosix( | |
| 287 in_handle, IPC::Channel::MODE_SERVER, &in_listener)); | |
| 288 IPC::ChannelHandle out_handle( | |
| 289 "OUT", base::FileDescriptor(in_chan->TakeClientFileDescriptor())); | |
| 290 std::unique_ptr<IPC::ChannelPosix> out_chan(new IPC::ChannelPosix( | |
| 291 out_handle, IPC::Channel::MODE_CLIENT, &out_listener)); | |
| 292 ASSERT_TRUE(in_chan->Connect()); | |
| 293 in_chan->Close(); // simulate remote process dying at an unfortunate time. | |
| 294 ASSERT_FALSE(out_chan->Connect()); | |
| 295 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 296 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status()); | |
| 297 } | |
| 298 | |
| 299 TEST_F(IPCChannelPosixTest, AdvancedConnected) { | |
| 300 // Test creating a connection to an external process. | |
| 301 IPCChannelPosixTestListener listener(false); | |
| 302 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
| 303 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | |
| 304 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
| 305 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
| 306 ASSERT_TRUE(channel->Connect()); | |
| 307 ASSERT_TRUE(channel->AcceptsConnections()); | |
| 308 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 309 | |
| 310 base::Process process = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
| 311 ASSERT_TRUE(process.IsValid()); | |
| 312 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 313 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
| 314 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
| 315 IPC::Message* message = new IPC::Message(0, // routing_id | |
| 316 kQuitMessage, // message type | |
| 317 IPC::Message::PRIORITY_NORMAL); | |
| 318 channel->Send(message); | |
| 319 SpinRunLoop(TestTimeouts::action_timeout()); | |
| 320 int exit_code = 0; | |
| 321 EXPECT_TRUE(WaitForExit(process, &exit_code)); | |
| 322 EXPECT_EQ(0, exit_code); | |
| 323 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
| 324 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 325 unlink(chan_handle.name.c_str()); | |
| 326 } | |
| 327 | |
| 328 TEST_F(IPCChannelPosixTest, ResetState) { | |
| 329 // Test creating a connection to an external process. Close the connection, | |
| 330 // but continue to listen and make sure another external process can connect | |
| 331 // to us. | |
| 332 IPCChannelPosixTestListener listener(false); | |
| 333 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
| 334 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | |
| 335 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
| 336 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
| 337 ASSERT_TRUE(channel->Connect()); | |
| 338 ASSERT_TRUE(channel->AcceptsConnections()); | |
| 339 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 340 | |
| 341 base::Process process = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
| 342 ASSERT_TRUE(process.IsValid()); | |
| 343 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 344 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
| 345 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
| 346 channel->ResetToAcceptingConnectionState(); | |
| 347 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 348 | |
| 349 base::Process process2 = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
| 350 ASSERT_TRUE(process2.IsValid()); | |
| 351 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 352 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
| 353 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
| 354 IPC::Message* message = new IPC::Message(0, // routing_id | |
| 355 kQuitMessage, // message type | |
| 356 IPC::Message::PRIORITY_NORMAL); | |
| 357 channel->Send(message); | |
| 358 SpinRunLoop(TestTimeouts::action_timeout()); | |
| 359 EXPECT_TRUE(process.Terminate(0, false)); | |
| 360 int exit_code = 0; | |
| 361 EXPECT_TRUE(WaitForExit(process2, &exit_code)); | |
| 362 EXPECT_EQ(0, exit_code); | |
| 363 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
| 364 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 365 unlink(chan_handle.name.c_str()); | |
| 366 } | |
| 367 | |
| 368 TEST_F(IPCChannelPosixTest, BadChannelName) { | |
| 369 // Test empty name | |
| 370 IPC::ChannelHandle handle(""); | |
| 371 std::unique_ptr<IPC::ChannelPosix> channel( | |
| 372 new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); | |
| 373 ASSERT_FALSE(channel->Connect()); | |
| 374 | |
| 375 // Test name that is too long. | |
| 376 const char *kTooLongName = "This_is_a_very_long_name_to_proactively_implement" | |
| 377 "client-centered_synergy_through_top-line" | |
| 378 "platforms_Phosfluorescently_disintermediate_" | |
| 379 "clicks-and-mortar_best_practices_without_" | |
| 380 "future-proof_growth_strategies_Continually" | |
| 381 "pontificate_proactive_potentialities_before" | |
| 382 "leading-edge_processes"; | |
| 383 EXPECT_GE(strlen(kTooLongName), IPC::kMaxSocketNameLength); | |
| 384 IPC::ChannelHandle handle2(kTooLongName); | |
| 385 std::unique_ptr<IPC::ChannelPosix> channel2( | |
| 386 new IPC::ChannelPosix(handle2, IPC::Channel::MODE_NAMED_SERVER, NULL)); | |
| 387 EXPECT_FALSE(channel2->Connect()); | |
| 388 } | |
| 389 | |
| 390 TEST_F(IPCChannelPosixTest, MultiConnection) { | |
| 391 // Test setting up a connection to an external process, and then have | |
| 392 // another external process attempt to connect to us. | |
| 393 IPCChannelPosixTestListener listener(false); | |
| 394 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
| 395 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | |
| 396 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
| 397 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
| 398 ASSERT_TRUE(channel->Connect()); | |
| 399 ASSERT_TRUE(channel->AcceptsConnections()); | |
| 400 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 401 | |
| 402 base::Process process = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
| 403 ASSERT_TRUE(process.IsValid()); | |
| 404 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 405 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
| 406 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
| 407 base::Process process2 = SpawnChild("IPCChannelPosixFailConnectionProc"); | |
| 408 ASSERT_TRUE(process2.IsValid()); | |
| 409 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 410 int exit_code = 0; | |
| 411 EXPECT_TRUE(WaitForExit(process2, &exit_code)); | |
| 412 EXPECT_EQ(exit_code, 0); | |
| 413 ASSERT_EQ(IPCChannelPosixTestListener::DENIED, listener.status()); | |
| 414 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
| 415 IPC::Message* message = new IPC::Message(0, // routing_id | |
| 416 kQuitMessage, // message type | |
| 417 IPC::Message::PRIORITY_NORMAL); | |
| 418 channel->Send(message); | |
| 419 SpinRunLoop(TestTimeouts::action_timeout()); | |
| 420 EXPECT_TRUE(WaitForExit(process, &exit_code)); | |
| 421 EXPECT_EQ(exit_code, 0); | |
| 422 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
| 423 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
| 424 unlink(chan_handle.name.c_str()); | |
| 425 } | |
| 426 | |
| 427 TEST_F(IPCChannelPosixTest, DoubleServer) { | |
| 428 // Test setting up two servers with the same name. | |
| 429 IPCChannelPosixTestListener listener(false); | |
| 430 IPCChannelPosixTestListener listener2(false); | |
| 431 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
| 432 std::unique_ptr<IPC::ChannelPosix> channel( | |
| 433 new IPC::ChannelPosix(chan_handle, IPC::Channel::MODE_SERVER, &listener)); | |
| 434 std::unique_ptr<IPC::ChannelPosix> channel2(new IPC::ChannelPosix( | |
| 435 chan_handle, IPC::Channel::MODE_SERVER, &listener2)); | |
| 436 ASSERT_TRUE(channel->Connect()); | |
| 437 ASSERT_FALSE(channel2->Connect()); | |
| 438 } | |
| 439 | |
| 440 TEST_F(IPCChannelPosixTest, BadMode) { | |
| 441 // Test setting up two servers with a bad mode. | |
| 442 IPCChannelPosixTestListener listener(false); | |
| 443 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
| 444 std::unique_ptr<IPC::ChannelPosix> channel( | |
| 445 new IPC::ChannelPosix(chan_handle, IPC::Channel::MODE_NONE, &listener)); | |
| 446 ASSERT_FALSE(channel->Connect()); | |
| 447 } | |
| 448 | |
| 449 TEST_F(IPCChannelPosixTest, IsNamedServerInitialized) { | |
| 450 const std::string& connection_socket_name = GetConnectionSocketName(); | |
| 451 IPCChannelPosixTestListener listener(false); | |
| 452 IPC::ChannelHandle chan_handle(connection_socket_name); | |
| 453 ASSERT_TRUE(base::DeleteFile(base::FilePath(connection_socket_name), false)); | |
| 454 ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized( | |
| 455 connection_socket_name)); | |
| 456 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
| 457 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
| 458 ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized( | |
| 459 connection_socket_name)); | |
| 460 channel->Close(); | |
| 461 ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized( | |
| 462 connection_socket_name)); | |
| 463 unlink(chan_handle.name.c_str()); | |
| 464 } | |
| 465 | |
| 466 // A long running process that connects to us | |
| 467 MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) { | |
| 468 base::MessageLoopForIO message_loop; | |
| 469 IPCChannelPosixTestListener listener(true); | |
| 470 IPC::ChannelHandle handle( | |
| 471 IPCChannelPosixTest::GetClientConnectionSocketName()); | |
| 472 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); | |
| 473 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
| 474 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); | |
| 475 EXPECT_TRUE(channel->Connect()); | |
| 476 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 477 EXPECT_EQ(IPCChannelPosixTestListener::MESSAGE_RECEIVED, listener.status()); | |
| 478 return 0; | |
| 479 } | |
| 480 | |
| 481 // Simple external process that shouldn't be able to connect to us. | |
| 482 MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) { | |
| 483 base::MessageLoopForIO message_loop; | |
| 484 IPCChannelPosixTestListener listener(false); | |
| 485 IPC::ChannelHandle handle( | |
| 486 IPCChannelPosixTest::GetClientConnectionSocketName()); | |
| 487 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); | |
| 488 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
| 489 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); | |
| 490 | |
| 491 // In this case connect may succeed or fail depending on if the packet | |
| 492 // actually gets sent at sendmsg. Since we never delay on send, we may not | |
| 493 // see the error. However even if connect succeeds, eventually we will get an | |
| 494 // error back since the channel will be closed when we attempt to read from | |
| 495 // it. | |
| 496 bool connected = channel->Connect(); | |
| 497 if (connected) { | |
| 498 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | |
| 499 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
| 500 } else { | |
| 501 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); | |
| 502 } | |
| 503 return 0; | |
| 504 } | |
| 505 | |
| 506 } // namespace | |
| OLD | NEW |