blob: 77ae72d39e3373857a44bbcdf4d32dee455cf355 [file] [log] [blame]
[email protected]532e9bd2012-01-25 12:04:171// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]0840cc72009-11-24 16:14:532// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]22b42c592010-12-20 06:59:235#include "base/sync_socket.h"
6
[email protected]0840cc72009-11-24 16:14:537#include <stdio.h>
[email protected]0840cc72009-11-24 16:14:538#include <string>
9#include <sstream>
10
[email protected]532e9bd2012-01-25 12:04:1711#include "base/bind.h"
[email protected]2a9ec0e2013-07-17 23:00:3012#include "base/message_loop/message_loop.h"
[email protected]532e9bd2012-01-25 12:04:1713#include "base/threading/thread.h"
[email protected]0cb7d8c82013-01-11 15:13:3714#include "ipc/ipc_test_base.h"
[email protected]0840cc72009-11-24 16:14:5315#include "testing/gtest/include/gtest/gtest.h"
[email protected]0840cc72009-11-24 16:14:5316
[email protected]23f771162011-06-02 18:37:5117#if defined(OS_POSIX)
[email protected]f214f8792011-01-01 02:17:0818#include "base/file_descriptor_posix.h"
[email protected]23f771162011-06-02 18:37:5119#endif
[email protected]0840cc72009-11-24 16:14:5320
[email protected]2a3aa7b52013-01-11 20:56:2221// IPC messages for testing ----------------------------------------------------
[email protected]1d4ecf42011-08-26 21:27:3022
23#define IPC_MESSAGE_IMPL
24#include "ipc/ipc_message_macros.h"
25
26#define IPC_MESSAGE_START TestMsgStart
27
28// Message class to pass a base::SyncSocket::Handle to another process. This
29// is not as easy as it sounds, because of the differences in transferring
30// Windows HANDLEs versus posix file descriptors.
31#if defined(OS_WIN)
32IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
33#elif defined(OS_POSIX)
34IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
35#endif
36
37// Message class to pass a response to the server.
38IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
39
40// Message class to tell the server to shut down.
41IPC_MESSAGE_CONTROL0(MsgClassShutdown)
42
[email protected]2a3aa7b52013-01-11 20:56:2243// -----------------------------------------------------------------------------
[email protected]0840cc72009-11-24 16:14:5344
45namespace {
[email protected]2a3aa7b52013-01-11 20:56:2246
[email protected]0840cc72009-11-24 16:14:5347const char kHelloString[] = "Hello, SyncSocket Client";
48const size_t kHelloStringLength = arraysize(kHelloString);
[email protected]0840cc72009-11-24 16:14:5349
[email protected]0840cc72009-11-24 16:14:5350// The SyncSocket server listener class processes two sorts of
51// messages from the client.
[email protected]b7f59e822012-06-29 22:05:2652class SyncSocketServerListener : public IPC::Listener {
[email protected]0840cc72009-11-24 16:14:5353 public:
[email protected]532e9bd2012-01-25 12:04:1754 SyncSocketServerListener() : chan_(NULL) {
[email protected]0840cc72009-11-24 16:14:5355 }
56
57 void Init(IPC::Channel* chan) {
58 chan_ = chan;
59 }
60
dchengfe61fca2014-10-22 02:29:5261 bool OnMessageReceived(const IPC::Message& msg) override {
[email protected]0840cc72009-11-24 16:14:5362 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
63 IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
64 IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
65 IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
66 IPC_END_MESSAGE_MAP()
67 }
[email protected]a95986a82010-12-24 06:19:2868 return true;
[email protected]0840cc72009-11-24 16:14:5369 }
70
71 private:
72 // This sort of message is sent first, causing the transfer of
73 // the handle for the SyncSocket. This message sends a buffer
74 // on the SyncSocket and then sends a response to the client.
[email protected]182c44fa2009-11-26 00:28:0275#if defined(OS_WIN)
[email protected]0840cc72009-11-24 16:14:5376 void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
[email protected]182c44fa2009-11-26 00:28:0277 SetHandle(handle);
78 }
79#elif defined(OS_POSIX)
80 void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
81 SetHandle(fd_struct.fd);
82 }
83#else
84# error "What platform?"
85#endif // defined(OS_WIN)
86
87 void SetHandle(base::SyncSocket::Handle handle) {
[email protected]0840cc72009-11-24 16:14:5388 base::SyncSocket sync_socket(handle);
[email protected]5d272092012-04-19 10:23:0389 EXPECT_EQ(sync_socket.Send(kHelloString, kHelloStringLength),
90 kHelloStringLength);
[email protected]0840cc72009-11-24 16:14:5391 IPC::Message* msg = new MsgClassResponse(kHelloString);
[email protected]0840cc72009-11-24 16:14:5392 EXPECT_TRUE(chan_->Send(msg));
93 }
94
95 // When the client responds, it sends back a shutdown message,
96 // which causes the message loop to exit.
97 void OnMsgClassShutdown() {
[email protected]fd0a773a2013-04-30 20:55:0398 base::MessageLoop::current()->Quit();
[email protected]0840cc72009-11-24 16:14:5399 }
100
101 IPC::Channel* chan_;
102
103 DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
104};
105
[email protected]3c788582013-01-25 21:51:35106// Runs the fuzzing server child mode. Returns when the preset number of
107// messages have been received.
108MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SyncSocketServerClient) {
[email protected]fd0a773a2013-04-30 20:55:03109 base::MessageLoopForIO main_message_loop;
[email protected]0840cc72009-11-24 16:14:53110 SyncSocketServerListener listener;
[email protected]e482111a82014-05-30 03:58:59111 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
112 IPCTestBase::GetChannelName("SyncSocketServerClient"),
113 &listener));
114 EXPECT_TRUE(channel->Connect());
115 listener.Init(channel.get());
[email protected]fd0a773a2013-04-30 20:55:03116 base::MessageLoop::current()->Run();
[email protected]0840cc72009-11-24 16:14:53117 return 0;
118}
119
120// The SyncSocket client listener only processes one sort of message,
121// a response from the server.
[email protected]b7f59e822012-06-29 22:05:26122class SyncSocketClientListener : public IPC::Listener {
[email protected]0840cc72009-11-24 16:14:53123 public:
124 SyncSocketClientListener() {
125 }
126
127 void Init(base::SyncSocket* socket, IPC::Channel* chan) {
128 socket_ = socket;
129 chan_ = chan;
130 }
131
dchengfe61fca2014-10-22 02:29:52132 bool OnMessageReceived(const IPC::Message& msg) override {
[email protected]0840cc72009-11-24 16:14:53133 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
134 IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
135 IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
136 IPC_END_MESSAGE_MAP()
137 }
[email protected]a95986a82010-12-24 06:19:28138 return true;
[email protected]0840cc72009-11-24 16:14:53139 }
140
141 private:
142 // When a response is received from the server, it sends the same
143 // string as was written on the SyncSocket. These are compared
144 // and a shutdown message is sent back to the server.
145 void OnMsgClassResponse(const std::string& str) {
[email protected]d8b65912009-12-04 22:53:22146 // We rely on the order of sync_socket.Send() and chan_->Send() in
147 // the SyncSocketServerListener object.
148 EXPECT_EQ(kHelloStringLength, socket_->Peek());
[email protected]0840cc72009-11-24 16:14:53149 char buf[kHelloStringLength];
150 socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
151 EXPECT_EQ(strcmp(str.c_str(), buf), 0);
[email protected]1e1f1a72009-12-06 19:45:08152 // After receiving from the socket there should be no bytes left.
[email protected]7ee1a44c2010-07-23 14:18:59153 EXPECT_EQ(0U, socket_->Peek());
[email protected]0840cc72009-11-24 16:14:53154 IPC::Message* msg = new MsgClassShutdown();
[email protected]0840cc72009-11-24 16:14:53155 EXPECT_TRUE(chan_->Send(msg));
[email protected]fd0a773a2013-04-30 20:55:03156 base::MessageLoop::current()->Quit();
[email protected]0840cc72009-11-24 16:14:53157 }
158
159 base::SyncSocket* socket_;
160 IPC::Channel* chan_;
161
162 DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
163};
164
[email protected]0cb7d8c82013-01-11 15:13:37165class SyncSocketTest : public IPCTestBase {
[email protected]0840cc72009-11-24 16:14:53166};
167
168TEST_F(SyncSocketTest, SanityTest) {
[email protected]3c788582013-01-25 21:51:35169 Init("SyncSocketServerClient");
170
[email protected]0840cc72009-11-24 16:14:53171 SyncSocketClientListener listener;
[email protected]3c788582013-01-25 21:51:35172 CreateChannel(&listener);
173 ASSERT_TRUE(StartClient());
[email protected]0840cc72009-11-24 16:14:53174 // Create a pair of SyncSockets.
[email protected]532e9bd2012-01-25 12:04:17175 base::SyncSocket pair[2];
176 base::SyncSocket::CreatePair(&pair[0], &pair[1]);
[email protected]1e1f1a72009-12-06 19:45:08177 // Immediately after creation there should be no pending bytes.
[email protected]532e9bd2012-01-25 12:04:17178 EXPECT_EQ(0U, pair[0].Peek());
179 EXPECT_EQ(0U, pair[1].Peek());
[email protected]0840cc72009-11-24 16:14:53180 base::SyncSocket::Handle target_handle;
[email protected]182c44fa2009-11-26 00:28:02181 // Connect the channel and listener.
[email protected]3c788582013-01-25 21:51:35182 ASSERT_TRUE(ConnectChannel());
183 listener.Init(&pair[0], channel());
[email protected]0840cc72009-11-24 16:14:53184#if defined(OS_WIN)
185 // On windows we need to duplicate the handle into the server process.
[email protected]532e9bd2012-01-25 12:04:17186 BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
[email protected]3c788582013-01-25 21:51:35187 client_process(), &target_handle,
[email protected]0840cc72009-11-24 16:14:53188 0, FALSE, DUPLICATE_SAME_ACCESS);
189 EXPECT_TRUE(retval);
[email protected]0840cc72009-11-24 16:14:53190 // Set up a message to pass the handle to the server.
191 IPC::Message* msg = new MsgClassSetHandle(target_handle);
[email protected]182c44fa2009-11-26 00:28:02192#else
[email protected]532e9bd2012-01-25 12:04:17193 target_handle = pair[1].handle();
[email protected]182c44fa2009-11-26 00:28:02194 // Set up a message to pass the handle to the server.
195 base::FileDescriptor filedesc(target_handle, false);
196 IPC::Message* msg = new MsgClassSetHandle(filedesc);
197#endif // defined(OS_WIN)
[email protected]3c788582013-01-25 21:51:35198 EXPECT_TRUE(sender()->Send(msg));
[email protected]0840cc72009-11-24 16:14:53199 // Use the current thread as the I/O thread.
[email protected]fd0a773a2013-04-30 20:55:03200 base::MessageLoop::current()->Run();
[email protected]0840cc72009-11-24 16:14:53201 // Shut down.
[email protected]532e9bd2012-01-25 12:04:17202 pair[0].Close();
203 pair[1].Close();
[email protected]3c788582013-01-25 21:51:35204 EXPECT_TRUE(WaitForClientShutdown());
205 DestroyChannel();
[email protected]0840cc72009-11-24 16:14:53206}
[email protected]532e9bd2012-01-25 12:04:17207
[email protected]5d272092012-04-19 10:23:03208// A blocking read operation that will block the thread until it receives
209// |length| bytes of packets or Shutdown() is called on another thread.
210static void BlockingRead(base::SyncSocket* socket, char* buf,
211 size_t length, size_t* received) {
212 DCHECK(buf != NULL);
[email protected]532e9bd2012-01-25 12:04:17213 // Notify the parent thread that we're up and running.
214 socket->Send(kHelloString, kHelloStringLength);
[email protected]5d272092012-04-19 10:23:03215 *received = socket->Receive(buf, length);
[email protected]532e9bd2012-01-25 12:04:17216}
217
218// Tests that we can safely end a blocking Receive operation on one thread
219// from another thread by disconnecting (but not closing) the socket.
220TEST_F(SyncSocketTest, DisconnectTest) {
221 base::CancelableSyncSocket pair[2];
222 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
223
224 base::Thread worker("BlockingThread");
225 worker.Start();
226
227 // Try to do a blocking read from one of the sockets on the worker thread.
[email protected]5d272092012-04-19 10:23:03228 char buf[0xff];
[email protected]532e9bd2012-01-25 12:04:17229 size_t received = 1U; // Initialize to an unexpected value.
230 worker.message_loop()->PostTask(FROM_HERE,
[email protected]5d272092012-04-19 10:23:03231 base::Bind(&BlockingRead, &pair[0], &buf[0], arraysize(buf), &received));
[email protected]532e9bd2012-01-25 12:04:17232
233 // Wait for the worker thread to say hello.
234 char hello[kHelloStringLength] = {0};
235 pair[1].Receive(&hello[0], sizeof(hello));
[email protected]5d272092012-04-19 10:23:03236 EXPECT_EQ(0, strcmp(hello, kHelloString));
[email protected]532e9bd2012-01-25 12:04:17237 // Give the worker a chance to start Receive().
238 base::PlatformThread::YieldCurrentThread();
239
240 // Now shut down the socket that the thread is issuing a blocking read on
241 // which should cause Receive to return with an error.
242 pair[0].Shutdown();
243
244 worker.Stop();
245
246 EXPECT_EQ(0U, received);
247}
[email protected]5d272092012-04-19 10:23:03248
249// Tests that read is a blocking operation.
250TEST_F(SyncSocketTest, BlockingReceiveTest) {
251 base::CancelableSyncSocket pair[2];
252 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
253
254 base::Thread worker("BlockingThread");
255 worker.Start();
256
257 // Try to do a blocking read from one of the sockets on the worker thread.
258 char buf[kHelloStringLength] = {0};
259 size_t received = 1U; // Initialize to an unexpected value.
260 worker.message_loop()->PostTask(FROM_HERE,
261 base::Bind(&BlockingRead, &pair[0], &buf[0],
262 kHelloStringLength, &received));
263
264 // Wait for the worker thread to say hello.
265 char hello[kHelloStringLength] = {0};
266 pair[1].Receive(&hello[0], sizeof(hello));
267 EXPECT_EQ(0, strcmp(hello, kHelloString));
268 // Give the worker a chance to start Receive().
269 base::PlatformThread::YieldCurrentThread();
270
271 // Send a message to the socket on the blocking thead, it should free the
272 // socket from Receive().
273 pair[1].Send(kHelloString, kHelloStringLength);
274 worker.Stop();
275
276 // Verify the socket has received the message.
277 EXPECT_TRUE(strcmp(buf, kHelloString) == 0);
278 EXPECT_EQ(kHelloStringLength, received);
279}
280
281// Tests that the write operation is non-blocking and returns immediately
282// when there is insufficient space in the socket's buffer.
283TEST_F(SyncSocketTest, NonBlockingWriteTest) {
284 base::CancelableSyncSocket pair[2];
285 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
286
287 // Fill up the buffer for one of the socket, Send() should not block the
288 // thread even when the buffer is full.
289 while (pair[0].Send(kHelloString, kHelloStringLength) != 0) {}
290
291 // Data should be avialble on another socket.
292 size_t bytes_in_buffer = pair[1].Peek();
293 EXPECT_NE(bytes_in_buffer, 0U);
294
295 // No more data can be written to the buffer since socket has been full,
296 // verify that the amount of avialble data on another socket is unchanged.
297 EXPECT_EQ(0U, pair[0].Send(kHelloString, kHelloStringLength));
298 EXPECT_EQ(bytes_in_buffer, pair[1].Peek());
299
300 // Read from another socket to free some space for a new write.
301 char hello[kHelloStringLength] = {0};
302 pair[1].Receive(&hello[0], sizeof(hello));
303
304 // Should be able to write more data to the buffer now.
305 EXPECT_EQ(kHelloStringLength, pair[0].Send(kHelloString, kHelloStringLength));
306}
[email protected]2a3aa7b52013-01-11 20:56:22307
308} // namespace