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.
5 #include "services/device/serial/bluetooth_serial_port_impl.h"
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"
35 using ::base::test::RunOnceCallback;
37 using ::testing::Invoke;
38 using ::testing::Return;
39 using ::testing::WithArgs;
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;
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);
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(
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;
73 if (state.readable()) {
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) {
83 read_data->insert(read_data->end(), read_buffer,
84 read_buffer + bytes_read);
86 if (state.peer_closed())
89 if (result != MOJO_RESULT_OK)
95 class BluetoothSerialPortImplTest : public testing::Test {
97 BluetoothSerialPortImplTest() {
98 base::CommandLine::ForCurrentProcess()->AppendSwitch(
99 switches::kEnableBluetoothSerialPortProfileInSerialApi);
101 BluetoothSerialPortImplTest(const BluetoothSerialPortImplTest&) = delete;
102 BluetoothSerialPortImplTest& operator=(const BluetoothSerialPortImplTest&) =
104 ~BluetoothSerialPortImplTest() override = default;
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());
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());
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_));
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));
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,
150 MojoResult result = mojo::CreateDataPipe(&options, *producer, *consumer);
151 DCHECK_EQ(result, MOJO_RESULT_OK);
154 MockBluetoothSocket& mock_socket() { return *mock_socket_; }
157 scoped_refptr<MockBluetoothSocket> mock_socket_ =
158 base::MakeRefCounted<MockBluetoothSocket>();
159 std::unique_ptr<MockBluetoothDevice> mock_device_;
161 base::test::SingleThreadTaskEnvironment task_environment_;
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());
174 EXPECT_CALL(*adapter, GetDevice(kDeviceAddress))
175 .WillOnce(Return(mock_device.get()));
176 EXPECT_CALL(*mock_device, ConnectToService(GetSerialPortProfileUUID(), _, _))
177 .WillOnce(RunOnceCallback<2>("Error"));
179 EXPECT_CALL(mock_socket(), Receive(_, _, _)).Times(0);
180 EXPECT_CALL(mock_socket(), Disconnect(_)).Times(0);
183 BluetoothSerialPortImpl::Open(
184 std::move(adapter), kDeviceAddress, GetSerialPortProfileUUID(),
185 mojom::SerialConnectionOptions::New(), FakeSerialPortClient::Create(),
187 base::BindLambdaForTesting(
188 [&](mojo::PendingRemote<mojom::SerialPort> remote) {
189 EXPECT_FALSE(remote.is_valid());
195 TEST_F(BluetoothSerialPortImplTest, StartWritingTest) {
196 mojo::Remote<mojom::SerialPort> serial_port;
197 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
198 CreatePort(&serial_port, &watcher);
200 mojo::ScopedDataPipeProducerHandle producer;
201 mojo::ScopedDataPipeConsumerHandle consumer;
202 CreateDataPipe(&producer, &consumer);
204 uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
205 auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
208 producer->WriteData(&kBuffer, &bytes_read, MOJO_WRITE_DATA_FLAG_NONE);
209 EXPECT_EQ(result, MOJO_RESULT_OK);
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;
222 std::move(success_callback).Run(buffer_size);
225 EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
227 serial_port->StartWriting(std::move(consumer));
229 EXPECT_EQ(write_buffer->size(), static_cast<int>(bytes_read));
231 base::RunLoop disconnect_loop;
232 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
235 disconnect_loop.Run();
238 TEST_F(BluetoothSerialPortImplTest, StartReadingTest) {
239 mojo::Remote<mojom::SerialPort> serial_port;
240 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
241 CreatePort(&serial_port, &watcher);
243 mojo::ScopedDataPipeProducerHandle producer;
244 mojo::ScopedDataPipeConsumerHandle consumer;
245 CreateDataPipe(&producer, &consumer);
247 auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
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>());
254 serial_port->StartReading(std::move(producer));
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;
264 base::RunLoop disconnect_loop;
265 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
268 disconnect_loop.Run();
271 TEST_F(BluetoothSerialPortImplTest, StartReadingLargeBufferTest) {
272 mojo::Remote<mojom::SerialPort> serial_port;
273 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
274 CreatePort(&serial_port, &watcher);
276 mojo::ScopedDataPipeProducerHandle producer;
277 mojo::ScopedDataPipeConsumerHandle consumer;
278 CreateDataPipe(&producer, &consumer);
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);
286 std::vector<char> consumer_data;
287 size_t total_bytes_read = 0;
289 base::RunLoop watcher_loop;
290 mojo::SimpleWatcher consumer_watcher(
291 FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
292 MojoResult result = consumer_watcher.Watch(
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;
309 } else if (state.peer_closed()) {
313 EXPECT_EQ(MOJO_RESULT_OK, result);
314 consumer_watcher.ArmOrNotify();
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"));
323 EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
325 serial_port->StartReading(std::move(producer));
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;
336 base::RunLoop disconnect_loop;
337 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
340 disconnect_loop.Run();
343 TEST_F(BluetoothSerialPortImplTest, FlushWrite) {
344 mojo::Remote<mojom::SerialPort> serial_port;
345 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
346 CreatePort(&serial_port, &watcher);
348 mojo::ScopedDataPipeProducerHandle producer;
349 mojo::ScopedDataPipeConsumerHandle consumer;
350 CreateDataPipe(&producer, &consumer);
352 EXPECT_CALL(mock_socket(), Send).Times(0);
353 serial_port->StartWriting(std::move(consumer));
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();
368 EXPECT_EQ(MOJO_RESULT_OK, result);
370 base::RunLoop flush_loop;
371 serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
372 flush_loop.QuitClosure());
373 peer_closed_loop.Run();
376 base::RunLoop disconnect_loop;
377 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
380 disconnect_loop.Run();
383 TEST_F(BluetoothSerialPortImplTest, FlushWriteWithDataInPipe) {
384 mojo::Remote<mojom::SerialPort> serial_port;
385 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
386 CreatePort(&serial_port, &watcher);
388 mojo::ScopedDataPipeProducerHandle producer;
389 mojo::ScopedDataPipeConsumerHandle consumer;
390 CreateDataPipe(&producer, &consumer);
392 uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
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));
399 EXPECT_CALL(mock_socket(), Send).Times(1);
400 serial_port->StartWriting(std::move(consumer));
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());
417 base::RunLoop flush_loop;
418 serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
419 flush_loop.QuitClosure());
423 base::RunLoop disconnect_loop;
424 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
427 disconnect_loop.Run();
430 TEST_F(BluetoothSerialPortImplTest, FlushWriteAndWriteNewPipe) {
431 mojo::Remote<mojom::SerialPort> serial_port;
432 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
433 CreatePort(&serial_port, &watcher);
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;
442 const std::string pre_flush_data =
443 write_data.substr(/*pos=*/0, /*count=*/kBufferMidpointPos);
445 const std::string post_flush_data = write_data.substr(
446 kBufferMidpointPos, write_data.size() - kBufferMidpointPos);
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;
454 mojo::ScopedDataPipeProducerHandle pre_flush_producer;
455 mojo::ScopedDataPipeConsumerHandle pre_flush_consumer;
456 CreateDataPipe(&pre_flush_producer, &pre_flush_consumer);
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;
468 pre_flush_send_callback = std::move(callback);
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());
477 serial_port->StartWriting(std::move(pre_flush_consumer));
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());
492 EXPECT_EQ(result, MOJO_RESULT_OK);
494 base::RunLoop flush_loop;
495 serial_port->Flush(mojom::SerialPortFlushMode::kTransmit,
496 flush_loop.QuitClosure());
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);
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());
516 base::RunLoop post_flush_send_run_loop;
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;
528 std::move(callback).Run(buffer_size);
529 post_flush_send_run_loop.Quit();
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();
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());
541 post_flush_send_run_loop.Run();
546 base::RunLoop disconnect_loop;
547 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
550 disconnect_loop.Run();
553 TEST_F(BluetoothSerialPortImplTest, FlushRead) {
554 mojo::Remote<mojom::SerialPort> serial_port;
555 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
556 CreatePort(&serial_port, &watcher);
558 mojo::ScopedDataPipeProducerHandle producer;
559 mojo::ScopedDataPipeConsumerHandle consumer;
560 CreateDataPipe(&producer, &consumer);
562 const std::string test_data = CreateTestData(4);
564 auto discarded_buffer =
565 base::MakeRefCounted<net::StringIOBuffer>(kDiscardedBuffer);
567 MockBluetoothSocket::ReceiveCompletionCallback pre_flush_receive_callback;
568 EXPECT_CALL(mock_socket(), Receive)
571 MockBluetoothSocket::ReceiveCompletionCallback success_callback,
572 MockBluetoothSocket::ReceiveErrorCompletionCallback
574 pre_flush_receive_callback = std::move(success_callback);
576 serial_port->StartReading(std::move(producer));
578 // Calling Flush(kReceive) should cause the data pipe to close.
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());
592 EXPECT_EQ(MOJO_RESULT_OK, result);
594 base::RunLoop flush_loop;
595 serial_port->Flush(mojom::SerialPortFlushMode::kReceive,
596 flush_loop.QuitClosure());
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);
607 mojo::ScopedDataPipeProducerHandle new_producer;
608 mojo::ScopedDataPipeConsumerHandle new_consumer;
609 CreateDataPipe(&new_producer, &new_consumer);
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));
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;
625 base::RunLoop disconnect_loop;
626 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
629 disconnect_loop.Run();
632 TEST_F(BluetoothSerialPortImplTest, FlushReadAndReadNewPipe) {
633 mojo::Remote<mojom::SerialPort> serial_port;
634 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
635 CreatePort(&serial_port, &watcher);
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);
642 // First half of data.
643 auto pre_flush_buffer = base::MakeRefCounted<net::StringIOBuffer>(
644 write_data.substr(/*pos=*/0, /*count=*/kBufferMidpointPos));
646 // Second half of data.
647 const std::string post_flush_data =
648 write_data.substr(kBufferMidpointPos, kBufferSize - kBufferMidpointPos);
650 MockBluetoothSocket::ReceiveCompletionCallback pre_flush_receive_callback;
652 // Calling Flush(kReceive) will cause the data pipe to close.
654 mojo::ScopedDataPipeProducerHandle pre_flush_producer;
655 mojo::ScopedDataPipeConsumerHandle pre_flush_consumer;
656 CreateDataPipe(&pre_flush_producer, &pre_flush_consumer);
658 EXPECT_CALL(mock_socket(), Receive)
661 MockBluetoothSocket::ReceiveCompletionCallback success_callback,
662 MockBluetoothSocket::ReceiveErrorCompletionCallback
664 EXPECT_FALSE(pre_flush_receive_callback);
665 pre_flush_receive_callback = std::move(success_callback);
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());
681 EXPECT_EQ(MOJO_RESULT_OK, result);
683 serial_port->StartReading(std::move(pre_flush_producer));
685 base::RunLoop flush_loop;
686 serial_port->Flush(mojom::SerialPortFlushMode::kReceive,
687 flush_loop.QuitClosure());
690 EXPECT_TRUE(pre_flush_receive_callback);
693 mojo::ScopedDataPipeProducerHandle post_flush_producer;
694 mojo::ScopedDataPipeConsumerHandle post_flush_consumer;
695 CreateDataPipe(&post_flush_producer, &post_flush_consumer);
697 size_t num_write_bytes = 0;
698 EXPECT_CALL(mock_socket(), Receive)
700 .WillRepeatedly([&](int buffer_size,
701 MockBluetoothSocket::ReceiveCompletionCallback
703 MockBluetoothSocket::ReceiveErrorCompletionCallback
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));
712 std::move(error_callback).Run(BluetoothSocket::kSystemError, "Error");
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();
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);
727 std::vector<char> consumer_data;
728 EXPECT_EQ(MOJO_RESULT_OK,
729 ReadConsumerData(post_flush_consumer, &consumer_data));
731 // Verify post flush receive data is received by the consumer in the correct
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;
739 base::RunLoop disconnect_loop;
740 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
743 disconnect_loop.Run();
746 TEST_F(BluetoothSerialPortImplTest, Drain) {
747 mojo::Remote<mojom::SerialPort> serial_port;
748 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
749 CreatePort(&serial_port, &watcher);
751 mojo::ScopedDataPipeProducerHandle producer;
752 mojo::ScopedDataPipeConsumerHandle consumer;
753 CreateDataPipe(&producer, &consumer);
755 serial_port->StartWriting(std::move(consumer));
759 base::RunLoop drain_loop;
760 serial_port->Drain(drain_loop.QuitClosure());
763 base::RunLoop disconnect_loop;
764 watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
767 disconnect_loop.Run();
770 TEST_F(BluetoothSerialPortImplTest, Close) {
771 mojo::Remote<mojom::SerialPort> serial_port;
772 mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
773 CreatePort(&serial_port, &watcher);
775 mojo::ScopedDataPipeProducerHandle producer;
776 mojo::ScopedDataPipeConsumerHandle consumer;
777 CreateDataPipe(&producer, &consumer);
779 EXPECT_CALL(mock_socket(), Disconnect(_)).WillOnce(RunOnceCallback<0>());
781 base::RunLoop close_loop;
782 serial_port->Close(/*flush=*/false, close_loop.QuitClosure());
785 base::RunLoop disconnect_loop;
786 watcher->set_connection_error_handler(
787 base::BindLambdaForTesting([&]() { disconnect_loop.Quit(); }));
790 disconnect_loop.Run();
793 } // namespace device