xref: /aosp_15_r20/external/cronet/ipc/sync_socket_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/sync_socket.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker #include <sstream>
12*6777b538SAndroid Build Coastguard Worker #include <string>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/types/fixed_array.h"
22*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
23*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_test_base.h"
24*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
27*6777b538SAndroid Build Coastguard Worker #include "base/file_descriptor_posix.h"
28*6777b538SAndroid Build Coastguard Worker #endif
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker // IPC messages for testing ----------------------------------------------------
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker #define IPC_MESSAGE_IMPL
33*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_message_macros.h"
34*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_message_start.h"
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker #define IPC_MESSAGE_START TestMsgStart
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker // Message class to pass a base::SyncSocket::Handle to another process.  This
39*6777b538SAndroid Build Coastguard Worker // is not as easy as it sounds, because of the differences in transferring
40*6777b538SAndroid Build Coastguard Worker // Windows HANDLEs versus posix file descriptors.
41*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
42*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::SyncSocket::Handle)
43*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
44*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_CONTROL1(MsgClassSetHandle, base::FileDescriptor)
45*6777b538SAndroid Build Coastguard Worker #endif
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker // Message class to pass a response to the server.
48*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_CONTROL1(MsgClassResponse, std::string)
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker // Message class to tell the server to shut down.
51*6777b538SAndroid Build Coastguard Worker IPC_MESSAGE_CONTROL0(MsgClassShutdown)
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker namespace {
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker const char kHelloString[] = "Hello, SyncSocket Client";
58*6777b538SAndroid Build Coastguard Worker const size_t kHelloStringLength = std::size(kHelloString);
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker // The SyncSocket server listener class processes two sorts of
61*6777b538SAndroid Build Coastguard Worker // messages from the client.
62*6777b538SAndroid Build Coastguard Worker class SyncSocketServerListener : public IPC::Listener {
63*6777b538SAndroid Build Coastguard Worker  public:
SyncSocketServerListener()64*6777b538SAndroid Build Coastguard Worker   SyncSocketServerListener() : chan_(nullptr) {}
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker   SyncSocketServerListener(const SyncSocketServerListener&) = delete;
67*6777b538SAndroid Build Coastguard Worker   SyncSocketServerListener& operator=(const SyncSocketServerListener&) = delete;
68*6777b538SAndroid Build Coastguard Worker 
Init(IPC::Channel * chan)69*6777b538SAndroid Build Coastguard Worker   void Init(IPC::Channel* chan) {
70*6777b538SAndroid Build Coastguard Worker     chan_ = chan;
71*6777b538SAndroid Build Coastguard Worker   }
72*6777b538SAndroid Build Coastguard Worker 
OnMessageReceived(const IPC::Message & msg)73*6777b538SAndroid Build Coastguard Worker   bool OnMessageReceived(const IPC::Message& msg) override {
74*6777b538SAndroid Build Coastguard Worker     if (msg.routing_id() == MSG_ROUTING_CONTROL) {
75*6777b538SAndroid Build Coastguard Worker       IPC_BEGIN_MESSAGE_MAP(SyncSocketServerListener, msg)
76*6777b538SAndroid Build Coastguard Worker         IPC_MESSAGE_HANDLER(MsgClassSetHandle, OnMsgClassSetHandle)
77*6777b538SAndroid Build Coastguard Worker         IPC_MESSAGE_HANDLER(MsgClassShutdown, OnMsgClassShutdown)
78*6777b538SAndroid Build Coastguard Worker       IPC_END_MESSAGE_MAP()
79*6777b538SAndroid Build Coastguard Worker     }
80*6777b538SAndroid Build Coastguard Worker     return true;
81*6777b538SAndroid Build Coastguard Worker   }
set_quit_closure(base::OnceClosure quit_closure)82*6777b538SAndroid Build Coastguard Worker   void set_quit_closure(base::OnceClosure quit_closure) {
83*6777b538SAndroid Build Coastguard Worker     quit_closure_ = std::move(quit_closure);
84*6777b538SAndroid Build Coastguard Worker   }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker  private:
87*6777b538SAndroid Build Coastguard Worker   // This sort of message is sent first, causing the transfer of
88*6777b538SAndroid Build Coastguard Worker   // the handle for the SyncSocket.  This message sends a buffer
89*6777b538SAndroid Build Coastguard Worker   // on the SyncSocket and then sends a response to the client.
90*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
OnMsgClassSetHandle(const base::SyncSocket::Handle handle)91*6777b538SAndroid Build Coastguard Worker   void OnMsgClassSetHandle(const base::SyncSocket::Handle handle) {
92*6777b538SAndroid Build Coastguard Worker     SetHandle(handle);
93*6777b538SAndroid Build Coastguard Worker   }
94*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
95*6777b538SAndroid Build Coastguard Worker   void OnMsgClassSetHandle(const base::FileDescriptor& fd_struct) {
96*6777b538SAndroid Build Coastguard Worker     SetHandle(fd_struct.fd);
97*6777b538SAndroid Build Coastguard Worker   }
98*6777b538SAndroid Build Coastguard Worker #else
99*6777b538SAndroid Build Coastguard Worker # error "What platform?"
100*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
101*6777b538SAndroid Build Coastguard Worker 
SetHandle(base::SyncSocket::Handle handle)102*6777b538SAndroid Build Coastguard Worker   void SetHandle(base::SyncSocket::Handle handle) {
103*6777b538SAndroid Build Coastguard Worker     base::SyncSocket sync_socket(handle);
104*6777b538SAndroid Build Coastguard Worker     auto bytes_to_send = base::as_byte_span(kHelloString);
105*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(sync_socket.Send(bytes_to_send), bytes_to_send.size());
106*6777b538SAndroid Build Coastguard Worker     IPC::Message* msg = new MsgClassResponse(kHelloString);
107*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(chan_->Send(msg));
108*6777b538SAndroid Build Coastguard Worker   }
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   // When the client responds, it sends back a shutdown message,
111*6777b538SAndroid Build Coastguard Worker   // which causes the message loop to exit.
OnMsgClassShutdown()112*6777b538SAndroid Build Coastguard Worker   void OnMsgClassShutdown() { std::move(quit_closure_).Run(); }
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker   raw_ptr<IPC::Channel> chan_;
115*6777b538SAndroid Build Coastguard Worker   base::OnceClosure quit_closure_;
116*6777b538SAndroid Build Coastguard Worker };
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker // Runs the fuzzing server child mode. Returns when the preset number of
119*6777b538SAndroid Build Coastguard Worker // messages have been received.
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SyncSocketServerClient)120*6777b538SAndroid Build Coastguard Worker DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SyncSocketServerClient) {
121*6777b538SAndroid Build Coastguard Worker   SyncSocketServerListener listener;
122*6777b538SAndroid Build Coastguard Worker   base::RunLoop loop;
123*6777b538SAndroid Build Coastguard Worker   listener.set_quit_closure(loop.QuitWhenIdleClosure());
124*6777b538SAndroid Build Coastguard Worker   Connect(&listener);
125*6777b538SAndroid Build Coastguard Worker   listener.Init(channel());
126*6777b538SAndroid Build Coastguard Worker   loop.Run();
127*6777b538SAndroid Build Coastguard Worker   Close();
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker // The SyncSocket client listener only processes one sort of message,
131*6777b538SAndroid Build Coastguard Worker // a response from the server.
132*6777b538SAndroid Build Coastguard Worker class SyncSocketClientListener : public IPC::Listener {
133*6777b538SAndroid Build Coastguard Worker  public:
134*6777b538SAndroid Build Coastguard Worker   SyncSocketClientListener() = default;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   SyncSocketClientListener(const SyncSocketClientListener&) = delete;
137*6777b538SAndroid Build Coastguard Worker   SyncSocketClientListener& operator=(const SyncSocketClientListener&) = delete;
138*6777b538SAndroid Build Coastguard Worker 
Init(base::SyncSocket * socket,IPC::Channel * chan)139*6777b538SAndroid Build Coastguard Worker   void Init(base::SyncSocket* socket, IPC::Channel* chan) {
140*6777b538SAndroid Build Coastguard Worker     socket_ = socket;
141*6777b538SAndroid Build Coastguard Worker     chan_ = chan;
142*6777b538SAndroid Build Coastguard Worker   }
143*6777b538SAndroid Build Coastguard Worker 
OnMessageReceived(const IPC::Message & msg)144*6777b538SAndroid Build Coastguard Worker   bool OnMessageReceived(const IPC::Message& msg) override {
145*6777b538SAndroid Build Coastguard Worker     if (msg.routing_id() == MSG_ROUTING_CONTROL) {
146*6777b538SAndroid Build Coastguard Worker       IPC_BEGIN_MESSAGE_MAP(SyncSocketClientListener, msg)
147*6777b538SAndroid Build Coastguard Worker         IPC_MESSAGE_HANDLER(MsgClassResponse, OnMsgClassResponse)
148*6777b538SAndroid Build Coastguard Worker       IPC_END_MESSAGE_MAP()
149*6777b538SAndroid Build Coastguard Worker     }
150*6777b538SAndroid Build Coastguard Worker     return true;
151*6777b538SAndroid Build Coastguard Worker   }
set_quit_closure(base::OnceClosure quit_closure)152*6777b538SAndroid Build Coastguard Worker   void set_quit_closure(base::OnceClosure quit_closure) {
153*6777b538SAndroid Build Coastguard Worker     quit_closure_ = std::move(quit_closure);
154*6777b538SAndroid Build Coastguard Worker   }
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker  private:
157*6777b538SAndroid Build Coastguard Worker   // When a response is received from the server, it sends the same
158*6777b538SAndroid Build Coastguard Worker   // string as was written on the SyncSocket.  These are compared
159*6777b538SAndroid Build Coastguard Worker   // and a shutdown message is sent back to the server.
OnMsgClassResponse(const std::string & str)160*6777b538SAndroid Build Coastguard Worker   void OnMsgClassResponse(const std::string& str) {
161*6777b538SAndroid Build Coastguard Worker     // Account for the terminating null byte.
162*6777b538SAndroid Build Coastguard Worker     size_t expected_bytes_to_receive = str.length() + 1;
163*6777b538SAndroid Build Coastguard Worker     // We rely on the order of sync_socket.Send() and chan_->Send() in
164*6777b538SAndroid Build Coastguard Worker     // the SyncSocketServerListener object.
165*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(socket_->Peek(), expected_bytes_to_receive);
166*6777b538SAndroid Build Coastguard Worker     base::FixedArray<char> buf(expected_bytes_to_receive);
167*6777b538SAndroid Build Coastguard Worker     socket_->Receive(base::as_writable_bytes(base::make_span(buf)));
168*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(strcmp(str.c_str(), buf.data()), 0);
169*6777b538SAndroid Build Coastguard Worker     // After receiving from the socket there should be no bytes left.
170*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0U, socket_->Peek());
171*6777b538SAndroid Build Coastguard Worker     IPC::Message* msg = new MsgClassShutdown();
172*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(chan_->Send(msg));
173*6777b538SAndroid Build Coastguard Worker     std::move(quit_closure_).Run();
174*6777b538SAndroid Build Coastguard Worker   }
175*6777b538SAndroid Build Coastguard Worker 
176*6777b538SAndroid Build Coastguard Worker   raw_ptr<base::SyncSocket> socket_;
177*6777b538SAndroid Build Coastguard Worker   raw_ptr<IPC::Channel, DanglingUntriaged> chan_;
178*6777b538SAndroid Build Coastguard Worker   base::OnceClosure quit_closure_;
179*6777b538SAndroid Build Coastguard Worker };
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker using SyncSocketTest = IPCChannelMojoTestBase;
182*6777b538SAndroid Build Coastguard Worker 
TEST_F(SyncSocketTest,SanityTest)183*6777b538SAndroid Build Coastguard Worker TEST_F(SyncSocketTest, SanityTest) {
184*6777b538SAndroid Build Coastguard Worker   Init("SyncSocketServerClient");
185*6777b538SAndroid Build Coastguard Worker   base::RunLoop loop;
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker   SyncSocketClientListener listener;
188*6777b538SAndroid Build Coastguard Worker   listener.set_quit_closure(loop.QuitWhenIdleClosure());
189*6777b538SAndroid Build Coastguard Worker   CreateChannel(&listener);
190*6777b538SAndroid Build Coastguard Worker   // Create a pair of SyncSockets.
191*6777b538SAndroid Build Coastguard Worker   base::SyncSocket pair[2];
192*6777b538SAndroid Build Coastguard Worker   base::SyncSocket::CreatePair(&pair[0], &pair[1]);
193*6777b538SAndroid Build Coastguard Worker   // Immediately after creation there should be no pending bytes.
194*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0U, pair[0].Peek());
195*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0U, pair[1].Peek());
196*6777b538SAndroid Build Coastguard Worker   base::SyncSocket::Handle target_handle;
197*6777b538SAndroid Build Coastguard Worker   // Connect the channel and listener.
198*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(ConnectChannel());
199*6777b538SAndroid Build Coastguard Worker   listener.Init(&pair[0], channel());
200*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
201*6777b538SAndroid Build Coastguard Worker   // On windows we need to duplicate the handle into the server process.
202*6777b538SAndroid Build Coastguard Worker   BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
203*6777b538SAndroid Build Coastguard Worker                                 client_process().Handle(), &target_handle,
204*6777b538SAndroid Build Coastguard Worker                                 0, FALSE, DUPLICATE_SAME_ACCESS);
205*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(retval);
206*6777b538SAndroid Build Coastguard Worker   // Set up a message to pass the handle to the server.
207*6777b538SAndroid Build Coastguard Worker   IPC::Message* msg = new MsgClassSetHandle(target_handle);
208*6777b538SAndroid Build Coastguard Worker #else
209*6777b538SAndroid Build Coastguard Worker   target_handle = pair[1].handle();
210*6777b538SAndroid Build Coastguard Worker   // Set up a message to pass the handle to the server.
211*6777b538SAndroid Build Coastguard Worker   base::FileDescriptor filedesc(target_handle, false);
212*6777b538SAndroid Build Coastguard Worker   IPC::Message* msg = new MsgClassSetHandle(filedesc);
213*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
214*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(sender()->Send(msg));
215*6777b538SAndroid Build Coastguard Worker   // Use the current thread as the I/O thread.
216*6777b538SAndroid Build Coastguard Worker   loop.Run();
217*6777b538SAndroid Build Coastguard Worker   // Shut down.
218*6777b538SAndroid Build Coastguard Worker   pair[0].Close();
219*6777b538SAndroid Build Coastguard Worker   pair[1].Close();
220*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(WaitForClientShutdown());
221*6777b538SAndroid Build Coastguard Worker   DestroyChannel();
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker 
224*6777b538SAndroid Build Coastguard Worker // A blocking read operation that will block the thread until it receives
225*6777b538SAndroid Build Coastguard Worker // |buffer|'s length bytes of packets or Shutdown() is called on another thread.
BlockingRead(base::SyncSocket * socket,base::span<uint8_t> buffer,size_t * received)226*6777b538SAndroid Build Coastguard Worker static void BlockingRead(base::SyncSocket* socket,
227*6777b538SAndroid Build Coastguard Worker                          base::span<uint8_t> buffer,
228*6777b538SAndroid Build Coastguard Worker                          size_t* received) {
229*6777b538SAndroid Build Coastguard Worker   // Notify the parent thread that we're up and running.
230*6777b538SAndroid Build Coastguard Worker   socket->Send(base::as_byte_span(kHelloString));
231*6777b538SAndroid Build Coastguard Worker   *received = socket->Receive(buffer);
232*6777b538SAndroid Build Coastguard Worker }
233*6777b538SAndroid Build Coastguard Worker 
234*6777b538SAndroid Build Coastguard Worker // Tests that we can safely end a blocking Receive operation on one thread
235*6777b538SAndroid Build Coastguard Worker // from another thread by disconnecting (but not closing) the socket.
TEST_F(SyncSocketTest,DisconnectTest)236*6777b538SAndroid Build Coastguard Worker TEST_F(SyncSocketTest, DisconnectTest) {
237*6777b538SAndroid Build Coastguard Worker   base::CancelableSyncSocket pair[2];
238*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
239*6777b538SAndroid Build Coastguard Worker 
240*6777b538SAndroid Build Coastguard Worker   base::Thread worker("BlockingThread");
241*6777b538SAndroid Build Coastguard Worker   worker.Start();
242*6777b538SAndroid Build Coastguard Worker 
243*6777b538SAndroid Build Coastguard Worker   // Try to do a blocking read from one of the sockets on the worker thread.
244*6777b538SAndroid Build Coastguard Worker   char buf[0xff];
245*6777b538SAndroid Build Coastguard Worker   size_t received = 1U;  // Initialize to an unexpected value.
246*6777b538SAndroid Build Coastguard Worker   worker.task_runner()->PostTask(
247*6777b538SAndroid Build Coastguard Worker       FROM_HERE,
248*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&BlockingRead, &pair[0],
249*6777b538SAndroid Build Coastguard Worker                      base::as_writable_bytes(base::make_span(buf)), &received));
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker   // Wait for the worker thread to say hello.
252*6777b538SAndroid Build Coastguard Worker   char hello[kHelloStringLength] = {0};
253*6777b538SAndroid Build Coastguard Worker   pair[1].Receive(base::as_writable_bytes(base::make_span(hello)));
254*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(strcmp(hello, kHelloString), 0);
255*6777b538SAndroid Build Coastguard Worker   // Give the worker a chance to start Receive().
256*6777b538SAndroid Build Coastguard Worker   base::PlatformThread::YieldCurrentThread();
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker   // Now shut down the socket that the thread is issuing a blocking read on
259*6777b538SAndroid Build Coastguard Worker   // which should cause Receive to return with an error.
260*6777b538SAndroid Build Coastguard Worker   pair[0].Shutdown();
261*6777b538SAndroid Build Coastguard Worker 
262*6777b538SAndroid Build Coastguard Worker   worker.Stop();
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0U, received);
265*6777b538SAndroid Build Coastguard Worker }
266*6777b538SAndroid Build Coastguard Worker 
267*6777b538SAndroid Build Coastguard Worker // Tests that read is a blocking operation.
TEST_F(SyncSocketTest,BlockingReceiveTest)268*6777b538SAndroid Build Coastguard Worker TEST_F(SyncSocketTest, BlockingReceiveTest) {
269*6777b538SAndroid Build Coastguard Worker   base::CancelableSyncSocket pair[2];
270*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker   base::Thread worker("BlockingThread");
273*6777b538SAndroid Build Coastguard Worker   worker.Start();
274*6777b538SAndroid Build Coastguard Worker 
275*6777b538SAndroid Build Coastguard Worker   // Try to do a blocking read from one of the sockets on the worker thread.
276*6777b538SAndroid Build Coastguard Worker   char buf[kHelloStringLength] = {0};
277*6777b538SAndroid Build Coastguard Worker   size_t received = 1U;  // Initialize to an unexpected value.
278*6777b538SAndroid Build Coastguard Worker   worker.task_runner()->PostTask(
279*6777b538SAndroid Build Coastguard Worker       FROM_HERE,
280*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&BlockingRead, &pair[0],
281*6777b538SAndroid Build Coastguard Worker                      base::as_writable_bytes(base::make_span(buf)), &received));
282*6777b538SAndroid Build Coastguard Worker 
283*6777b538SAndroid Build Coastguard Worker   // Wait for the worker thread to say hello.
284*6777b538SAndroid Build Coastguard Worker   char hello[kHelloStringLength] = {0};
285*6777b538SAndroid Build Coastguard Worker   pair[1].Receive(base::as_writable_bytes(base::make_span(hello)));
286*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, strcmp(hello, kHelloString));
287*6777b538SAndroid Build Coastguard Worker   // Give the worker a chance to start Receive().
288*6777b538SAndroid Build Coastguard Worker   base::PlatformThread::YieldCurrentThread();
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   // Send a message to the socket on the blocking thead, it should free the
291*6777b538SAndroid Build Coastguard Worker   // socket from Receive().
292*6777b538SAndroid Build Coastguard Worker   auto bytes_to_send = base::as_byte_span(kHelloString);
293*6777b538SAndroid Build Coastguard Worker   pair[1].Send(bytes_to_send);
294*6777b538SAndroid Build Coastguard Worker   worker.Stop();
295*6777b538SAndroid Build Coastguard Worker 
296*6777b538SAndroid Build Coastguard Worker   // Verify the socket has received the message.
297*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(strcmp(buf, kHelloString) == 0);
298*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(received, bytes_to_send.size());
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker // Tests that the write operation is non-blocking and returns immediately
302*6777b538SAndroid Build Coastguard Worker // when there is insufficient space in the socket's buffer.
TEST_F(SyncSocketTest,NonBlockingWriteTest)303*6777b538SAndroid Build Coastguard Worker TEST_F(SyncSocketTest, NonBlockingWriteTest) {
304*6777b538SAndroid Build Coastguard Worker   base::CancelableSyncSocket pair[2];
305*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1]));
306*6777b538SAndroid Build Coastguard Worker 
307*6777b538SAndroid Build Coastguard Worker   // Fill up the buffer for one of the socket, Send() should not block the
308*6777b538SAndroid Build Coastguard Worker   // thread even when the buffer is full.
309*6777b538SAndroid Build Coastguard Worker   auto bytes_to_send = base::as_byte_span(kHelloString);
310*6777b538SAndroid Build Coastguard Worker   while (pair[0].Send(bytes_to_send) != 0) {
311*6777b538SAndroid Build Coastguard Worker   }
312*6777b538SAndroid Build Coastguard Worker 
313*6777b538SAndroid Build Coastguard Worker   // Data should be avialble on another socket.
314*6777b538SAndroid Build Coastguard Worker   size_t bytes_in_buffer = pair[1].Peek();
315*6777b538SAndroid Build Coastguard Worker   EXPECT_NE(bytes_in_buffer, 0U);
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker   // No more data can be written to the buffer since socket has been full,
318*6777b538SAndroid Build Coastguard Worker   // verify that the amount of avialble data on another socket is unchanged.
319*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(pair[0].Send(bytes_to_send), 0U);
320*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(bytes_in_buffer, pair[1].Peek());
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker   // Read from another socket to free some space for a new write.
323*6777b538SAndroid Build Coastguard Worker   char hello[kHelloStringLength] = {0};
324*6777b538SAndroid Build Coastguard Worker   pair[1].Receive(base::as_writable_bytes(base::make_span(hello)));
325*6777b538SAndroid Build Coastguard Worker 
326*6777b538SAndroid Build Coastguard Worker   // Should be able to write more data to the buffer now.
327*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(pair[0].Send(bytes_to_send), bytes_to_send.size());
328*6777b538SAndroid Build Coastguard Worker }
329*6777b538SAndroid Build Coastguard Worker 
330*6777b538SAndroid Build Coastguard Worker }  // namespace
331