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 #include "build/build_config.h"
      6 
      7 #if defined(OS_WIN)
      8 #include <windows.h>
      9 #endif
     10 
     11 #include <string>
     12 
     13 #include "base/message_loop/message_loop.h"
     14 #include "base/pickle.h"
     15 #include "base/threading/thread.h"
     16 #include "ipc/ipc_message.h"
     17 #include "ipc/ipc_test_base.h"
     18 
     19 namespace {
     20 
     21 const size_t kLongMessageStringNumBytes = 50000;
     22 
     23 static void Send(IPC::Sender* sender, const char* text) {
     24   static int message_index = 0;
     25 
     26   IPC::Message* message = new IPC::Message(0,
     27                                            2,
     28                                            IPC::Message::PRIORITY_NORMAL);
     29   message->WriteInt(message_index++);
     30   message->WriteString(std::string(text));
     31 
     32   // Make sure we can handle large messages.
     33   char junk[kLongMessageStringNumBytes];
     34   memset(junk, 'a', sizeof(junk)-1);
     35   junk[sizeof(junk)-1] = 0;
     36   message->WriteString(std::string(junk));
     37 
     38   // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text);
     39   sender->Send(message);
     40 }
     41 
     42 // A generic listener that expects messages of a certain type (see
     43 // OnMessageReceived()), and either sends a generic response or quits after the
     44 // 50th message (or on channel error).
     45 class GenericChannelListener : public IPC::Listener {
     46  public:
     47   GenericChannelListener() : sender_(NULL), messages_left_(50) {}
     48   virtual ~GenericChannelListener() {}
     49 
     50   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
     51     PickleIterator iter(message);
     52 
     53     int ignored;
     54     EXPECT_TRUE(iter.ReadInt(&ignored));
     55     std::string data;
     56     EXPECT_TRUE(iter.ReadString(&data));
     57     std::string big_string;
     58     EXPECT_TRUE(iter.ReadString(&big_string));
     59     EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length());
     60 
     61     SendNextMessage();
     62     return true;
     63   }
     64 
     65   virtual void OnChannelError() OVERRIDE {
     66     // There is a race when closing the channel so the last message may be lost.
     67     EXPECT_LE(messages_left_, 1);
     68     base::MessageLoop::current()->Quit();
     69   }
     70 
     71   void Init(IPC::Sender* s) {
     72     sender_ = s;
     73   }
     74 
     75  protected:
     76   void SendNextMessage() {
     77     if (--messages_left_ <= 0)
     78       base::MessageLoop::current()->Quit();
     79     else
     80       Send(sender_, "Foo");
     81   }
     82 
     83  private:
     84   IPC::Sender* sender_;
     85   int messages_left_;
     86 };
     87 
     88 class IPCChannelTest : public IPCTestBase {
     89 };
     90 
     91 // TODO(viettrungluu): Move to a separate IPCMessageTest.
     92 TEST_F(IPCChannelTest, BasicMessageTest) {
     93   int v1 = 10;
     94   std::string v2("foobar");
     95   std::wstring v3(L"hello world");
     96 
     97   IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
     98   EXPECT_TRUE(m.WriteInt(v1));
     99   EXPECT_TRUE(m.WriteString(v2));
    100   EXPECT_TRUE(m.WriteWString(v3));
    101 
    102   PickleIterator iter(m);
    103 
    104   int vi;
    105   std::string vs;
    106   std::wstring vw;
    107 
    108   EXPECT_TRUE(m.ReadInt(&iter, &vi));
    109   EXPECT_EQ(v1, vi);
    110 
    111   EXPECT_TRUE(m.ReadString(&iter, &vs));
    112   EXPECT_EQ(v2, vs);
    113 
    114   EXPECT_TRUE(m.ReadWString(&iter, &vw));
    115   EXPECT_EQ(v3, vw);
    116 
    117   // should fail
    118   EXPECT_FALSE(m.ReadInt(&iter, &vi));
    119   EXPECT_FALSE(m.ReadString(&iter, &vs));
    120   EXPECT_FALSE(m.ReadWString(&iter, &vw));
    121 }
    122 
    123 TEST_F(IPCChannelTest, ChannelTest) {
    124   Init("GenericClient");
    125 
    126   // Set up IPC channel and start client.
    127   GenericChannelListener listener;
    128   CreateChannel(&listener);
    129   listener.Init(sender());
    130   ASSERT_TRUE(ConnectChannel());
    131   ASSERT_TRUE(StartClient());
    132 
    133   Send(sender(), "hello from parent");
    134 
    135   // Run message loop.
    136   base::MessageLoop::current()->Run();
    137 
    138   // Close the channel so the client's OnChannelError() gets fired.
    139   channel()->Close();
    140 
    141   EXPECT_TRUE(WaitForClientShutdown());
    142   DestroyChannel();
    143 }
    144 
    145 // TODO(viettrungluu): Move to a separate IPCChannelWinTest.
    146 #if defined(OS_WIN)
    147 TEST_F(IPCChannelTest, ChannelTestExistingPipe) {
    148   Init("GenericClient");
    149 
    150   // Create pipe manually using the standard Chromium name and set up IPC
    151   // channel.
    152   GenericChannelListener listener;
    153   std::string name("\\\\.\\pipe\\chrome.");
    154   name.append(GetChannelName("GenericClient"));
    155   HANDLE pipe = CreateNamedPipeA(name.c_str(),
    156                                  PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
    157                                      FILE_FLAG_FIRST_PIPE_INSTANCE,
    158                                  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
    159                                  1,
    160                                  4096,
    161                                  4096,
    162                                  5000,
    163                                  NULL);
    164   CreateChannelFromChannelHandle(IPC::ChannelHandle(pipe), &listener);
    165   CloseHandle(pipe);  // The channel duplicates the handle.
    166   listener.Init(sender());
    167 
    168   // Connect to channel and start client.
    169   ASSERT_TRUE(ConnectChannel());
    170   ASSERT_TRUE(StartClient());
    171 
    172   Send(sender(), "hello from parent");
    173 
    174   // Run message loop.
    175   base::MessageLoop::current()->Run();
    176 
    177   // Close the channel so the client's OnChannelError() gets fired.
    178   channel()->Close();
    179 
    180   EXPECT_TRUE(WaitForClientShutdown());
    181   DestroyChannel();
    182 }
    183 #endif  // defined (OS_WIN)
    184 
    185 TEST_F(IPCChannelTest, ChannelProxyTest) {
    186   Init("GenericClient");
    187 
    188   base::Thread thread("ChannelProxyTestServer");
    189   base::Thread::Options options;
    190   options.message_loop_type = base::MessageLoop::TYPE_IO;
    191   thread.StartWithOptions(options);
    192 
    193   // Set up IPC channel proxy.
    194   GenericChannelListener listener;
    195   CreateChannelProxy(&listener, thread.message_loop_proxy().get());
    196   listener.Init(sender());
    197 
    198   ASSERT_TRUE(StartClient());
    199 
    200   Send(sender(), "hello from parent");
    201 
    202   // Run message loop.
    203   base::MessageLoop::current()->Run();
    204 
    205   EXPECT_TRUE(WaitForClientShutdown());
    206 
    207   // Destroy the channel proxy before shutting down the thread.
    208   DestroyChannelProxy();
    209   thread.Stop();
    210 }
    211 
    212 class ChannelListenerWithOnConnectedSend : public GenericChannelListener {
    213  public:
    214   ChannelListenerWithOnConnectedSend() {}
    215   virtual ~ChannelListenerWithOnConnectedSend() {}
    216 
    217   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
    218     SendNextMessage();
    219   }
    220 };
    221 
    222 #if defined(OS_WIN)
    223 // Acting flakey in Windows. http://crbug.com/129595
    224 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnected
    225 #else
    226 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected
    227 #endif
    228 // This tests the case of a listener sending back an event in its
    229 // OnChannelConnected handler.
    230 TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) {
    231   Init("GenericClient");
    232 
    233   // Set up IPC channel and start client.
    234   ChannelListenerWithOnConnectedSend listener;
    235   CreateChannel(&listener);
    236   listener.Init(sender());
    237   ASSERT_TRUE(ConnectChannel());
    238   ASSERT_TRUE(StartClient());
    239 
    240   Send(sender(), "hello from parent");
    241 
    242   // Run message loop.
    243   base::MessageLoop::current()->Run();
    244 
    245   // Close the channel so the client's OnChannelError() gets fired.
    246   channel()->Close();
    247 
    248   EXPECT_TRUE(WaitForClientShutdown());
    249   DestroyChannel();
    250 }
    251 
    252 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(GenericClient) {
    253   base::MessageLoopForIO main_message_loop;
    254   GenericChannelListener listener;
    255 
    256   // Set up IPC channel.
    257   IPC::Channel channel(IPCTestBase::GetChannelName("GenericClient"),
    258                        IPC::Channel::MODE_CLIENT,
    259                        &listener);
    260   CHECK(channel.Connect());
    261   listener.Init(&channel);
    262   Send(&channel, "hello from child");
    263 
    264   base::MessageLoop::current()->Run();
    265   return 0;
    266 }
    267 
    268 }  // namespace
    269