Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / services / device / serial / bluetooth_serial_port_impl_unittest.cc
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/device/serial/bluetooth_serial_port_impl.h"
6
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/test/bind.h"
11 #include "base/test/gmock_callback_support.h"
12 #include "base/test/task_environment.h"
13 #include "device/bluetooth/bluetooth_adapter_factory.h"
14 #include "device/bluetooth/bluetooth_socket.h"
15 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
16 #include "device/bluetooth/test/mock_bluetooth_device.h"
17 #include "device/bluetooth/test/mock_bluetooth_socket.h"
18 #include "mojo/public/cpp/bindings/pending_remote.h"
19 #include "mojo/public/cpp/bindings/remote.h"
20 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
21 #include "mojo/public/cpp/system/data_pipe.h"
22 #include "mojo/public/cpp/system/simple_watcher.h"
23 #include "net/base/io_buffer.h"
24 #include "services/device/public/cpp/bluetooth/bluetooth_utils.h"
25 #include "services/device/public/cpp/serial/serial_switches.h"
26 #include "services/device/public/cpp/test/fake_serial_port_client.h"
27 #include "services/device/public/mojom/serial.mojom.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 namespace device {
32
33 namespace {
34
35 using ::base::test::RunOnceCallback;
36 using ::testing::_;
37 using ::testing::Invoke;
38 using ::testing::Return;
39 using ::testing::WithArgs;
40
41 constexpr char kBuffer[] = "test";
42 const size_t kBufferNumBytes = std::char_traits<char>::length(kBuffer);
43 constexpr char kDiscardedBuffer[] = "discarded";
44 constexpr char kDeviceAddress[] = "00:00:00:00:00:00";
45 constexpr uint32_t kElementNumBytes = 1;
46 constexpr uint32_t kCapacityNumBytes = 64;
47
48 std::string CreateTestData(size_t buffer_size) {
49   std::string test_data(buffer_size, 'X');
50   for (size_t i = 0; i < test_data.size(); i++)
51     test_data[i] = 1 + (i % 127);
52   return test_data;
53 }
54
55 // Read all readable data from |consumer| into |read_data|.
56 MojoResult ReadConsumerData(mojo::ScopedDataPipeConsumerHandle& consumer,
57                             std::vector<char>* read_data) {
58   base::RunLoop run_loop;
59   mojo::SimpleWatcher consumer_watcher(
60       FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
61   MojoResult result = consumer_watcher.Watch(
62       consumer.get(),
63       MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
64       MOJO_WATCH_CONDITION_SATISFIED,
65       base::BindLambdaForTesting(
66           [&](MojoResult watch_result, const mojo::HandleSignalsState& state) {
67             EXPECT_EQ(watch_result, MOJO_RESULT_OK);
68             if (watch_result != MOJO_RESULT_OK) {
69               result = watch_result;
70               run_loop.Quit();
71               return;
72             }
73             if (state.readable()) {
74               char read_buffer[32];
75               uint32_t bytes_read = sizeof(read_buffer);
76               result = consumer->ReadData(read_buffer, &bytes_read,
77                                           MOJO_READ_DATA_FLAG_NONE);
78               EXPECT_EQ(MOJO_RESULT_OK, result);
79               if (result != MOJO_RESULT_OK) {
80                 run_loop.Quit();
81                 return;
82               }
83               read_data->insert(read_data->end(), read_buffer,
84                                 read_buffer + bytes_read);
85             }
86             if (state.peer_closed())
87               run_loop.Quit();
88           }));
89   if (result != MOJO_RESULT_OK)
90     return result;
91   run_loop.Run();
92   return result;
93 }
94
95 class BluetoothSerialPortImplTest : public testing::Test {
96  public:
97   BluetoothSerialPortImplTest() {
98     base::CommandLine::ForCurrentProcess()->AppendSwitch(
99         switches::kEnableBluetoothSerialPortProfileInSerialApi);
100   }
101   BluetoothSerialPortImplTest(const BluetoothSerialPortImplTest&) = delete;
102   BluetoothSerialPortImplTest& operator=(const BluetoothSerialPortImplTest&) =
103       delete;
104   ~BluetoothSerialPortImplTest() override = default;
105
106   void CreatePort(
107       mojo::Remote<mojom::SerialPort>* port,
108       mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher>* watcher) {
109     mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote;
110     *watcher = mojo::MakeSelfOwnedReceiver(
111         std::make_unique<mojom::SerialPortConnectionWatcher>(),
112         watcher_remote.InitWithNewPipeAndPassReceiver());
113
114     scoped_refptr<MockBluetoothAdapter> adapter =
115         base::MakeRefCounted<MockBluetoothAdapter>();
116     device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
117     mock_device_ = std::make_unique<MockBluetoothDevice>(
118         adapter.get(), 0, "Test Device", kDeviceAddress, false, false);
119     mock_device_->AddUUID(GetSerialPortProfileUUID());
120
121     EXPECT_CALL(*adapter, GetDevice(kDeviceAddress))
122         .WillOnce(Return(mock_device_.get()));
123     EXPECT_CALL(*mock_device_,
124                 ConnectToService(GetSerialPortProfileUUID(), _, _))
125         .WillOnce(RunOnceCallback<1>(mock_socket_));
126
127     base::RunLoop loop;
128     BluetoothSerialPortImpl::Open(
129         std::move(adapter), kDeviceAddress, GetSerialPortProfileUUID(),
130         mojom::SerialConnectionOptions::New(), FakeSerialPortClient::Create(),
131         std::move(watcher_remote),
132         base::BindLambdaForTesting(
133             [&](mojo::PendingRemote<mojom::SerialPort> remote) {
134               EXPECT_TRUE(remote.is_valid());
135               port->Bind(std::move(remote));
136               loop.Quit();
137             }));
138     loop.Run();
139   }
140
141   void CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
142                       mojo::ScopedDataPipeConsumerHandle* consumer) {
143     constexpr MojoCreateDataPipeOptions options = {
144         .struct_size = sizeof(MojoCreateDataPipeOptions),
145         .flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE,
146         .element_num_bytes = kElementNumBytes,
147         .capacity_num_bytes = kCapacityNumBytes,
148     };
149
150     MojoResult result = mojo::CreateDataPipe(&options, *producer, *consumer);
151     DCHECK_EQ(result, MOJO_RESULT_OK);
152   }
153
154   MockBluetoothSocket& mock_socket() { return *mock_socket_; }
155
156  private:
157   scoped_refptr<MockBluetoothSocket> mock_socket_ =
158       base::MakeRefCounted<MockBluetoothSocket>();
159   std::unique_ptr<MockBluetoothDevice> mock_device_;
160
161   base::test::SingleThreadTaskEnvironment task_environment_;
162 };
163
164 }  // namespace
165
166 TEST_F(BluetoothSerialPortImplTest, OpenFailure) {
167   scoped_refptr<MockBluetoothAdapter> adapter =
168       base::MakeRefCounted<MockBluetoothAdapter>();
169   device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
170   auto mock_device = std::make_unique<MockBluetoothDevice>(
171       adapter.get(), 0, "Test Device", kDeviceAddress, false, false);
172   mock_device->AddUUID(GetSerialPortProfileUUID());
173
174   EXPECT_CALL(*adapter, GetDevice(kDeviceAddress))
175       .WillOnce(Return(mock_device.get()));
176   EXPECT_CALL(*mock_device, ConnectToService(GetSerialPortProfileUUID(), _, _))
177       .WillOnce(RunOnceCallback<2>("Error"));
178
179   EXPECT_CALL(mock_socket(), Receive(_, _, _)).Times(0);
180   EXPECT_CALL(mock_socket(), Disconnect(_)).Times(0);
181
182   base::RunLoop loop;
183   BluetoothSerialPortImpl::Open(
184       std::move(adapter), kDeviceAddress, GetSerialPortProfileUUID(),
185       mojom::SerialConnectionOptions::New(), FakeSerialPortClient::Create(),
186       mojo::NullRemote(),
187       base::BindLambdaForTesting(
188           [&](mojo::PendingRemote<mojom::SerialPort> remote) {
189             EXPECT_FALSE(remote.is_valid());
190             loop.Quit();
191           }));
192   loop.Run();
193 }
194
195 TEST_F(BluetoothSerialPortImplTest, StartWritingTest) {
196   mojo::Remote<mojom::SerialPort> serial_port;
197   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
198   CreatePort(&serial_port, &watcher);
199
200   mojo::ScopedDataPipeProducerHandle producer;
201   mojo::ScopedDataPipeConsumerHandle consumer;
202   CreateDataPipe(&producer, &consumer);
203
204   uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
205   auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
206
207   MojoResult result =
208       producer->WriteData(&kBuffer, &bytes_read, MOJO_WRITE_DATA_FLAG_NONE);
209   EXPECT_EQ(result, MOJO_RESULT_OK);
210
211   EXPECT_CALL(mock_socket(), Send)
212       .WillOnce(WithArgs<0, 1, 2>(Invoke(
213           [&](scoped_refptr<net::IOBuffer> buf, int buffer_size,
214               MockBluetoothSocket::SendCompletionCallback success_callback) {
215             ASSERT_EQ(buffer_size, static_cast<int>(bytes_read));
216             // EXPECT_EQ only does a shallow comparison, so it's necessary to
217             // iterate through both objects and compare each character.
218             for (int i = 0; i < buffer_size; i++) {
219               EXPECT_EQ(buf->data()[i], kBuffer[i])
220                   << "buffer comparison failed at index " << i;
221             }
222             std::move(success_callback).Run(buffer_size);
223           })));
224
225   EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
226
227   serial_port->StartWriting(std::move(consumer));
228
229   EXPECT_EQ(write_buffer->size(), static_cast<int>(bytes_read));
230
231   base::RunLoop disconnect_loop;
232   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
233
234   serial_port.reset();
235   disconnect_loop.Run();
236 }
237
238 TEST_F(BluetoothSerialPortImplTest, StartReadingTest) {
239   mojo::Remote<mojom::SerialPort> serial_port;
240   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
241   CreatePort(&serial_port, &watcher);
242
243   mojo::ScopedDataPipeProducerHandle producer;
244   mojo::ScopedDataPipeConsumerHandle consumer;
245   CreateDataPipe(&producer, &consumer);
246
247   auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
248
249   EXPECT_CALL(mock_socket(), Receive(_, _, _))
250       .WillOnce(RunOnceCallback<1>(write_buffer->size(), write_buffer))
251       .WillOnce(RunOnceCallback<2>(BluetoothSocket::kSystemError, "Error"));
252   EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
253
254   serial_port->StartReading(std::move(producer));
255
256   std::vector<char> consumer_data;
257   EXPECT_EQ(MOJO_RESULT_OK, ReadConsumerData(consumer, &consumer_data));
258   ASSERT_EQ(kBufferNumBytes, consumer_data.size());
259   for (size_t i = 0; i < consumer_data.size(); i++) {
260     EXPECT_EQ(consumer_data[i], kBuffer[i])
261         << "buffer comparison failed at index " << i;
262   }
263
264   base::RunLoop disconnect_loop;
265   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
266
267   serial_port.reset();
268   disconnect_loop.Run();
269 }
270
271 TEST_F(BluetoothSerialPortImplTest, StartReadingLargeBufferTest) {
272   mojo::Remote<mojom::SerialPort> serial_port;
273   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
274   CreatePort(&serial_port, &watcher);
275
276   mojo::ScopedDataPipeProducerHandle producer;
277   mojo::ScopedDataPipeConsumerHandle consumer;
278   CreateDataPipe(&producer, &consumer);
279
280   constexpr uint32_t kTestBufferNumBytes = 2 * kCapacityNumBytes;
281   static_assert(kTestBufferNumBytes > kCapacityNumBytes,
282                 "must be greater than pipe capacity to test large reads.");
283   const std::string test_data = CreateTestData(kTestBufferNumBytes);
284   auto data_buffer = base::MakeRefCounted<net::StringIOBuffer>(test_data);
285
286   std::vector<char> consumer_data;
287   size_t total_bytes_read = 0;
288
289   base::RunLoop watcher_loop;
290   mojo::SimpleWatcher consumer_watcher(
291       FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
292   MojoResult result = consumer_watcher.Watch(
293       consumer.get(),
294       MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
295       MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
296       base::BindLambdaForTesting(
297           [&](MojoResult result, const mojo::HandleSignalsState& state) {
298             EXPECT_EQ(result, MOJO_RESULT_OK);
299             if (state.readable()) {
300               char read_buffer[32];
301               uint32_t bytes_read = sizeof(read_buffer);
302               result = consumer->ReadData(read_buffer, &bytes_read,
303                                           MOJO_READ_DATA_FLAG_NONE);
304               if (result == MOJO_RESULT_OK) {
305                 consumer_data.insert(consumer_data.end(), read_buffer,
306                                      read_buffer + bytes_read);
307                 total_bytes_read += bytes_read;
308               }
309             } else if (state.peer_closed()) {
310               watcher_loop.Quit();
311             }
312           }));
313   EXPECT_EQ(MOJO_RESULT_OK, result);
314   consumer_watcher.ArmOrNotify();
315
316   // BluetoothSerialPortImpl::StartReading() will request to receive the
317   // datapipe capacity (kCapacityNumBytes), but this test will respond with
318   // a larger buffer size.
319   EXPECT_CALL(mock_socket(), Receive(_, _, _))
320       .WillOnce(RunOnceCallback<1>(data_buffer->size(), data_buffer))
321       .WillOnce(RunOnceCallback<2>(BluetoothSocket::kSystemError, "Error"));
322
323   EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
324
325   serial_port->StartReading(std::move(producer));
326
327   watcher_loop.Run();
328
329   // Validate the data that was read is correct.
330   ASSERT_EQ(total_bytes_read, kTestBufferNumBytes);
331   for (size_t i = 0; i < total_bytes_read; i++) {
332     EXPECT_EQ(test_data[i], consumer_data[i])
333         << "consumer data invalid at index " << i;
334   }
335
336   base::RunLoop disconnect_loop;
337   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
338
339   serial_port.reset();
340   disconnect_loop.Run();
341 }
342
343 TEST_F(BluetoothSerialPortImplTest, FlushWrite) {
344   mojo::Remote<mojom::SerialPort> serial_port;
345   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
346   CreatePort(&serial_port, &watcher);
347
348   mojo::ScopedDataPipeProducerHandle producer;
349   mojo::ScopedDataPipeConsumerHandle consumer;
350   CreateDataPipe(&producer, &consumer);
351
352   EXPECT_CALL(mock_socket(), Send).Times(0);
353   serial_port->StartWriting(std::move(consumer));
354
355   // Calling Flush(kTransmit) should cause the data pipe to close.
356   base::RunLoop peer_closed_loop;
357   mojo::SimpleWatcher pipe_watcher(
358       FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
359   MojoResult result = pipe_watcher.Watch(
360       producer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
361       MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
362       base::BindLambdaForTesting(
363           [&](MojoResult result, const mojo::HandleSignalsState& state) {
364             EXPECT_EQ(result, MOJO_RESULT_OK);
365             EXPECT_TRUE(state.peer_closed());
366             peer_closed_loop.Quit();
367           }));
368   EXPECT_EQ(MOJO_RESULT_OK, result);
369
370   base::RunLoop flush_loop;
371   serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
372                      flush_loop.QuitClosure());
373   peer_closed_loop.Run();
374   flush_loop.Run();
375
376   base::RunLoop disconnect_loop;
377   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
378
379   serial_port.reset();
380   disconnect_loop.Run();
381 }
382
383 TEST_F(BluetoothSerialPortImplTest, FlushWriteWithDataInPipe) {
384   mojo::Remote<mojom::SerialPort> serial_port;
385   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
386   CreatePort(&serial_port, &watcher);
387
388   mojo::ScopedDataPipeProducerHandle producer;
389   mojo::ScopedDataPipeConsumerHandle consumer;
390   CreateDataPipe(&producer, &consumer);
391
392   uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
393
394   MojoResult result =
395       producer->WriteData(&kBuffer, &bytes_read, MOJO_WRITE_DATA_FLAG_NONE);
396   EXPECT_EQ(result, MOJO_RESULT_OK);
397   EXPECT_EQ(bytes_read, std::char_traits<char>::length(kBuffer));
398
399   EXPECT_CALL(mock_socket(), Send).Times(1);
400   serial_port->StartWriting(std::move(consumer));
401
402   // Calling Flush(kTransmit) should cause the data pipe to close.
403   base::RunLoop watcher_loop;
404   mojo::SimpleWatcher pipe_watcher(
405       FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
406   EXPECT_EQ(pipe_watcher.Watch(producer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
407                                MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
408                                base::BindLambdaForTesting(
409                                    [&](MojoResult result,
410                                        const mojo::HandleSignalsState& state) {
411                                      EXPECT_EQ(result, MOJO_RESULT_OK);
412                                      EXPECT_TRUE(state.peer_closed());
413                                      watcher_loop.Quit();
414                                    })),
415             MOJO_RESULT_OK);
416
417   base::RunLoop flush_loop;
418   serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
419                      flush_loop.QuitClosure());
420   flush_loop.Run();
421   watcher_loop.Run();
422
423   base::RunLoop disconnect_loop;
424   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
425
426   serial_port.reset();
427   disconnect_loop.Run();
428 }
429
430 TEST_F(BluetoothSerialPortImplTest, FlushWriteAndWriteNewPipe) {
431   mojo::Remote<mojom::SerialPort> serial_port;
432   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
433   CreatePort(&serial_port, &watcher);
434
435   // The data to be written to the serial port in this test.
436   constexpr size_t kBufferSize = kCapacityNumBytes;
437   constexpr size_t kBufferMidpointPos = kBufferSize / 2;
438   const std::string write_data = CreateTestData(kBufferSize);
439   uint32_t bytes_written;
440   MojoResult result;
441
442   const std::string pre_flush_data =
443       write_data.substr(/*pos=*/0, /*count=*/kBufferMidpointPos);
444
445   const std::string post_flush_data = write_data.substr(
446       kBufferMidpointPos, write_data.size() - kBufferMidpointPos);
447
448   /*******************************************************************/
449   /* Start writing a first time, which calls Send(...), but save the */
450   /* completion callback so that it can be called after the Flush()  */
451   /*******************************************************************/
452   MockBluetoothSocket::SendCompletionCallback pre_flush_send_callback;
453   {
454     mojo::ScopedDataPipeProducerHandle pre_flush_producer;
455     mojo::ScopedDataPipeConsumerHandle pre_flush_consumer;
456     CreateDataPipe(&pre_flush_producer, &pre_flush_consumer);
457
458     EXPECT_CALL(mock_socket(), Send)
459         .WillOnce(WithArgs<0, 1, 2>(
460             Invoke([&](scoped_refptr<net::IOBuffer> buf, int buffer_size,
461                        MockBluetoothSocket::SendCompletionCallback callback) {
462               EXPECT_EQ(buffer_size, static_cast<int>(bytes_written));
463               DCHECK(!pre_flush_send_callback);
464               for (int i = 0; i < buffer_size; i++) {
465                 EXPECT_EQ(buf->data()[i], pre_flush_data[i])
466                     << "buffer comparison failed at index " << i;
467               }
468               pre_flush_send_callback = std::move(callback);
469             })));
470
471     bytes_written = pre_flush_data.size();
472     result = pre_flush_producer->WriteData(
473         pre_flush_data.data(), &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
474     EXPECT_EQ(result, MOJO_RESULT_OK);
475     EXPECT_EQ(bytes_written, pre_flush_data.size());
476
477     serial_port->StartWriting(std::move(pre_flush_consumer));
478
479     // Calling Flush(kTransmit) causes the data pipe to close.
480     base::RunLoop watcher_loop;
481     mojo::SimpleWatcher pipe_watcher(
482         FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
483     result = pipe_watcher.Watch(
484         pre_flush_producer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
485         MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
486         base::BindLambdaForTesting(
487             [&](MojoResult result, const mojo::HandleSignalsState& state) {
488               EXPECT_EQ(result, MOJO_RESULT_OK);
489               EXPECT_TRUE(state.peer_closed());
490               watcher_loop.Quit();
491             }));
492     EXPECT_EQ(result, MOJO_RESULT_OK);
493
494     base::RunLoop flush_loop;
495     serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
496                        flush_loop.QuitClosure());
497     flush_loop.Run();
498     watcher_loop.Run();
499   }
500
501   /***************************************************************************/
502   /* Start writing a second time after flushing. Call the send callback for  */
503   /* the first write. This simulates a pre flush in-flight Send() completing */
504   /* after flushing and restarting writing.                                  */
505   /***************************************************************************/
506   mojo::ScopedDataPipeProducerHandle post_flush_producer;
507   mojo::ScopedDataPipeConsumerHandle post_flush_consumer;
508   CreateDataPipe(&post_flush_producer, &post_flush_consumer);
509
510   bytes_written = post_flush_data.size();
511   result = post_flush_producer->WriteData(
512       post_flush_data.data(), &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
513   EXPECT_EQ(result, MOJO_RESULT_OK);
514   EXPECT_EQ(bytes_written, post_flush_data.size());
515
516   base::RunLoop post_flush_send_run_loop;
517
518   EXPECT_CALL(mock_socket(), Send)
519       .WillOnce(WithArgs<0, 1, 2>(
520           Invoke([&](scoped_refptr<net::IOBuffer> buf, int buffer_size,
521                      MockBluetoothSocket::SendCompletionCallback callback) {
522             EXPECT_EQ(buffer_size, static_cast<int>(bytes_written));
523             DCHECK(!pre_flush_send_callback);
524             for (int i = 0; i < buffer_size; i++) {
525               EXPECT_EQ(buf->data()[i], post_flush_data[i])
526                   << "buffer comparison failed at index " << i;
527             }
528             std::move(callback).Run(buffer_size);
529             post_flush_send_run_loop.Quit();
530           })));
531
532   serial_port->StartWriting(std::move(post_flush_consumer));
533   // Wait for StartWriting to start on the remote end before directly calling
534   // the receive callback - which executes on the remote end.
535   serial_port.FlushForTesting();
536
537   // Write the first half of the data to the pre-flush receive callback.
538   ASSERT_TRUE(pre_flush_send_callback);
539   std::move(pre_flush_send_callback).Run(pre_flush_data.size());
540
541   post_flush_send_run_loop.Run();
542
543   /************/
544   /* Cleanup. */
545   /************/
546   base::RunLoop disconnect_loop;
547   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
548
549   serial_port.reset();
550   disconnect_loop.Run();
551 }
552
553 TEST_F(BluetoothSerialPortImplTest, FlushRead) {
554   mojo::Remote<mojom::SerialPort> serial_port;
555   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
556   CreatePort(&serial_port, &watcher);
557
558   mojo::ScopedDataPipeProducerHandle producer;
559   mojo::ScopedDataPipeConsumerHandle consumer;
560   CreateDataPipe(&producer, &consumer);
561
562   const std::string test_data = CreateTestData(4);
563
564   auto discarded_buffer =
565       base::MakeRefCounted<net::StringIOBuffer>(kDiscardedBuffer);
566
567   MockBluetoothSocket::ReceiveCompletionCallback pre_flush_receive_callback;
568   EXPECT_CALL(mock_socket(), Receive)
569       .WillOnce(
570           [&](int buffer_size,
571               MockBluetoothSocket::ReceiveCompletionCallback success_callback,
572               MockBluetoothSocket::ReceiveErrorCompletionCallback
573                   error_callback) {
574             pre_flush_receive_callback = std::move(success_callback);
575           });
576   serial_port->StartReading(std::move(producer));
577
578   // Calling Flush(kReceive) should cause the data pipe to close.
579   {
580     base::RunLoop watcher_loop;
581     mojo::SimpleWatcher pipe_watcher(
582         FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
583     MojoResult result = pipe_watcher.Watch(
584         consumer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
585         MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
586         base::BindLambdaForTesting([&](MojoResult watcher_result,
587                                        const mojo::HandleSignalsState& state) {
588           EXPECT_EQ(watcher_result, MOJO_RESULT_OK);
589           EXPECT_TRUE(state.peer_closed());
590           watcher_loop.Quit();
591         }));
592     EXPECT_EQ(MOJO_RESULT_OK, result);
593
594     base::RunLoop flush_loop;
595     serial_port->Flush(mojom::SerialPortFlushMode::kReceive,
596                        flush_loop.QuitClosure());
597     flush_loop.Run();
598     watcher_loop.Run();
599   }
600
601   // Running the Receive callback before StartReading() is called should result
602   // in this data being discarded.
603   ASSERT_TRUE(pre_flush_receive_callback);
604   std::move(pre_flush_receive_callback)
605       .Run(discarded_buffer->size(), discarded_buffer);
606
607   mojo::ScopedDataPipeProducerHandle new_producer;
608   mojo::ScopedDataPipeConsumerHandle new_consumer;
609   CreateDataPipe(&new_producer, &new_consumer);
610
611   auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(test_data);
612   EXPECT_CALL(mock_socket(), Receive(_, _, _))
613       .WillOnce(RunOnceCallback<1>(write_buffer->size(), write_buffer))
614       .WillOnce(RunOnceCallback<2>(BluetoothSocket::kSystemError, "Error"));
615   serial_port->StartReading(std::move(new_producer));
616
617   std::vector<char> consumer_data;
618   EXPECT_EQ(MOJO_RESULT_OK, ReadConsumerData(new_consumer, &consumer_data));
619   ASSERT_EQ(test_data.size(), consumer_data.size());
620   for (size_t i = 0; i < consumer_data.size(); i++) {
621     EXPECT_EQ(consumer_data[i], test_data[i])
622         << "buffer comparison failed at index " << i;
623   }
624
625   base::RunLoop disconnect_loop;
626   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
627
628   serial_port.reset();
629   disconnect_loop.Run();
630 }
631
632 TEST_F(BluetoothSerialPortImplTest, FlushReadAndReadNewPipe) {
633   mojo::Remote<mojom::SerialPort> serial_port;
634   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
635   CreatePort(&serial_port, &watcher);
636
637   // The data to be written to the serial port.
638   constexpr size_t kBufferSize = kCapacityNumBytes - 1;
639   constexpr size_t kBufferMidpointPos = kBufferSize / 2;
640   const std::string write_data = CreateTestData(kBufferSize);
641
642   // First half of data.
643   auto pre_flush_buffer = base::MakeRefCounted<net::StringIOBuffer>(
644       write_data.substr(/*pos=*/0, /*count=*/kBufferMidpointPos));
645
646   // Second half of data.
647   const std::string post_flush_data =
648       write_data.substr(kBufferMidpointPos, kBufferSize - kBufferMidpointPos);
649
650   MockBluetoothSocket::ReceiveCompletionCallback pre_flush_receive_callback;
651
652   // Calling Flush(kReceive) will cause the data pipe to close.
653   {
654     mojo::ScopedDataPipeProducerHandle pre_flush_producer;
655     mojo::ScopedDataPipeConsumerHandle pre_flush_consumer;
656     CreateDataPipe(&pre_flush_producer, &pre_flush_consumer);
657
658     EXPECT_CALL(mock_socket(), Receive)
659         .WillOnce(
660             [&](int buffer_size,
661                 MockBluetoothSocket::ReceiveCompletionCallback success_callback,
662                 MockBluetoothSocket::ReceiveErrorCompletionCallback
663                     error_callback) {
664               EXPECT_FALSE(pre_flush_receive_callback);
665               pre_flush_receive_callback = std::move(success_callback);
666             });
667
668     base::RunLoop watcher_loop;
669     mojo::SimpleWatcher write_watcher(
670         FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
671     MojoResult result = result = write_watcher.Watch(
672         pre_flush_consumer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
673         MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
674         base::BindLambdaForTesting(
675             [&watcher_loop](MojoResult result,
676                             const mojo::HandleSignalsState& state) {
677               EXPECT_EQ(result, MOJO_RESULT_OK);
678               EXPECT_TRUE(state.peer_closed());
679               watcher_loop.Quit();
680             }));
681     EXPECT_EQ(MOJO_RESULT_OK, result);
682
683     serial_port->StartReading(std::move(pre_flush_producer));
684
685     base::RunLoop flush_loop;
686     serial_port->Flush(mojom::SerialPortFlushMode::kReceive,
687                        flush_loop.QuitClosure());
688     flush_loop.Run();
689     watcher_loop.Run();
690     EXPECT_TRUE(pre_flush_receive_callback);
691   }
692
693   mojo::ScopedDataPipeProducerHandle post_flush_producer;
694   mojo::ScopedDataPipeConsumerHandle post_flush_consumer;
695   CreateDataPipe(&post_flush_producer, &post_flush_consumer);
696
697   size_t num_write_bytes = 0;
698   EXPECT_CALL(mock_socket(), Receive)
699       .Times(2)
700       .WillRepeatedly([&](int buffer_size,
701                           MockBluetoothSocket::ReceiveCompletionCallback
702                               success_callback,
703                           MockBluetoothSocket::ReceiveErrorCompletionCallback
704                               error_callback) {
705         EXPECT_FALSE(pre_flush_receive_callback);
706         if (!num_write_bytes) {
707           num_write_bytes = post_flush_data.size();
708           std::move(success_callback)
709               .Run(post_flush_data.size(),
710                    base::MakeRefCounted<net::StringIOBuffer>(post_flush_data));
711         } else {
712           std::move(error_callback).Run(BluetoothSocket::kSystemError, "Error");
713         }
714       });
715
716   // Write the second half of the data after the flush.
717   serial_port->StartReading(std::move(post_flush_producer));
718   // Wait for StartReading to start on the remote end before directly calling
719   // the receive callback - which executes on the remote end.
720   serial_port.FlushForTesting();
721
722   // Write the first half of the data to the pre-flush receive callback.
723   ASSERT_TRUE(pre_flush_receive_callback);
724   std::move(pre_flush_receive_callback)
725       .Run(pre_flush_buffer->size(), pre_flush_buffer);
726
727   std::vector<char> consumer_data;
728   EXPECT_EQ(MOJO_RESULT_OK,
729             ReadConsumerData(post_flush_consumer, &consumer_data));
730
731   // Verify post flush receive data is received by the consumer in the correct
732   // order.
733   ASSERT_EQ(write_data.size(), consumer_data.size());
734   for (size_t i = 0; i < consumer_data.size(); i++) {
735     EXPECT_EQ(consumer_data[i], write_data[i])
736         << "buffer comparison failed at index " << i;
737   }
738
739   base::RunLoop disconnect_loop;
740   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
741
742   serial_port.reset();
743   disconnect_loop.Run();
744 }
745
746 TEST_F(BluetoothSerialPortImplTest, Drain) {
747   mojo::Remote<mojom::SerialPort> serial_port;
748   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
749   CreatePort(&serial_port, &watcher);
750
751   mojo::ScopedDataPipeProducerHandle producer;
752   mojo::ScopedDataPipeConsumerHandle consumer;
753   CreateDataPipe(&producer, &consumer);
754
755   serial_port->StartWriting(std::move(consumer));
756
757   producer.reset();
758
759   base::RunLoop drain_loop;
760   serial_port->Drain(drain_loop.QuitClosure());
761   drain_loop.Run();
762
763   base::RunLoop disconnect_loop;
764   watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
765
766   serial_port.reset();
767   disconnect_loop.Run();
768 }
769
770 TEST_F(BluetoothSerialPortImplTest, Close) {
771   mojo::Remote<mojom::SerialPort> serial_port;
772   mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
773   CreatePort(&serial_port, &watcher);
774
775   mojo::ScopedDataPipeProducerHandle producer;
776   mojo::ScopedDataPipeConsumerHandle consumer;
777   CreateDataPipe(&producer, &consumer);
778
779   EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
780
781   base::RunLoop close_loop;
782   serial_port->Close(/*flush=*/false, close_loop.QuitClosure());
783   close_loop.Run();
784
785   base::RunLoop disconnect_loop;
786   watcher->set_connection_error_handler(
787       base::BindLambdaForTesting([&]() { disconnect_loop.Quit(); }));
788
789   serial_port.reset();
790   disconnect_loop.Run();
791 }
792
793 }  // namespace device