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