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.
5 #include "build/build_config.h"
13 #include "base/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"
21 const size_t kLongMessageStringNumBytes
= 50000;
23 static void Send(IPC::Sender
* sender
, const char* text
) {
24 static int message_index
= 0;
26 IPC::Message
* message
= new IPC::Message(0,
28 IPC::Message::PRIORITY_NORMAL
);
29 message
->WriteInt(message_index
++);
30 message
->WriteString(std::string(text
));
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
));
38 // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text);
39 sender
->Send(message
);
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
{
47 GenericChannelListener() : sender_(NULL
), messages_left_(50) {}
48 virtual ~GenericChannelListener() {}
50 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
51 PickleIterator
iter(message
);
54 EXPECT_TRUE(iter
.ReadInt(&ignored
));
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());
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 MessageLoop::current()->Quit();
71 void Init(IPC::Sender
* s
) {
76 void SendNextMessage() {
77 if (--messages_left_
<= 0)
78 MessageLoop::current()->Quit();
88 class IPCChannelTest
: public IPCTestBase
{
91 // TODO(viettrungluu): Move to a separate IPCMessageTest.
92 TEST_F(IPCChannelTest
, BasicMessageTest
) {
94 std::string
v2("foobar");
95 std::wstring
v3(L
"hello world");
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
));
102 PickleIterator
iter(m
);
108 EXPECT_TRUE(m
.ReadInt(&iter
, &vi
));
111 EXPECT_TRUE(m
.ReadString(&iter
, &vs
));
114 EXPECT_TRUE(m
.ReadWString(&iter
, &vw
));
118 EXPECT_FALSE(m
.ReadInt(&iter
, &vi
));
119 EXPECT_FALSE(m
.ReadString(&iter
, &vs
));
120 EXPECT_FALSE(m
.ReadWString(&iter
, &vw
));
123 TEST_F(IPCChannelTest
, ChannelTest
) {
124 Init("GenericClient");
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());
133 Send(sender(), "hello from parent");
136 MessageLoop::current()->Run();
138 // Close the channel so the client's OnChannelError() gets fired.
141 EXPECT_TRUE(WaitForClientShutdown());
145 // TODO(viettrungluu): Move to a separate IPCChannelWinTest.
147 TEST_F(IPCChannelTest
, ChannelTestExistingPipe
) {
148 Init("GenericClient");
150 // Create pipe manually using the standard Chromium name and set up IPC
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
,
164 CreateChannelFromChannelHandle(IPC::ChannelHandle(pipe
), &listener
);
165 CloseHandle(pipe
); // The channel duplicates the handle.
166 listener
.Init(sender());
168 // Connect to channel and start client.
169 ASSERT_TRUE(ConnectChannel());
170 ASSERT_TRUE(StartClient());
172 Send(sender(), "hello from parent");
175 MessageLoop::current()->Run();
177 // Close the channel so the client's OnChannelError() gets fired.
180 EXPECT_TRUE(WaitForClientShutdown());
183 #endif // defined (OS_WIN)
185 TEST_F(IPCChannelTest
, ChannelProxyTest
) {
186 Init("GenericClient");
188 base::Thread
thread("ChannelProxyTestServer");
189 base::Thread::Options options
;
190 options
.message_loop_type
= MessageLoop::TYPE_IO
;
191 thread
.StartWithOptions(options
);
193 // Set up IPC channel proxy.
194 GenericChannelListener listener
;
195 CreateChannelProxy(&listener
, thread
.message_loop_proxy());
196 listener
.Init(sender());
198 ASSERT_TRUE(StartClient());
200 Send(sender(), "hello from parent");
203 MessageLoop::current()->Run();
205 EXPECT_TRUE(WaitForClientShutdown());
207 // Destroy the channel proxy before shutting down the thread.
208 DestroyChannelProxy();
212 class ChannelListenerWithOnConnectedSend
: public GenericChannelListener
{
214 ChannelListenerWithOnConnectedSend() {}
215 virtual ~ChannelListenerWithOnConnectedSend() {}
217 virtual void OnChannelConnected(int32 peer_pid
) OVERRIDE
{
223 // Acting flakey in Windows. http://crbug.com/129595
224 #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnected
226 #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected
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");
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());
240 Send(sender(), "hello from parent");
243 MessageLoop::current()->Run();
245 // Close the channel so the client's OnChannelError() gets fired.
248 EXPECT_TRUE(WaitForClientShutdown());
252 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(GenericClient
) {
253 MessageLoopForIO main_message_loop
;
254 GenericChannelListener listener
;
256 // Set up IPC channel.
257 IPC::Channel
channel(IPCTestBase::GetChannelName("GenericClient"),
258 IPC::Channel::MODE_CLIENT
,
260 CHECK(channel
.Connect());
261 listener
.Init(&channel
);
262 Send(&channel
, "hello from child");
264 MessageLoop::current()->Run();