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