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