123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- // Copyright 2020 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 "device/bluetooth/socket.h"
- #include <tuple>
- #include <vector>
- #include "base/callback_helpers.h"
- #include "base/location.h"
- #include "base/run_loop.h"
- #include "base/test/gmock_callback_support.h"
- #include "base/test/task_environment.h"
- #include "device/bluetooth/bluetooth_socket.h"
- #include "device/bluetooth/test/fake_bluetooth_socket.h"
- #include "mojo/public/cpp/system/simple_watcher.h"
- #include "net/base/io_buffer.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace bluetooth {
- class SocketTest : public testing::Test {
- public:
- SocketTest() = default;
- ~SocketTest() override = default;
- SocketTest(const SocketTest&) = delete;
- SocketTest& operator=(const SocketTest&) = delete;
- void SetUp() override {
- mojo::ScopedDataPipeProducerHandle receive_pipe_producer_handle;
- mojo::ScopedDataPipeConsumerHandle receive_pipe_consumer_handle;
- ASSERT_EQ(
- MOJO_RESULT_OK,
- mojo::CreateDataPipe(/*options=*/nullptr, receive_pipe_producer_handle,
- receive_pipe_consumer_handle));
- mojo::ScopedDataPipeProducerHandle send_pipe_producer_handle;
- mojo::ScopedDataPipeConsumerHandle send_pipe_consumer_handle;
- ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(/*options=*/nullptr,
- send_pipe_producer_handle,
- send_pipe_consumer_handle));
- receive_stream_ = std::move(receive_pipe_consumer_handle);
- send_stream_ = std::move(send_pipe_producer_handle);
- fake_bluetooth_socket_ =
- base::MakeRefCounted<device::FakeBluetoothSocket>();
- socket_ = std::make_unique<Socket>(fake_bluetooth_socket_,
- std::move(receive_pipe_producer_handle),
- std::move(send_pipe_consumer_handle));
- }
- void VerifyReceiveAndRead(const std::string& message, bool success) {
- EXPECT_FALSE(receive_stream_->QuerySignalsState().never_readable());
- // Socket should only have 1 outstanding invocation of
- // BluetoothSocket::Receive().
- EXPECT_TRUE(fake_bluetooth_socket_->HasReceiveArgs());
- auto receive_args = fake_bluetooth_socket_->TakeReceiveArgs();
- EXPECT_FALSE(fake_bluetooth_socket_->HasReceiveArgs());
- int max_buffer_size = std::get<0>(*receive_args);
- EXPECT_GT(max_buffer_size, 0);
- // Attempting to read from |receive_stream_| before the BluetoothSocket
- // provides received data should signal a MOJO_RESULT_SHOULD_WAIT result.
- uint32_t buffer_size = static_cast<uint32_t>(max_buffer_size);
- EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- receive_stream_->ReadData(nullptr, &buffer_size,
- MOJO_READ_DATA_FLAG_NONE));
- if (success) {
- // Emulate a successful response from the remote device on the other side
- // of the BluetoothSocket. |receive_stream_| should then be ready to be
- // read from.
- auto success_callback = std::move(std::get<1>(*receive_args));
- std::move(success_callback)
- .Run(
- /*num_bytes_received=*/message.size(),
- /*io_buffer=*/base::MakeRefCounted<net::StringIOBuffer>(message));
- std::vector<char> buffer(max_buffer_size);
- EXPECT_EQ(MOJO_RESULT_OK,
- receive_stream_->ReadData(buffer.data(), &buffer_size,
- MOJO_READ_DATA_FLAG_NONE));
- std::string received_string(buffer.data(), buffer_size);
- EXPECT_EQ(message, received_string);
- } else {
- // Emulate an error in the stack. We should not be able to read from
- // |receive_stream_|.
- auto error_callback = std::move(std::get<2>(*receive_args));
- std::move(error_callback)
- .Run(device::BluetoothSocket::ErrorReason::kSystemError, "Error");
- }
- // Socket should only invoke BluetoothSocket::Receive() if it received
- // a success callback from the previous invocation.
- EXPECT_EQ(success, fake_bluetooth_socket_->HasReceiveArgs());
- // |receive_stream_| should only remain readable if Socket received a
- // success callback.
- EXPECT_EQ(success, !receive_stream_->QuerySignalsState().never_readable());
- }
- void WriteAndVerifySend(const std::string& message, bool success) {
- EXPECT_FALSE(send_stream_->QuerySignalsState().never_writable());
- // Verify that Socket has not attempted to invoke BluetoothSocket::Send(),
- // because no bytes have been written over |send_stream_| yet.
- EXPECT_FALSE(fake_bluetooth_socket_->HasSendArgs());
- uint32_t message_size = message.size();
- EXPECT_EQ(MOJO_RESULT_OK,
- send_stream_->WriteData(message.data(), &message_size,
- MOJO_WRITE_DATA_FLAG_NONE));
- EXPECT_EQ(message.size(), message_size);
- // Allow Socket to be notified that it can now read |send_stream_|.
- base::RunLoop().RunUntilIdle();
- // Socket should have now attempted to send our |message| to the remote
- // device on the other side of the BluetoothSocket.
- EXPECT_TRUE(fake_bluetooth_socket_->HasSendArgs());
- auto send_args = fake_bluetooth_socket_->TakeSendArgs();
- int buffer_size = std::get<1>(*send_args);
- EXPECT_EQ(message_size, static_cast<uint32_t>(buffer_size));
- char* buffer = std::get<0>(*send_args)->data();
- std::string sent_string(buffer, buffer_size);
- EXPECT_EQ(message, sent_string);
- if (success) {
- auto success_callback = std::move(std::get<2>(*send_args));
- std::move(success_callback).Run(/*num_bytes_sent=*/message.size());
- } else {
- auto error_callback = std::move(std::get<3>(*send_args));
- std::move(error_callback).Run(/*error_message=*/"Error");
- }
- // Never expect an outstanding invocation of BluetoothSocket::Send().
- EXPECT_FALSE(fake_bluetooth_socket_->HasSendArgs());
- // |send_stream_| should only remain writeable if Socket received a success
- // callback.
- EXPECT_EQ(success, !send_stream_->QuerySignalsState().never_writable());
- }
- protected:
- scoped_refptr<device::FakeBluetoothSocket> fake_bluetooth_socket_;
- mojo::ScopedDataPipeConsumerHandle receive_stream_;
- mojo::ScopedDataPipeProducerHandle send_stream_;
- std::unique_ptr<Socket> socket_;
- private:
- base::test::SingleThreadTaskEnvironment task_environment;
- };
- TEST_F(SocketTest, TestOnDestroyCallsClose) {
- // When destroyed, |socket_| is expected to tear down its BluetoothSocket.
- socket_.reset();
- EXPECT_TRUE(fake_bluetooth_socket_->called_disconnect());
- }
- TEST_F(SocketTest, TestDisconnect) {
- socket_->Disconnect(base::DoNothing());
- EXPECT_TRUE(fake_bluetooth_socket_->called_disconnect());
- }
- TEST_F(SocketTest, TestReceive_Success) {
- VerifyReceiveAndRead("received_message", /*success=*/true);
- }
- TEST_F(SocketTest, TestReceive_Error) {
- VerifyReceiveAndRead("received_message", /*success=*/false);
- }
- TEST_F(SocketTest, TestSend_Success) {
- WriteAndVerifySend("sent_message", /*success=*/true);
- }
- TEST_F(SocketTest, TestSend_Error) {
- WriteAndVerifySend("sent_message", /*success=*/false);
- }
- TEST_F(SocketTest, TestReceiveAndSendMultiple) {
- VerifyReceiveAndRead("message_1", /*success=*/true);
- VerifyReceiveAndRead("message_2", /*success=*/true);
- WriteAndVerifySend("message_3", /*success=*/true);
- WriteAndVerifySend("message_4", /*success=*/true);
- VerifyReceiveAndRead("message_5", /*success=*/true);
- WriteAndVerifySend("message_6", /*success=*/true);
- }
- } // namespace bluetooth
|