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 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( 258 IPCTestBase::GetChannelName("GenericClient"), 259 &listener)); 260 CHECK(channel->Connect()); 261 listener.Init(channel.get()); 262 Send(channel.get(), "hello from child"); 263 264 base::MessageLoop::current()->Run(); 265 return 0; 266 } 267 268 } // namespace 269