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