brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · 514bce1 Raw
299 lines · cpp
1//===-- PlatformAndroidTest.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/PlatformAndroid.h"10#include "Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h"11#include "lldb/Utility/Connection.h"12#include "gmock/gmock.h"13 14using namespace lldb;15using namespace lldb_private;16using namespace lldb_private::platform_android;17using namespace testing;18 19namespace {20 21class MockAdbClient : public AdbClient {22public:23  explicit MockAdbClient() : AdbClient() {}24 25  MOCK_METHOD3(ShellToFile,26               Status(const char *command, std::chrono::milliseconds timeout,27                      const FileSpec &output_file_spec));28};29 30class PlatformAndroidTest : public PlatformAndroid, public ::testing::Test {31public:32  PlatformAndroidTest() : PlatformAndroid(false) {33    m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());34 35    // Set up default mock behavior to avoid uninteresting call warnings36    ON_CALL(*this, GetSyncService(_))37        .WillByDefault([](Status &error) -> std::unique_ptr<AdbSyncService> {38          error = Status::FromErrorString("Sync service unavailable");39          return nullptr;40        });41  }42 43  MOCK_METHOD1(GetAdbClient, AdbClientUP(Status &error));44  MOCK_METHOD0(GetPropertyPackageName, llvm::StringRef());45  MOCK_METHOD1(GetSyncService, std::unique_ptr<AdbSyncService>(Status &error));46 47  // Make GetSyncService public for testing48  using PlatformAndroid::GetSyncService;49};50 51} // namespace52 53TEST_F(PlatformAndroidTest,54       DownloadModuleSlice_AdbClientError_FailsGracefully) {55  EXPECT_CALL(*this, GetAdbClient(_))56      .WillOnce(DoAll(WithArg<0>([](auto &arg) {57                        arg = Status::FromErrorString(58                            "Failed to create AdbClient");59                      }),60                      Return(ByMove(AdbClientUP()))));61 62  Status result = DownloadModuleSlice(63      FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,64      3600, FileSpec("/tmp/libtest.so"));65 66  EXPECT_TRUE(result.Fail());67  EXPECT_THAT(result.AsCString(), HasSubstr("Failed to create AdbClient"));68}69 70TEST_F(PlatformAndroidTest, DownloadModuleSlice_ZipFile_UsesCorrectDdCommand) {71  auto *adb_client = new MockAdbClient();72  EXPECT_CALL(*adb_client,73              ShellToFile(StrEq("dd if='/system/app/Test/Test.apk' "74                                "iflag=skip_bytes,count_bytes "75                                "skip=4096 count=3600 status=none"),76                          _, _))77      .WillOnce(Return(Status()));78 79  EXPECT_CALL(*this, GetPropertyPackageName())80      .WillOnce(Return(llvm::StringRef("")));81 82  EXPECT_CALL(*this, GetAdbClient(_))83      .WillOnce(Return(ByMove(AdbClientUP(adb_client))));84 85  Status result = DownloadModuleSlice(86      FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,87      3600, FileSpec("/tmp/libtest.so"));88 89  EXPECT_TRUE(result.Success());90}91 92TEST_F(PlatformAndroidTest,93       DownloadModuleSlice_ZipFileWithRunAs_UsesRunAsCommand) {94  auto *adb_client = new MockAdbClient();95  EXPECT_CALL(*adb_client,96              ShellToFile(StrEq("run-as 'com.example.test' "97                                "dd if='/system/app/Test/Test.apk' "98                                "iflag=skip_bytes,count_bytes "99                                "skip=4096 count=3600 status=none"),100                          _, _))101      .WillOnce(Return(Status()));102 103  EXPECT_CALL(*this, GetPropertyPackageName())104      .WillOnce(Return(llvm::StringRef("com.example.test")));105 106  EXPECT_CALL(*this, GetAdbClient(_))107      .WillOnce(Return(ByMove(AdbClientUP(adb_client))));108 109  Status result = DownloadModuleSlice(110      FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,111      3600, FileSpec("/tmp/libtest.so"));112 113  EXPECT_TRUE(result.Success());114}115 116TEST_F(PlatformAndroidTest,117       DownloadModuleSlice_LargeFile_CalculatesParametersCorrectly) {118  const uint64_t large_offset = 100 * 1024 * 1024; // 100MB offset119  const uint64_t large_size = 50 * 1024 * 1024;    // 50MB size120 121  auto *adb_client = new MockAdbClient();122  EXPECT_CALL(*adb_client,123              ShellToFile(StrEq("dd if='/system/app/Large.apk' "124                                "iflag=skip_bytes,count_bytes "125                                "skip=104857600 count=52428800 status=none"),126                          _, _))127      .WillOnce(Return(Status()));128 129  EXPECT_CALL(*this, GetPropertyPackageName())130      .WillOnce(Return(llvm::StringRef("")));131 132  EXPECT_CALL(*this, GetAdbClient(_))133      .WillOnce(Return(ByMove(AdbClientUP(adb_client))));134 135  Status result = DownloadModuleSlice(136      FileSpec("/system/app/Large.apk!/lib/arm64-v8a/large.so"), large_offset,137      large_size, FileSpec("/tmp/large.so"));138 139  EXPECT_TRUE(result.Success());140}141 142TEST_F(PlatformAndroidTest,143       GetFile_SyncServiceUnavailable_FallsBackToShellCat) {144  auto *adb_client = new MockAdbClient();145  EXPECT_CALL(*adb_client,146              ShellToFile(StrEq("cat '/data/local/tmp/test'"), _, _))147      .WillOnce(Return(Status()));148 149  EXPECT_CALL(*this, GetPropertyPackageName())150      .WillOnce(Return(llvm::StringRef("")));151 152  EXPECT_CALL(*this, GetAdbClient(_))153      .WillOnce(DoAll(WithArg<0>([](auto &arg) { arg.Clear(); }),154                      Return(ByMove(AdbClientUP(adb_client)))));155 156  EXPECT_CALL(*this, GetSyncService(_))157      .WillOnce([](Status &error) -> std::unique_ptr<AdbSyncService> {158        error = Status::FromErrorString("Sync service unavailable");159        return nullptr;160      });161 162  Status result =163      GetFile(FileSpec("/data/local/tmp/test"), FileSpec("/tmp/test"));164  EXPECT_TRUE(result.Success());165}166 167TEST_F(PlatformAndroidTest, GetFile_WithRunAs_UsesRunAsInShellCommand) {168  auto *adb_client = new MockAdbClient();169  EXPECT_CALL(170      *adb_client,171      ShellToFile(StrEq("run-as 'com.example.app' "172                        "cat '/data/data/com.example.app/lib-main/libtest.so'"),173                  _, _))174      .WillOnce(Return(Status()));175 176  EXPECT_CALL(*this, GetPropertyPackageName())177      .WillOnce(Return(llvm::StringRef("com.example.app")));178 179  EXPECT_CALL(*this, GetAdbClient(_))180      .WillOnce(DoAll(WithArg<0>([](auto &arg) { arg.Clear(); }),181                      Return(ByMove(AdbClientUP(adb_client)))));182 183  EXPECT_CALL(*this, GetSyncService(_))184      .WillOnce([](Status &error) -> std::unique_ptr<AdbSyncService> {185        error = Status::FromErrorString("Sync service unavailable");186        return nullptr;187      });188 189  Status result =190      GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),191              FileSpec("/tmp/libtest.so"));192  EXPECT_TRUE(result.Success());193}194 195TEST_F(PlatformAndroidTest, GetFile_FilenameWithSingleQuotes_Rejected) {196  EXPECT_CALL(*this, GetSyncService(_))197      .WillOnce([](Status &error) -> std::unique_ptr<AdbSyncService> {198        error = Status::FromErrorString("Sync service unavailable");199        return nullptr;200      });201 202  Status result =203      GetFile(FileSpec("/test/file'with'quotes"), FileSpec("/tmp/output"));204 205  EXPECT_TRUE(result.Fail());206  EXPECT_THAT(result.AsCString(), HasSubstr("single-quotes"));207}208 209TEST_F(PlatformAndroidTest,210       DownloadModuleSlice_FilenameWithSingleQuotes_Rejected) {211  Status result = DownloadModuleSlice(FileSpec("/test/file'with'quotes"), 100,212                                      200, FileSpec("/tmp/output"));213 214  EXPECT_TRUE(result.Fail());215  EXPECT_THAT(result.AsCString(), HasSubstr("single-quotes"));216}217 218TEST_F(PlatformAndroidTest, GetFile_NetworkTimeout_PropagatesErrorCorrectly) {219  auto *adb_client = new MockAdbClient();220  EXPECT_CALL(*adb_client, ShellToFile(_, _, _))221      .WillOnce(Return(Status::FromErrorString("Network timeout")));222 223  EXPECT_CALL(*this, GetPropertyPackageName())224      .WillOnce(Return(llvm::StringRef("")));225 226  EXPECT_CALL(*this, GetAdbClient(_))227      .WillOnce(DoAll(WithArg<0>([](auto &arg) { arg.Clear(); }),228                      Return(ByMove(AdbClientUP(adb_client)))));229 230  EXPECT_CALL(*this, GetSyncService(_))231      .WillOnce([](Status &error) -> std::unique_ptr<AdbSyncService> {232        error = Status::FromErrorString("Sync service unavailable");233        return nullptr;234      });235 236  Status result =237      GetFile(FileSpec("/data/large/file.so"), FileSpec("/tmp/large.so"));238  EXPECT_TRUE(result.Fail());239  EXPECT_THAT(result.AsCString(), HasSubstr("Network timeout"));240}241 242TEST_F(PlatformAndroidTest, SyncService_ConnectionFailsGracefully) {243  // Constructor should succeed even with a failing connection244  AdbSyncService sync_service("test-device");245 246  // The service should report as not connected initially247  EXPECT_FALSE(sync_service.IsConnected());248  EXPECT_EQ(sync_service.GetDeviceId(), "test-device");249 250  // Operations should fail gracefully when connection setup fails251  FileSpec remote_file("/data/test.txt");252  FileSpec local_file("/tmp/test.txt");253  uint32_t mode, size, mtime;254 255  Status result = sync_service.Stat(remote_file, mode, size, mtime);256  EXPECT_TRUE(result.Fail());257}258 259TEST_F(PlatformAndroidTest, GetRunAs_FormatsPackageNameCorrectly) {260  // Empty package name261  EXPECT_CALL(*this, GetPropertyPackageName())262      .WillOnce(Return(llvm::StringRef("")));263  EXPECT_EQ(this->GetRunAs(), "");264 265  // Valid package name266  EXPECT_CALL(*this, GetPropertyPackageName())267      .WillOnce(Return(llvm::StringRef("com.example.test")));268  EXPECT_EQ(this->GetRunAs(), "run-as 'com.example.test' ");269}270 271TEST_F(PlatformAndroidTest,272       DownloadModuleSlice_ZeroOffset_CallsGetFileInsteadOfDd) {273  // When offset=0, DownloadModuleSlice calls GetFile which uses 'cat', not 'dd'274  // We need to ensure the sync service fails so GetFile falls back to shell cat275  auto *adb_client = new MockAdbClient();276  EXPECT_CALL(*adb_client,277              ShellToFile(StrEq("cat '/system/lib64/libc.so'"), _, _))278      .WillOnce(Return(Status()));279 280  EXPECT_CALL(*this, GetPropertyPackageName())281      .WillOnce(Return(llvm::StringRef("")));282 283  EXPECT_CALL(*this, GetAdbClient(_))284      .WillOnce(DoAll(WithArg<0>([](auto &arg) { arg.Clear(); }),285                      Return(ByMove(AdbClientUP(adb_client)))));286 287  // Mock GetSyncService to fail, forcing GetFile to use shell cat fallback288  EXPECT_CALL(*this, GetSyncService(_))289      .WillOnce(DoAll(WithArg<0>([](auto &arg) {290                        arg =291                            Status::FromErrorString("Sync service unavailable");292                      }),293                      Return(ByMove(std::unique_ptr<AdbSyncService>()))));294 295  Status result = DownloadModuleSlice(FileSpec("/system/lib64/libc.so"), 0, 0,296                                      FileSpec("/tmp/libc.so"));297  EXPECT_TRUE(result.Success());298}299