144 lines · cpp
1//===-- AdbClientTest.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Plugins/Platform/Android/AdbClient.h"10#include "lldb/Host/Socket.h"11#include "lldb/Host/common/TCPSocket.h"12#include "gtest/gtest.h"13#include <chrono>14#include <cstdlib>15 16static void set_env(const char *var, const char *value) {17#ifdef _WIN3218 _putenv_s(var, value);19#else20 setenv(var, value, true);21#endif22}23 24using namespace lldb;25using namespace lldb_private;26using namespace lldb_private::platform_android;27 28class AdbClientTest : public ::testing::Test {29public:30 void SetUp() override {31 set_env("ANDROID_SERIAL", "");32 set_env("ANDROID_ADB_SERVER_PORT", "");33 }34 35 void TearDown() override {36 set_env("ANDROID_SERIAL", "");37 set_env("ANDROID_ADB_SERVER_PORT", "");38 }39};40 41TEST_F(AdbClientTest, ResolveDeviceId_ExplicitDeviceId) {42 auto result = AdbClient::ResolveDeviceID("device1");43 EXPECT_TRUE(static_cast<bool>(result));44 EXPECT_EQ("device1", *result);45}46 47TEST_F(AdbClientTest, ResolveDeviceId_ByEnvVar) {48 set_env("ANDROID_SERIAL", "device2");49 50 auto result = AdbClient::ResolveDeviceID("");51 EXPECT_TRUE(static_cast<bool>(result));52 EXPECT_EQ("device2", *result);53}54 55TEST_F(AdbClientTest, ResolveDeviceId_PrefersExplicitOverEnvVar) {56 set_env("ANDROID_SERIAL", "env_device");57 58 // Explicit device ID should take precedence over environment variable59 auto result = AdbClient::ResolveDeviceID("explicit_device");60 EXPECT_TRUE(static_cast<bool>(result));61 EXPECT_EQ("explicit_device", *result);62}63 64TEST_F(AdbClientTest, AdbClient_Constructor_StoresDeviceId) {65 AdbClient client("test_device_123");66 EXPECT_EQ(client.GetDeviceID(), "test_device_123");67}68 69TEST_F(AdbClientTest, AdbClient_DefaultConstructor) {70 AdbClient client;71 EXPECT_EQ(client.GetDeviceID(), "");72}73 74TEST_F(AdbClientTest, AdbSyncService_Constructor_StoresDeviceId) {75 AdbSyncService sync("device123");76 EXPECT_EQ(sync.GetDeviceId(), "device123");77}78 79TEST_F(AdbClientTest, AdbSyncService_OperationsFailWhenNotConnected) {80 AdbSyncService sync_service("test_device");81 82 // Verify service is not connected initially83 EXPECT_FALSE(sync_service.IsConnected());84 85 // File operations should fail when not connected86 FileSpec remote_file("/data/test.txt");87 FileSpec local_file("/tmp/test.txt");88 uint32_t mode, size, mtime;89 90 Status stat_result = sync_service.Stat(remote_file, mode, size, mtime);91 EXPECT_TRUE(stat_result.Fail());92 93 Status pull_result = sync_service.PullFile(remote_file, local_file);94 EXPECT_TRUE(pull_result.Fail());95 96 Status push_result = sync_service.PushFile(local_file, remote_file);97 EXPECT_TRUE(push_result.Fail());98}99 100static uint16_t FindUnusedPort() {101 auto temp_socket = std::make_unique<TCPSocket>(true);102 Status error = temp_socket->Listen("localhost:0", 1);103 if (error.Fail()) {104 return 0; // fallback105 }106 uint16_t port = temp_socket->GetLocalPortNumber();107 temp_socket.reset(); // Close the socket to free the port108 return port;109}110 111#ifndef _WIN32112// This test is disabled on Windows due to platform-specific socket behavior113// that causes assertion failures in TCPSocket::Listen()114TEST_F(AdbClientTest, RealTcpConnection) {115 uint16_t unused_port = FindUnusedPort();116 ASSERT_NE(unused_port, 0) << "Failed to find an unused port";117 118 std::string port_str = std::to_string(unused_port);119 set_env("ANDROID_ADB_SERVER_PORT", port_str.c_str());120 121 AdbClient client;122 const auto status1 = client.Connect();123 EXPECT_FALSE(status1.Success())124 << "Connection should fail when no server is listening on port "125 << unused_port;126 127 // now start a server on the port and try again128 auto listen_socket = std::make_unique<TCPSocket>(true);129 std::string listen_address = "localhost:" + port_str;130 Status error = listen_socket->Listen(listen_address.c_str(), 5);131 ASSERT_TRUE(error.Success()) << "Failed to create listening socket on port "132 << unused_port << ": " << error.AsCString();133 134 // Verify the socket is listening on the expected port135 ASSERT_EQ(listen_socket->GetLocalPortNumber(), unused_port)136 << "Socket is not listening on the expected port";137 138 const auto status2 = client.Connect();139 EXPECT_TRUE(status2.Success())140 << "Connection should succeed when server is listening on port "141 << unused_port;142}143#endif // _WIN32144