sync_socket_unittest.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sync_socket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_test_base.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_descriptor_posix.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// IPC messages for testing ----------------------------------------------------
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_MESSAGE_IMPL
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_MESSAGE_START TestMsgStart
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Message class to pass a base::SyncSocket::Handle to another process.  This
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is not as easy as it sounds, because of the differences in transferring
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows HANDLEs versus posix file descriptors.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Message class to pass a response to the server.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Message class to tell the server to shut down.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPC_MESSAGE_CONTROL0(MsgClassShutdown)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// -----------------------------------------------------------------------------
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHelloString[] = "Hello, SyncSocket Client";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kHelloStringLength = arraysize(kHelloString);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The SyncSocket server listener class processes two sorts of
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// messages from the client.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncSocketServerListener : public IPC::Listener {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncSocketServerListener() : chan_(NULL) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init(IPC::Channel* chan) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chan_ = chan;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (msg.routing_id() == MSG_ROUTING_CONTROL) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_END_MESSAGE_MAP()
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This sort of message is sent first, causing the transfer of
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the handle for the SyncSocket.  This message sends a buffer
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the SyncSocket and then sends a response to the client.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetHandle(handle);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetHandle(fd_struct.fd);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error "What platform?"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetHandle(base::SyncSocket::Handle handle) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SyncSocket sync_socket(handle);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(sync_socket.Send(kHelloString, kHelloStringLength),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kHelloStringLength);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* msg = new MsgClassResponse(kHelloString);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(chan_->Send(msg));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the client responds, it sends back a shutdown message,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which causes the message loop to exit.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMsgClassShutdown() {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->Quit();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Channel* chan_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Runs the fuzzing server child mode. Returns when the preset number of
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// messages have been received.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SyncSocketServerClient) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForIO main_message_loop;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncSocketServerListener listener;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPC::Channel channel(IPCTestBase::GetChannelName("SyncSocketServerClient"),
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       IPC::Channel::MODE_CLIENT,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       &listener);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(channel.Connect());
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listener.Init(&channel);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->Run();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The SyncSocket client listener only processes one sort of message,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a response from the server.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncSocketClientListener : public IPC::Listener {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncSocketClientListener() {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init(base::SyncSocket* socket, IPC::Channel* chan) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_ = socket;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chan_ = chan;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (msg.routing_id() == MSG_ROUTING_CONTROL) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_END_MESSAGE_MAP()
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When a response is received from the server, it sends the same
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string as was written on the SyncSocket.  These are compared
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and a shutdown message is sent back to the server.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnMsgClassResponse(const std::string& str) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We rely on the order of sync_socket.Send() and chan_->Send() in
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the SyncSocketServerListener object.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kHelloStringLength, socket_->Peek());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char buf[kHelloStringLength];
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(strcmp(str.c_str(), buf), 0);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // After receiving from the socket there should be no bytes left.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0U, socket_->Peek());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::Message* msg = new MsgClassShutdown();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(chan_->Send(msg));
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->Quit();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SyncSocket* socket_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Channel* chan_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncSocketTest : public IPCTestBase {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncSocketTest, SanityTest) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Init("SyncSocketServerClient");
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncSocketClientListener listener;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CreateChannel(&listener);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(StartClient());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a pair of SyncSockets.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SyncSocket pair[2];
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SyncSocket::CreatePair(&pair[0], &pair[1]);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Immediately after creation there should be no pending bytes.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, pair[0].Peek());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, pair[1].Peek());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SyncSocket::Handle target_handle;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connect the channel and listener.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(ConnectChannel());
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listener.Init(&pair[0], channel());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On windows we need to duplicate the handle into the server process.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                client_process(), &target_handle,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                0, FALSE, DUPLICATE_SAME_ACCESS);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(retval);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up a message to pass the handle to the server.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Message* msg = new MsgClassSetHandle(target_handle);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_handle = pair[1].handle();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up a message to pass the handle to the server.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FileDescriptor filedesc(target_handle, false);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Message* msg = new MsgClassSetHandle(filedesc);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(sender()->Send(msg));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the current thread as the I/O thread.
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->Run();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[0].Close();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[1].Close();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(WaitForClientShutdown());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DestroyChannel();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A blocking read operation that will block the thread until it receives
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |length| bytes of packets or Shutdown() is called on another thread.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void BlockingRead(base::SyncSocket* socket, char* buf,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         size_t length, size_t* received) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf != NULL);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify the parent thread that we're up and running.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket->Send(kHelloString, kHelloStringLength);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *received = socket->Receive(buf, length);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that we can safely end a blocking Receive operation on one thread
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from another thread by disconnecting (but not closing) the socket.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncSocketTest, DisconnectTest) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancelableSyncSocket pair[2];
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread worker("BlockingThread");
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.Start();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to do a blocking read from one of the sockets on the worker thread.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[0xff];
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t received = 1U;  // Initialize to an unexpected value.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.message_loop()->PostTask(FROM_HERE,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BlockingRead, &pair[0], &buf[0], arraysize(buf), &received));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the worker thread to say hello.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char hello[kHelloStringLength] = {0};
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[1].Receive(&hello[0], sizeof(hello));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, strcmp(hello, kHelloString));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give the worker a chance to start Receive().
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::YieldCurrentThread();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now shut down the socket that the thread is issuing a blocking read on
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which should cause Receive to return with an error.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[0].Shutdown();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.Stop();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, received);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that read is a blocking operation.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncSocketTest, BlockingReceiveTest) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancelableSyncSocket pair[2];
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread worker("BlockingThread");
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.Start();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to do a blocking read from one of the sockets on the worker thread.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[kHelloStringLength] = {0};
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t received = 1U;  // Initialize to an unexpected value.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.message_loop()->PostTask(FROM_HERE,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BlockingRead, &pair[0], &buf[0],
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 kHelloStringLength, &received));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the worker thread to say hello.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char hello[kHelloStringLength] = {0};
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[1].Receive(&hello[0], sizeof(hello));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, strcmp(hello, kHelloString));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give the worker a chance to start Receive().
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::YieldCurrentThread();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a message to the socket on the blocking thead, it should free the
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // socket from Receive().
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[1].Send(kHelloString, kHelloStringLength);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  worker.Stop();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the socket has received the message.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(strcmp(buf, kHelloString) == 0);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHelloStringLength, received);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that the write operation is non-blocking and returns immediately
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when there is insufficient space in the socket's buffer.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncSocketTest, NonBlockingWriteTest) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CancelableSyncSocket pair[2];
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill up the buffer for one of the socket, Send() should not block the
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread even when the buffer is full.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (pair[0].Send(kHelloString, kHelloStringLength) != 0) {}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Data should be avialble on another socket.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_in_buffer = pair[1].Peek();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(bytes_in_buffer, 0U);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No more data can be written to the buffer since socket has been full,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // verify that the amount of avialble data on another socket is unchanged.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, pair[0].Send(kHelloString, kHelloStringLength));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(bytes_in_buffer, pair[1].Peek());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read from another socket to free some space for a new write.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char hello[kHelloStringLength] = {0};
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pair[1].Receive(&hello[0], sizeof(hello));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should be able to write more data to the buffer now.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHelloStringLength, pair[0].Send(kHelloString, kHelloStringLength));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
310