| 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 #include "build/build_config.h" | 5 #include "build/build_config.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include <string> | 11 #include <string> |
| 12 | 12 |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/pickle.h" | 14 #include "base/pickle.h" |
| 15 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 16 #include "ipc/ipc_message.h" | 16 #include "ipc/ipc_message.h" |
| 17 #include "ipc/ipc_test_base.h" | 17 #include "ipc/ipc_test_base.h" |
| 18 #include "ipc/ipc_test_channel_listener.h" |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 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 { | 22 class IPCChannelTest : public IPCTestBase { |
| 89 }; | 23 }; |
| 90 | 24 |
| 91 // TODO(viettrungluu): Move to a separate IPCMessageTest. | 25 // TODO(viettrungluu): Move to a separate IPCMessageTest. |
| 92 TEST_F(IPCChannelTest, BasicMessageTest) { | 26 TEST_F(IPCChannelTest, BasicMessageTest) { |
| 93 int v1 = 10; | 27 int v1 = 10; |
| 94 std::string v2("foobar"); | 28 std::string v2("foobar"); |
| 95 std::wstring v3(L"hello world"); | 29 std::wstring v3(L"hello world"); |
| 96 | 30 |
| 97 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); | 31 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 117 // should fail | 51 // should fail |
| 118 EXPECT_FALSE(m.ReadInt(&iter, &vi)); | 52 EXPECT_FALSE(m.ReadInt(&iter, &vi)); |
| 119 EXPECT_FALSE(m.ReadString(&iter, &vs)); | 53 EXPECT_FALSE(m.ReadString(&iter, &vs)); |
| 120 EXPECT_FALSE(m.ReadWString(&iter, &vw)); | 54 EXPECT_FALSE(m.ReadWString(&iter, &vw)); |
| 121 } | 55 } |
| 122 | 56 |
| 123 TEST_F(IPCChannelTest, ChannelTest) { | 57 TEST_F(IPCChannelTest, ChannelTest) { |
| 124 Init("GenericClient"); | 58 Init("GenericClient"); |
| 125 | 59 |
| 126 // Set up IPC channel and start client. | 60 // Set up IPC channel and start client. |
| 127 GenericChannelListener listener; | 61 IPC::TestChannelListener listener; |
| 128 CreateChannel(&listener); | 62 CreateChannel(&listener); |
| 129 listener.Init(sender()); | 63 listener.Init(sender()); |
| 130 ASSERT_TRUE(ConnectChannel()); | 64 ASSERT_TRUE(ConnectChannel()); |
| 131 ASSERT_TRUE(StartClient()); | 65 ASSERT_TRUE(StartClient()); |
| 132 | 66 |
| 133 Send(sender(), "hello from parent"); | 67 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| 134 | 68 |
| 135 // Run message loop. | 69 // Run message loop. |
| 136 base::MessageLoop::current()->Run(); | 70 base::MessageLoop::current()->Run(); |
| 137 | 71 |
| 138 // Close the channel so the client's OnChannelError() gets fired. | 72 // Close the channel so the client's OnChannelError() gets fired. |
| 139 channel()->Close(); | 73 channel()->Close(); |
| 140 | 74 |
| 141 EXPECT_TRUE(WaitForClientShutdown()); | 75 EXPECT_TRUE(WaitForClientShutdown()); |
| 142 DestroyChannel(); | 76 DestroyChannel(); |
| 143 } | 77 } |
| 144 | 78 |
| 145 // TODO(viettrungluu): Move to a separate IPCChannelWinTest. | 79 // TODO(viettrungluu): Move to a separate IPCChannelWinTest. |
| 146 #if defined(OS_WIN) | 80 #if defined(OS_WIN) |
| 147 TEST_F(IPCChannelTest, ChannelTestExistingPipe) { | 81 TEST_F(IPCChannelTest, ChannelTestExistingPipe) { |
| 148 Init("GenericClient"); | 82 Init("GenericClient"); |
| 149 | 83 |
| 150 // Create pipe manually using the standard Chromium name and set up IPC | 84 // Create pipe manually using the standard Chromium name and set up IPC |
| 151 // channel. | 85 // channel. |
| 152 GenericChannelListener listener; | 86 IPC::TestChannelListener listener; |
| 153 std::string name("\\\\.\\pipe\\chrome."); | 87 std::string name("\\\\.\\pipe\\chrome."); |
| 154 name.append(GetChannelName("GenericClient")); | 88 name.append(GetChannelName("GenericClient")); |
| 155 HANDLE pipe = CreateNamedPipeA(name.c_str(), | 89 HANDLE pipe = CreateNamedPipeA(name.c_str(), |
| 156 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | | 90 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
| 157 FILE_FLAG_FIRST_PIPE_INSTANCE, | 91 FILE_FLAG_FIRST_PIPE_INSTANCE, |
| 158 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, | 92 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, |
| 159 1, | 93 1, |
| 160 4096, | 94 4096, |
| 161 4096, | 95 4096, |
| 162 5000, | 96 5000, |
| 163 NULL); | 97 NULL); |
| 164 CreateChannelFromChannelHandle(IPC::ChannelHandle(pipe), &listener); | 98 CreateChannelFromChannelHandle(IPC::ChannelHandle(pipe), &listener); |
| 165 CloseHandle(pipe); // The channel duplicates the handle. | 99 CloseHandle(pipe); // The channel duplicates the handle. |
| 166 listener.Init(sender()); | 100 listener.Init(sender()); |
| 167 | 101 |
| 168 // Connect to channel and start client. | 102 // Connect to channel and start client. |
| 169 ASSERT_TRUE(ConnectChannel()); | 103 ASSERT_TRUE(ConnectChannel()); |
| 170 ASSERT_TRUE(StartClient()); | 104 ASSERT_TRUE(StartClient()); |
| 171 | 105 |
| 172 Send(sender(), "hello from parent"); | 106 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| 173 | 107 |
| 174 // Run message loop. | 108 // Run message loop. |
| 175 base::MessageLoop::current()->Run(); | 109 base::MessageLoop::current()->Run(); |
| 176 | 110 |
| 177 // Close the channel so the client's OnChannelError() gets fired. | 111 // Close the channel so the client's OnChannelError() gets fired. |
| 178 channel()->Close(); | 112 channel()->Close(); |
| 179 | 113 |
| 180 EXPECT_TRUE(WaitForClientShutdown()); | 114 EXPECT_TRUE(WaitForClientShutdown()); |
| 181 DestroyChannel(); | 115 DestroyChannel(); |
| 182 } | 116 } |
| 183 #endif // defined (OS_WIN) | 117 #endif // defined (OS_WIN) |
| 184 | 118 |
| 185 TEST_F(IPCChannelTest, ChannelProxyTest) { | 119 TEST_F(IPCChannelTest, ChannelProxyTest) { |
| 186 Init("GenericClient"); | 120 Init("GenericClient"); |
| 187 | 121 |
| 188 base::Thread thread("ChannelProxyTestServer"); | 122 base::Thread thread("ChannelProxyTestServer"); |
| 189 base::Thread::Options options; | 123 base::Thread::Options options; |
| 190 options.message_loop_type = base::MessageLoop::TYPE_IO; | 124 options.message_loop_type = base::MessageLoop::TYPE_IO; |
| 191 thread.StartWithOptions(options); | 125 thread.StartWithOptions(options); |
| 192 | 126 |
| 193 // Set up IPC channel proxy. | 127 // Set up IPC channel proxy. |
| 194 GenericChannelListener listener; | 128 IPC::TestChannelListener listener; |
| 195 CreateChannelProxy(&listener, thread.message_loop_proxy().get()); | 129 CreateChannelProxy(&listener, thread.message_loop_proxy().get()); |
| 196 listener.Init(sender()); | 130 listener.Init(sender()); |
| 197 | 131 |
| 198 ASSERT_TRUE(StartClient()); | 132 ASSERT_TRUE(StartClient()); |
| 199 | 133 |
| 200 Send(sender(), "hello from parent"); | 134 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| 201 | 135 |
| 202 // Run message loop. | 136 // Run message loop. |
| 203 base::MessageLoop::current()->Run(); | 137 base::MessageLoop::current()->Run(); |
| 204 | 138 |
| 205 EXPECT_TRUE(WaitForClientShutdown()); | 139 EXPECT_TRUE(WaitForClientShutdown()); |
| 206 | 140 |
| 207 // Destroy the channel proxy before shutting down the thread. | 141 // Destroy the channel proxy before shutting down the thread. |
| 208 DestroyChannelProxy(); | 142 DestroyChannelProxy(); |
| 209 thread.Stop(); | 143 thread.Stop(); |
| 210 } | 144 } |
| 211 | 145 |
| 212 class ChannelListenerWithOnConnectedSend : public GenericChannelListener { | 146 class ChannelListenerWithOnConnectedSend : public IPC::TestChannelListener { |
| 213 public: | 147 public: |
| 214 ChannelListenerWithOnConnectedSend() {} | 148 ChannelListenerWithOnConnectedSend() {} |
| 215 virtual ~ChannelListenerWithOnConnectedSend() {} | 149 virtual ~ChannelListenerWithOnConnectedSend() {} |
| 216 | 150 |
| 217 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { | 151 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
| 218 SendNextMessage(); | 152 SendNextMessage(); |
| 219 } | 153 } |
| 220 }; | 154 }; |
| 221 | 155 |
| 222 #if defined(OS_WIN) | 156 #if defined(OS_WIN) |
| 223 // Acting flakey in Windows. http://crbug.com/129595 | 157 // Acting flakey in Windows. http://crbug.com/129595 |
| 224 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnect
ed | 158 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnect
ed |
| 225 #else | 159 #else |
| 226 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected | 160 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected |
| 227 #endif | 161 #endif |
| 228 // This tests the case of a listener sending back an event in its | 162 // This tests the case of a listener sending back an event in its |
| 229 // OnChannelConnected handler. | 163 // OnChannelConnected handler. |
| 230 TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) { | 164 TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) { |
| 231 Init("GenericClient"); | 165 Init("GenericClient"); |
| 232 | 166 |
| 233 // Set up IPC channel and start client. | 167 // Set up IPC channel and start client. |
| 234 ChannelListenerWithOnConnectedSend listener; | 168 ChannelListenerWithOnConnectedSend listener; |
| 235 CreateChannel(&listener); | 169 CreateChannel(&listener); |
| 236 listener.Init(sender()); | 170 listener.Init(sender()); |
| 237 ASSERT_TRUE(ConnectChannel()); | 171 ASSERT_TRUE(ConnectChannel()); |
| 238 ASSERT_TRUE(StartClient()); | 172 ASSERT_TRUE(StartClient()); |
| 239 | 173 |
| 240 Send(sender(), "hello from parent"); | 174 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| 241 | 175 |
| 242 // Run message loop. | 176 // Run message loop. |
| 243 base::MessageLoop::current()->Run(); | 177 base::MessageLoop::current()->Run(); |
| 244 | 178 |
| 245 // Close the channel so the client's OnChannelError() gets fired. | 179 // Close the channel so the client's OnChannelError() gets fired. |
| 246 channel()->Close(); | 180 channel()->Close(); |
| 247 | 181 |
| 248 EXPECT_TRUE(WaitForClientShutdown()); | 182 EXPECT_TRUE(WaitForClientShutdown()); |
| 249 DestroyChannel(); | 183 DestroyChannel(); |
| 250 } | 184 } |
| 251 | 185 |
| 252 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(GenericClient) { | 186 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(GenericClient) { |
| 253 base::MessageLoopForIO main_message_loop; | 187 base::MessageLoopForIO main_message_loop; |
| 254 GenericChannelListener listener; | 188 IPC::TestChannelListener listener; |
| 255 | 189 |
| 256 // Set up IPC channel. | 190 // Set up IPC channel. |
| 257 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( | 191 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( |
| 258 IPCTestBase::GetChannelName("GenericClient"), | 192 IPCTestBase::GetChannelName("GenericClient"), |
| 259 &listener)); | 193 &listener)); |
| 260 CHECK(channel->Connect()); | 194 CHECK(channel->Connect()); |
| 261 listener.Init(channel.get()); | 195 listener.Init(channel.get()); |
| 262 Send(channel.get(), "hello from child"); | 196 IPC::TestChannelListener::SendOneMessage(channel.get(), "hello from child"); |
| 263 | 197 |
| 264 base::MessageLoop::current()->Run(); | 198 base::MessageLoop::current()->Run(); |
| 265 return 0; | 199 return 0; |
| 266 } | 200 } |
| 267 | 201 |
| 268 } // namespace | 202 } // namespace |
| OLD | NEW |