#include "device/bluetooth/socket.h"
#include <tuple>
#include <vector>
#include "base/functional/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(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(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());
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);
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) {
auto success_callback = std::move(std::get<1>(*receive_args));
std::move(success_callback)
.Run(
message.size(),
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 {
auto error_callback = std::move(std::get<2>(*receive_args));
std::move(error_callback)
.Run(device::BluetoothSocket::ErrorReason::kSystemError, "Error");
}
EXPECT_EQ(success, fake_bluetooth_socket_->HasReceiveArgs());
EXPECT_EQ(success, !receive_stream_->QuerySignalsState().never_readable());
}
void WriteAndVerifySend(const std::string& message, bool success) {
EXPECT_FALSE(send_stream_->QuerySignalsState().never_writable());
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);
base::RunLoop().RunUntilIdle();
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(message.size());
} else {
auto error_callback = std::move(std::get<3>(*send_args));
std::move(error_callback).Run("Error");
}
EXPECT_FALSE(fake_bluetooth_socket_->HasSendArgs());
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) {
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", true);
}
TEST_F(SocketTest, TestReceive_Error) {
VerifyReceiveAndRead("received_message", false);
}
TEST_F(SocketTest, TestSend_Success) {
WriteAndVerifySend("sent_message", true);
}
TEST_F(SocketTest, TestSend_Error) {
WriteAndVerifySend("sent_message", false);
}
TEST_F(SocketTest, TestReceiveAndSendMultiple) {
VerifyReceiveAndRead("message_1", true);
VerifyReceiveAndRead("message_2", true);
WriteAndVerifySend("message_3", true);
WriteAndVerifySend("message_4", true);
VerifyReceiveAndRead("message_5", true);
WriteAndVerifySend("message_6", true);
}
}