| Index: ipc/sync_socket_unittest.cc
|
| diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
|
| index dc50525b3673a83599350fc8ee9038dd9dbbf371..f283de00bef0c5a441128afa6fff81b8788f952f 100644
|
| --- a/ipc/sync_socket_unittest.cc
|
| +++ b/ipc/sync_socket_unittest.cc
|
| @@ -1,244 +1,309 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "base/sync_socket.h"
|
| -
|
| -#include <stdio.h>
|
| -#include <string>
|
| -#include <sstream>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/process_util.h"
|
| -#include "base/threading/thread.h"
|
| -#include "ipc/ipc_channel_proxy.h"
|
| -#include "ipc/ipc_tests.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "testing/multiprocess_func_list.h"
|
| -
|
| -#if defined(OS_POSIX)
|
| -#include "base/file_descriptor_posix.h"
|
| -#endif
|
| -
|
| -// IPC messages for testing ---------------------------------------------------
|
| -
|
| -#define IPC_MESSAGE_IMPL
|
| -#include "ipc/ipc_message_macros.h"
|
| -
|
| -#define IPC_MESSAGE_START TestMsgStart
|
| -
|
| -// Message class to pass a base::SyncSocket::Handle to another process. This
|
| -// is not as easy as it sounds, because of the differences in transferring
|
| -// Windows HANDLEs versus posix file descriptors.
|
| -#if defined(OS_WIN)
|
| -IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
|
| -#elif defined(OS_POSIX)
|
| -IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
|
| -#endif
|
| -
|
| -// Message class to pass a response to the server.
|
| -IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
|
| -
|
| -// Message class to tell the server to shut down.
|
| -IPC_MESSAGE_CONTROL0(MsgClassShutdown)
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -namespace {
|
| -const char kHelloString[] = "Hello, SyncSocket Client";
|
| -const size_t kHelloStringLength = arraysize(kHelloString);
|
| -} // namespace
|
| -
|
| -// The SyncSocket server listener class processes two sorts of
|
| -// messages from the client.
|
| -class SyncSocketServerListener : public IPC::Channel::Listener {
|
| - public:
|
| - SyncSocketServerListener() : chan_(NULL) {
|
| - }
|
| -
|
| - void Init(IPC::Channel* chan) {
|
| - chan_ = chan;
|
| - }
|
| -
|
| - virtual bool OnMessageReceived(const IPC::Message& msg) {
|
| - if (msg.routing_id() == MSG_ROUTING_CONTROL) {
|
| - IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
|
| - IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
|
| - IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
|
| - IPC_END_MESSAGE_MAP()
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - // This sort of message is sent first, causing the transfer of
|
| - // the handle for the SyncSocket. This message sends a buffer
|
| - // on the SyncSocket and then sends a response to the client.
|
| -#if defined(OS_WIN)
|
| - void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
|
| - SetHandle(handle);
|
| - }
|
| -#elif defined(OS_POSIX)
|
| - void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
|
| - SetHandle(fd_struct.fd);
|
| - }
|
| -#else
|
| -# error "What platform?"
|
| -#endif // defined(OS_WIN)
|
| -
|
| - void SetHandle(base::SyncSocket::Handle handle) {
|
| - base::SyncSocket sync_socket(handle);
|
| - EXPECT_EQ(sync_socket.Send(static_cast<const void*>(kHelloString),
|
| - kHelloStringLength), kHelloStringLength);
|
| - IPC::Message* msg = new MsgClassResponse(kHelloString);
|
| - EXPECT_TRUE(chan_->Send(msg));
|
| - }
|
| -
|
| - // When the client responds, it sends back a shutdown message,
|
| - // which causes the message loop to exit.
|
| - void OnMsgClassShutdown() {
|
| - MessageLoop::current()->Quit();
|
| - }
|
| -
|
| - IPC::Channel* chan_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
|
| -};
|
| -
|
| -// Runs the fuzzing server child mode. Returns when the preset number
|
| -// of messages have been received.
|
| -MULTIPROCESS_TEST_MAIN(RunSyncSocketServer) {
|
| - MessageLoopForIO main_message_loop;
|
| - SyncSocketServerListener listener;
|
| - IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_CLIENT, &listener);
|
| - EXPECT_TRUE(chan.Connect());
|
| - listener.Init(&chan);
|
| - MessageLoop::current()->Run();
|
| - return 0;
|
| -}
|
| -
|
| -// The SyncSocket client listener only processes one sort of message,
|
| -// a response from the server.
|
| -class SyncSocketClientListener : public IPC::Channel::Listener {
|
| - public:
|
| - SyncSocketClientListener() {
|
| - }
|
| -
|
| - void Init(base::SyncSocket* socket, IPC::Channel* chan) {
|
| - socket_ = socket;
|
| - chan_ = chan;
|
| - }
|
| -
|
| - virtual bool OnMessageReceived(const IPC::Message& msg) {
|
| - if (msg.routing_id() == MSG_ROUTING_CONTROL) {
|
| - IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
|
| - IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
|
| - IPC_END_MESSAGE_MAP()
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - // When a response is received from the server, it sends the same
|
| - // string as was written on the SyncSocket. These are compared
|
| - // and a shutdown message is sent back to the server.
|
| - void OnMsgClassResponse(const std::string& str) {
|
| - // We rely on the order of sync_socket.Send() and chan_->Send() in
|
| - // the SyncSocketServerListener object.
|
| - EXPECT_EQ(kHelloStringLength, socket_->Peek());
|
| - char buf[kHelloStringLength];
|
| - socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
|
| - EXPECT_EQ(strcmp(str.c_str(), buf), 0);
|
| - // After receiving from the socket there should be no bytes left.
|
| - EXPECT_EQ(0U, socket_->Peek());
|
| - IPC::Message* msg = new MsgClassShutdown();
|
| - EXPECT_TRUE(chan_->Send(msg));
|
| - MessageLoop::current()->Quit();
|
| - }
|
| -
|
| - base::SyncSocket* socket_;
|
| - IPC::Channel* chan_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
|
| -};
|
| -
|
| -class SyncSocketTest : public IPCChannelTest {
|
| -};
|
| -
|
| -TEST_F(SyncSocketTest, SanityTest) {
|
| - SyncSocketClientListener listener;
|
| - IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_SERVER,
|
| - &listener);
|
| - base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan);
|
| - ASSERT_TRUE(server_process);
|
| - // Create a pair of SyncSockets.
|
| - base::SyncSocket pair[2];
|
| - base::SyncSocket::CreatePair(&pair[0], &pair[1]);
|
| - // Immediately after creation there should be no pending bytes.
|
| - EXPECT_EQ(0U, pair[0].Peek());
|
| - EXPECT_EQ(0U, pair[1].Peek());
|
| - base::SyncSocket::Handle target_handle;
|
| - // Connect the channel and listener.
|
| - ASSERT_TRUE(chan.Connect());
|
| - listener.Init(&pair[0], &chan);
|
| -#if defined(OS_WIN)
|
| - // On windows we need to duplicate the handle into the server process.
|
| - BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
|
| - server_process, &target_handle,
|
| - 0, FALSE, DUPLICATE_SAME_ACCESS);
|
| - EXPECT_TRUE(retval);
|
| - // Set up a message to pass the handle to the server.
|
| - IPC::Message* msg = new MsgClassSetHandle(target_handle);
|
| -#else
|
| - target_handle = pair[1].handle();
|
| - // Set up a message to pass the handle to the server.
|
| - base::FileDescriptor filedesc(target_handle, false);
|
| - IPC::Message* msg = new MsgClassSetHandle(filedesc);
|
| -#endif // defined(OS_WIN)
|
| - EXPECT_TRUE(chan.Send(msg));
|
| - // Use the current thread as the I/O thread.
|
| - MessageLoop::current()->Run();
|
| - // Shut down.
|
| - pair[0].Close();
|
| - pair[1].Close();
|
| - EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
|
| - base::CloseProcessHandle(server_process);
|
| -}
|
| -
|
| -static void BlockingRead(base::SyncSocket* socket, size_t* received) {
|
| - // Notify the parent thread that we're up and running.
|
| - socket->Send(kHelloString, kHelloStringLength);
|
| - char buf[0xff]; // Won't ever be filled.
|
| - *received = socket->Receive(buf, arraysize(buf));
|
| -}
|
| -
|
| -// Tests that we can safely end a blocking Receive operation on one thread
|
| -// from another thread by disconnecting (but not closing) the socket.
|
| -TEST_F(SyncSocketTest, DisconnectTest) {
|
| - base::CancelableSyncSocket pair[2];
|
| - ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
|
| -
|
| - base::Thread worker("BlockingThread");
|
| - worker.Start();
|
| -
|
| - // Try to do a blocking read from one of the sockets on the worker thread.
|
| - size_t received = 1U; // Initialize to an unexpected value.
|
| - worker.message_loop()->PostTask(FROM_HERE,
|
| - base::Bind(&BlockingRead, &pair[0], &received));
|
| -
|
| - // Wait for the worker thread to say hello.
|
| - char hello[kHelloStringLength] = {0};
|
| - pair[1].Receive(&hello[0], sizeof(hello));
|
| - VLOG(1) << "Received: " << hello;
|
| - // Give the worker a chance to start Receive().
|
| - base::PlatformThread::YieldCurrentThread();
|
| -
|
| - // Now shut down the socket that the thread is issuing a blocking read on
|
| - // which should cause Receive to return with an error.
|
| - pair[0].Shutdown();
|
| -
|
| - worker.Stop();
|
| -
|
| - EXPECT_EQ(0U, received);
|
| -}
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/sync_socket.h"
|
| +
|
| +#include <stdio.h>
|
| +#include <string>
|
| +#include <sstream>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/process_util.h"
|
| +#include "base/threading/thread.h"
|
| +#include "ipc/ipc_channel_proxy.h"
|
| +#include "ipc/ipc_tests.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "testing/multiprocess_func_list.h"
|
| +
|
| +#if defined(OS_POSIX)
|
| +#include "base/file_descriptor_posix.h"
|
| +#endif
|
| +
|
| +// IPC messages for testing ---------------------------------------------------
|
| +
|
| +#define IPC_MESSAGE_IMPL
|
| +#include "ipc/ipc_message_macros.h"
|
| +
|
| +#define IPC_MESSAGE_START TestMsgStart
|
| +
|
| +// Message class to pass a base::SyncSocket::Handle to another process. This
|
| +// is not as easy as it sounds, because of the differences in transferring
|
| +// Windows HANDLEs versus posix file descriptors.
|
| +#if defined(OS_WIN)
|
| +IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
|
| +#elif defined(OS_POSIX)
|
| +IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
|
| +#endif
|
| +
|
| +// Message class to pass a response to the server.
|
| +IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
|
| +
|
| +// Message class to tell the server to shut down.
|
| +IPC_MESSAGE_CONTROL0(MsgClassShutdown)
|
| +
|
| +// ----------------------------------------------------------------------------
|
| +
|
| +namespace {
|
| +const char kHelloString[] = "Hello, SyncSocket Client";
|
| +const size_t kHelloStringLength = arraysize(kHelloString);
|
| +} // namespace
|
| +
|
| +// The SyncSocket server listener class processes two sorts of
|
| +// messages from the client.
|
| +class SyncSocketServerListener : public IPC::Channel::Listener {
|
| + public:
|
| + SyncSocketServerListener() : chan_(NULL) {
|
| + }
|
| +
|
| + void Init(IPC::Channel* chan) {
|
| + chan_ = chan;
|
| + }
|
| +
|
| + virtual bool OnMessageReceived(const IPC::Message& msg) {
|
| + if (msg.routing_id() == MSG_ROUTING_CONTROL) {
|
| + IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
|
| + IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
|
| + IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
|
| + IPC_END_MESSAGE_MAP()
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + private:
|
| + // This sort of message is sent first, causing the transfer of
|
| + // the handle for the SyncSocket. This message sends a buffer
|
| + // on the SyncSocket and then sends a response to the client.
|
| +#if defined(OS_WIN)
|
| + void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
|
| + SetHandle(handle);
|
| + }
|
| +#elif defined(OS_POSIX)
|
| + void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
|
| + SetHandle(fd_struct.fd);
|
| + }
|
| +#else
|
| +# error "What platform?"
|
| +#endif // defined(OS_WIN)
|
| +
|
| + void SetHandle(base::SyncSocket::Handle handle) {
|
| + base::SyncSocket sync_socket(handle);
|
| + EXPECT_EQ(sync_socket.Send(kHelloString, kHelloStringLength),
|
| + kHelloStringLength);
|
| + IPC::Message* msg = new MsgClassResponse(kHelloString);
|
| + EXPECT_TRUE(chan_->Send(msg));
|
| + }
|
| +
|
| + // When the client responds, it sends back a shutdown message,
|
| + // which causes the message loop to exit.
|
| + void OnMsgClassShutdown() {
|
| + MessageLoop::current()->Quit();
|
| + }
|
| +
|
| + IPC::Channel* chan_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
|
| +};
|
| +
|
| +// Runs the fuzzing server child mode. Returns when the preset number
|
| +// of messages have been received.
|
| +MULTIPROCESS_TEST_MAIN(RunSyncSocketServer) {
|
| + MessageLoopForIO main_message_loop;
|
| + SyncSocketServerListener listener;
|
| + IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_CLIENT, &listener);
|
| + EXPECT_TRUE(chan.Connect());
|
| + listener.Init(&chan);
|
| + MessageLoop::current()->Run();
|
| + return 0;
|
| +}
|
| +
|
| +// The SyncSocket client listener only processes one sort of message,
|
| +// a response from the server.
|
| +class SyncSocketClientListener : public IPC::Channel::Listener {
|
| + public:
|
| + SyncSocketClientListener() {
|
| + }
|
| +
|
| + void Init(base::SyncSocket* socket, IPC::Channel* chan) {
|
| + socket_ = socket;
|
| + chan_ = chan;
|
| + }
|
| +
|
| + virtual bool OnMessageReceived(const IPC::Message& msg) {
|
| + if (msg.routing_id() == MSG_ROUTING_CONTROL) {
|
| + IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
|
| + IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
|
| + IPC_END_MESSAGE_MAP()
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + private:
|
| + // When a response is received from the server, it sends the same
|
| + // string as was written on the SyncSocket. These are compared
|
| + // and a shutdown message is sent back to the server.
|
| + void OnMsgClassResponse(const std::string& str) {
|
| + // We rely on the order of sync_socket.Send() and chan_->Send() in
|
| + // the SyncSocketServerListener object.
|
| + EXPECT_EQ(kHelloStringLength, socket_->Peek());
|
| + char buf[kHelloStringLength];
|
| + socket_->Receive(static_cast<void*>(buf), kHelloStringLength);
|
| + EXPECT_EQ(strcmp(str.c_str(), buf), 0);
|
| + // After receiving from the socket there should be no bytes left.
|
| + EXPECT_EQ(0U, socket_->Peek());
|
| + IPC::Message* msg = new MsgClassShutdown();
|
| + EXPECT_TRUE(chan_->Send(msg));
|
| + MessageLoop::current()->Quit();
|
| + }
|
| +
|
| + base::SyncSocket* socket_;
|
| + IPC::Channel* chan_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SyncSocketClientListener);
|
| +};
|
| +
|
| +class SyncSocketTest : public IPCChannelTest {
|
| +};
|
| +
|
| +TEST_F(SyncSocketTest, SanityTest) {
|
| + SyncSocketClientListener listener;
|
| + IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_SERVER,
|
| + &listener);
|
| + base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan);
|
| + ASSERT_TRUE(server_process);
|
| + // Create a pair of SyncSockets.
|
| + base::SyncSocket pair[2];
|
| + base::SyncSocket::CreatePair(&pair[0], &pair[1]);
|
| + // Immediately after creation there should be no pending bytes.
|
| + EXPECT_EQ(0U, pair[0].Peek());
|
| + EXPECT_EQ(0U, pair[1].Peek());
|
| + base::SyncSocket::Handle target_handle;
|
| + // Connect the channel and listener.
|
| + ASSERT_TRUE(chan.Connect());
|
| + listener.Init(&pair[0], &chan);
|
| +#if defined(OS_WIN)
|
| + // On windows we need to duplicate the handle into the server process.
|
| + BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
|
| + server_process, &target_handle,
|
| + 0, FALSE, DUPLICATE_SAME_ACCESS);
|
| + EXPECT_TRUE(retval);
|
| + // Set up a message to pass the handle to the server.
|
| + IPC::Message* msg = new MsgClassSetHandle(target_handle);
|
| +#else
|
| + target_handle = pair[1].handle();
|
| + // Set up a message to pass the handle to the server.
|
| + base::FileDescriptor filedesc(target_handle, false);
|
| + IPC::Message* msg = new MsgClassSetHandle(filedesc);
|
| +#endif // defined(OS_WIN)
|
| + EXPECT_TRUE(chan.Send(msg));
|
| + // Use the current thread as the I/O thread.
|
| + MessageLoop::current()->Run();
|
| + // Shut down.
|
| + pair[0].Close();
|
| + pair[1].Close();
|
| + EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000));
|
| + base::CloseProcessHandle(server_process);
|
| +}
|
| +
|
| +static void BlockingRead(base::SyncSocket* socket, char* buf,
|
| + size_t length, size_t* received) {
|
| + DCHECK(buf != NULL);
|
| + // Notify the parent thread that we're up and running.
|
| + socket->Send(kHelloString, kHelloStringLength);
|
| + *received = socket->Receive(buf, length);
|
| +}
|
| +
|
| +// Tests that we can safely end a blocking Receive operation on one thread
|
| +// from another thread by disconnecting (but not closing) the socket.
|
| +TEST_F(SyncSocketTest, DisconnectTest) {
|
| + base::CancelableSyncSocket pair[2];
|
| + ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
|
| +
|
| + base::Thread worker("BlockingThread");
|
| + worker.Start();
|
| +
|
| + // Try to do a blocking read from one of the sockets on the worker thread.
|
| + char buf[0xff];
|
| + size_t received = 1U; // Initialize to an unexpected value.
|
| + worker.message_loop()->PostTask(FROM_HERE,
|
| + base::Bind(&BlockingRead, &pair[0], &buf[0], arraysize(buf), &received));
|
| +
|
| + // Wait for the worker thread to say hello.
|
| + char hello[kHelloStringLength] = {0};
|
| + pair[1].Receive(&hello[0], sizeof(hello));
|
| + EXPECT_EQ(0, strcmp(hello, kHelloString));
|
| + // Give the worker a chance to start Receive().
|
| + base::PlatformThread::YieldCurrentThread();
|
| +
|
| + // Now shut down the socket that the thread is issuing a blocking read on
|
| + // which should cause Receive to return with an error.
|
| + pair[0].Shutdown();
|
| +
|
| + worker.Stop();
|
| +
|
| + EXPECT_EQ(0U, received);
|
| +}
|
| +
|
| +// Tests that read is a blocking operation.
|
| +TEST_F(SyncSocketTest, BlockingReceiveTest) {
|
| + base::CancelableSyncSocket pair[2];
|
| + ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
|
| +
|
| + base::Thread worker("BlockingThread");
|
| + worker.Start();
|
| +
|
| + // Try to do a blocking read from one of the sockets on the worker thread.
|
| + char buf[kHelloStringLength] = {0};
|
| + size_t received = 1U; // Initialize to an unexpected value.
|
| + worker.message_loop()->PostTask(FROM_HERE,
|
| + base::Bind(&BlockingRead, &pair[0], &buf[0],
|
| + kHelloStringLength, &received));
|
| +
|
| + // Wait for the worker thread to say hello.
|
| + char hello[kHelloStringLength] = {0};
|
| + pair[1].Receive(&hello[0], sizeof(hello));
|
| + EXPECT_EQ(0, strcmp(hello, kHelloString));
|
| + // Give the worker a chance to start Receive().
|
| + base::PlatformThread::YieldCurrentThread();
|
| +
|
| + // The socket on the blocking thread is currently blocked on Receive() and
|
| + // has got nothing.
|
| + EXPECT_EQ(1U, received);
|
| +
|
| + // Send a message to the socket on the blocking thead, it should free the
|
| + // socket from Receive().
|
| + pair[1].Send(kHelloString, kHelloStringLength);
|
| + worker.Stop();
|
| +
|
| + // Verify the socket has received the message.
|
| + EXPECT_TRUE(strcmp(buf, kHelloString) == 0);
|
| + EXPECT_EQ(kHelloStringLength, received);
|
| +}
|
| +
|
| +// Tests that the write operation is non-blocking and returns immediately
|
| +// when there is insufficient space in the socket's buffer.
|
| +TEST_F(SyncSocketTest, NonBlockingWriteTest) {
|
| + base::CancelableSyncSocket pair[2];
|
| + ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
|
| +
|
| + // Fill up the buffer for one of the socket, Send() should not block the
|
| + // thread even when the buffer is full.
|
| + while (pair[0].Send(kHelloString, kHelloStringLength) != 0) {}
|
| +
|
| + // Data should be avialble on another socket.
|
| + size_t bytes_in_buffer = pair[1].Peek();
|
| + EXPECT_NE(bytes_in_buffer, 0U);
|
| +
|
| + // No more data can be written to the buffer since socket has been full,
|
| + // verify that the amount of avialble data on another socket is unchanged.
|
| + EXPECT_EQ(0U, pair[0].Send(kHelloString, kHelloStringLength));
|
| + EXPECT_EQ(bytes_in_buffer, pair[1].Peek());
|
| +
|
| + // Read from another socket to free some space for a new write.
|
| + char hello[kHelloStringLength] = {0};
|
| + pair[1].Receive(&hello[0], sizeof(hello));
|
| +
|
| + // Should be able to write more data to the buffer now.
|
| + EXPECT_EQ(kHelloStringLength, pair[0].Send(kHelloString, kHelloStringLength));
|
| +}
|
|
|