Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / ipc / sync_socket_unittest.cc
blobedda3c48508bf8c625750f279abce80df0f85c79
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 "base/sync_socket.h"
7 #include <stdio.h>
8 #include <sstream>
9 #include <string>
11 #include "base/bind.h"
12 #include "base/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/threading/thread.h"
15 #include "ipc/ipc_test_base.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 #if defined(OS_POSIX)
19 #include "base/file_descriptor_posix.h"
20 #endif
22 // IPC messages for testing ----------------------------------------------------
24 #define IPC_MESSAGE_IMPL
25 #include "ipc/ipc_message_macros.h"
27 #define IPC_MESSAGE_START TestMsgStart
29 // Message class to pass a base::SyncSocket::Handle to another process. This
30 // is not as easy as it sounds, because of the differences in transferring
31 // Windows HANDLEs versus posix file descriptors.
32 #if defined(OS_WIN)
33 IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
34 #elif defined(OS_POSIX)
35 IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
36 #endif
38 // Message class to pass a response to the server.
39 IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
41 // Message class to tell the server to shut down.
42 IPC_MESSAGE_CONTROL0(MsgClassShutdown)
44 // -----------------------------------------------------------------------------
46 namespace {
48 const char kHelloString[] = "Hello, SyncSocket Client";
49 const size_t kHelloStringLength = arraysize(kHelloString);
51 // The SyncSocket server listener class processes two sorts of
52 // messages from the client.
53 class SyncSocketServerListener : public IPC::Listener {
54 public:
55 SyncSocketServerListener() : chan_(NULL) {
58 void Init(IPC::Channel* chan) {
59 chan_ = chan;
62 bool OnMessageReceived(const IPC::Message& msg) override {
63 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
64 IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
65 IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
66 IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
67 IPC_END_MESSAGE_MAP()
69 return true;
72 private:
73 // This sort of message is sent first, causing the transfer of
74 // the handle for the SyncSocket. This message sends a buffer
75 // on the SyncSocket and then sends a response to the client.
76 #if defined(OS_WIN)
77 void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
78 SetHandle(handle);
80 #elif defined(OS_POSIX)
81 void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
82 SetHandle(fd_struct.fd);
84 #else
85 # error "What platform?"
86 #endif // defined(OS_WIN)
88 void SetHandle(base::SyncSocket::Handle handle) {
89 base::SyncSocket sync_socket(handle);
90 EXPECT_EQ(sync_socket.Send(kHelloString, kHelloStringLength),
91 kHelloStringLength);
92 IPC::Message* msg = new MsgClassResponse(kHelloString);
93 EXPECT_TRUE(chan_->Send(msg));
96 // When the client responds, it sends back a shutdown message,
97 // which causes the message loop to exit.
98 void OnMsgClassShutdown() {
99 base::MessageLoop::current()->Quit();
102 IPC::Channel* chan_;
104 DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
107 // Runs the fuzzing server child mode. Returns when the preset number of
108 // messages have been received.
109 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SyncSocketServerClient) {
110 base::MessageLoopForIO main_message_loop;
111 SyncSocketServerListener listener;
112 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
113 IPCTestBase::GetChannelName("SyncSocketServerClient"), &listener,
114 nullptr));
115 EXPECT_TRUE(channel->Connect());
116 listener.Init(channel.get());
117 base::MessageLoop::current()->Run();
118 return 0;
121 // The SyncSocket client listener only processes one sort of message,
122 // a response from the server.
123 class SyncSocketClientListener : public IPC::Listener {
124 public:
125 SyncSocketClientListener() {
128 void Init(base::SyncSocket* socket, IPC::Channel* chan) {
129 socket_ = socket;
130 chan_ = chan;
133 bool OnMessageReceived(const IPC::Message& msg) override {
134 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
135 IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
136 IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
137 IPC_END_MESSAGE_MAP()
139 return true;
142 private:
143 // When a response is received from the server, it sends the same
144 // string as was written on the SyncSocket. These are compared
145 // and a shutdown message is sent back to the server.
146 void OnMsgClassResponse(const std::string& str) {
147 // We rely on the order of sync_socket.Send() and chan_->Send() in
148 // the SyncSocketServerListener object.
149 EXPECT_EQ(kHelloStringLength, socket_->Peek());
150 char buf[kHelloStringLength];
151 socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
152 EXPECT_EQ(strcmp(str.c_str(), buf), 0);
153 // After receiving from the socket there should be no bytes left.
154 EXPECT_EQ(0U, socket_->Peek());
155 IPC::Message* msg = new MsgClassShutdown();
156 EXPECT_TRUE(chan_->Send(msg));
157 base::MessageLoop::current()->Quit();
160 base::SyncSocket* socket_;
161 IPC::Channel* chan_;
163 DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
166 class SyncSocketTest : public IPCTestBase {
169 #if defined(OS_ANDROID)
170 #define MAYBE_SanityTest DISABLED_SanityTest
171 #else
172 #define MAYBE_SanityTest SanityTest
173 #endif
174 TEST_F(SyncSocketTest, MAYBE_SanityTest) {
175 Init("SyncSocketServerClient");
177 SyncSocketClientListener listener;
178 CreateChannel(&listener);
179 ASSERT_TRUE(StartClient());
180 // Create a pair of SyncSockets.
181 base::SyncSocket pair[2];
182 base::SyncSocket::CreatePair(&pair[0], &pair[1]);
183 // Immediately after creation there should be no pending bytes.
184 EXPECT_EQ(0U, pair[0].Peek());
185 EXPECT_EQ(0U, pair[1].Peek());
186 base::SyncSocket::Handle target_handle;
187 // Connect the channel and listener.
188 ASSERT_TRUE(ConnectChannel());
189 listener.Init(&pair[0], channel());
190 #if defined(OS_WIN)
191 // On windows we need to duplicate the handle into the server process.
192 BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
193 client_process().Handle(), &target_handle,
194 0, FALSE, DUPLICATE_SAME_ACCESS);
195 EXPECT_TRUE(retval);
196 // Set up a message to pass the handle to the server.
197 IPC::Message* msg = new MsgClassSetHandle(target_handle);
198 #else
199 target_handle = pair[1].handle();
200 // Set up a message to pass the handle to the server.
201 base::FileDescriptor filedesc(target_handle, false);
202 IPC::Message* msg = new MsgClassSetHandle(filedesc);
203 #endif // defined(OS_WIN)
204 EXPECT_TRUE(sender()->Send(msg));
205 // Use the current thread as the I/O thread.
206 base::MessageLoop::current()->Run();
207 // Shut down.
208 pair[0].Close();
209 pair[1].Close();
210 EXPECT_TRUE(WaitForClientShutdown());
211 DestroyChannel();
214 // A blocking read operation that will block the thread until it receives
215 // |length| bytes of packets or Shutdown() is called on another thread.
216 static void BlockingRead(base::SyncSocket* socket, char* buf,
217 size_t length, size_t* received) {
218 DCHECK(buf != NULL);
219 // Notify the parent thread that we're up and running.
220 socket->Send(kHelloString, kHelloStringLength);
221 *received = socket->Receive(buf, length);
224 // Tests that we can safely end a blocking Receive operation on one thread
225 // from another thread by disconnecting (but not closing) the socket.
226 TEST_F(SyncSocketTest, DisconnectTest) {
227 base::CancelableSyncSocket pair[2];
228 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
230 base::Thread worker("BlockingThread");
231 worker.Start();
233 // Try to do a blocking read from one of the sockets on the worker thread.
234 char buf[0xff];
235 size_t received = 1U; // Initialize to an unexpected value.
236 worker.task_runner()->PostTask(
237 FROM_HERE,
238 base::Bind(&BlockingRead, &pair[0], &buf[0], arraysize(buf), &received));
240 // Wait for the worker thread to say hello.
241 char hello[kHelloStringLength] = {0};
242 pair[1].Receive(&hello[0], sizeof(hello));
243 EXPECT_EQ(0, strcmp(hello, kHelloString));
244 // Give the worker a chance to start Receive().
245 base::PlatformThread::YieldCurrentThread();
247 // Now shut down the socket that the thread is issuing a blocking read on
248 // which should cause Receive to return with an error.
249 pair[0].Shutdown();
251 worker.Stop();
253 EXPECT_EQ(0U, received);
256 #if defined(OS_ANDROID)
257 #define MAYBE_BlockingReceiveTest DISABLED_BlockingReceiveTest
258 #else
259 #define MAYBE_BlockingReceiveTest BlockingReceiveTest
260 #endif
261 // Tests that read is a blocking operation.
262 TEST_F(SyncSocketTest, MAYBE_BlockingReceiveTest) {
263 base::CancelableSyncSocket pair[2];
264 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
266 base::Thread worker("BlockingThread");
267 worker.Start();
269 // Try to do a blocking read from one of the sockets on the worker thread.
270 char buf[kHelloStringLength] = {0};
271 size_t received = 1U; // Initialize to an unexpected value.
272 worker.task_runner()->PostTask(FROM_HERE,
273 base::Bind(&BlockingRead, &pair[0], &buf[0],
274 kHelloStringLength, &received));
276 // Wait for the worker thread to say hello.
277 char hello[kHelloStringLength] = {0};
278 pair[1].Receive(&hello[0], sizeof(hello));
279 EXPECT_EQ(0, strcmp(hello, kHelloString));
280 // Give the worker a chance to start Receive().
281 base::PlatformThread::YieldCurrentThread();
283 // Send a message to the socket on the blocking thead, it should free the
284 // socket from Receive().
285 pair[1].Send(kHelloString, kHelloStringLength);
286 worker.Stop();
288 // Verify the socket has received the message.
289 EXPECT_TRUE(strcmp(buf, kHelloString) == 0);
290 EXPECT_EQ(kHelloStringLength, received);
293 // Tests that the write operation is non-blocking and returns immediately
294 // when there is insufficient space in the socket's buffer.
295 TEST_F(SyncSocketTest, NonBlockingWriteTest) {
296 base::CancelableSyncSocket pair[2];
297 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
299 // Fill up the buffer for one of the socket, Send() should not block the
300 // thread even when the buffer is full.
301 while (pair[0].Send(kHelloString, kHelloStringLength) != 0) {}
303 // Data should be avialble on another socket.
304 size_t bytes_in_buffer = pair[1].Peek();
305 EXPECT_NE(bytes_in_buffer, 0U);
307 // No more data can be written to the buffer since socket has been full,
308 // verify that the amount of avialble data on another socket is unchanged.
309 EXPECT_EQ(0U, pair[0].Send(kHelloString, kHelloStringLength));
310 EXPECT_EQ(bytes_in_buffer, pair[1].Peek());
312 // Read from another socket to free some space for a new write.
313 char hello[kHelloStringLength] = {0};
314 pair[1].Receive(&hello[0], sizeof(hello));
316 // Should be able to write more data to the buffer now.
317 EXPECT_EQ(kHelloStringLength, pair[0].Send(kHelloString, kHelloStringLength));
320 } // namespace