brintos

brintos / llvm-project-archived public Read only

0
0
Text · 37.2 KiB · d727cea Raw
899 lines · cpp
1//===-- LocateModuleCallbackTest.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/ObjectFile/Breakpad/ObjectFileBreakpad.h"10#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"11#include "Plugins/Platform/Android/PlatformAndroid.h"12#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"13#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"14#include "TestingSupport/SubsystemRAII.h"15#include "TestingSupport/TestUtilities.h"16#include "lldb/Core/Debugger.h"17#include "lldb/Core/PluginManager.h"18#include "lldb/Host/HostInfo.h"19#include "lldb/Target/Target.h"20#include "gmock/gmock.h"21 22using namespace lldb;23using namespace lldb_private;24using namespace lldb_private::platform_android;25using namespace lldb_private::platform_linux;26using namespace lldb_private::breakpad;27using namespace testing;28 29namespace {30 31constexpr llvm::StringLiteral k_process_plugin("mock-process-plugin");32constexpr llvm::StringLiteral k_platform_dir("remote-android");33constexpr llvm::StringLiteral k_cache_dir(".cache");34constexpr llvm::StringLiteral k_module_file("AndroidModule.so");35constexpr llvm::StringLiteral k_symbol_file("AndroidModule.unstripped.so");36constexpr llvm::StringLiteral k_breakpad_symbol_file("AndroidModule.so.sym");37constexpr llvm::StringLiteral k_arch("aarch64-none-linux");38constexpr llvm::StringLiteral39    k_module_uuid("80008338-82A0-51E5-5922-C905D23890DA-BDDEFECC");40constexpr llvm::StringLiteral k_function_symbol("boom");41constexpr llvm::StringLiteral k_hidden_function_symbol("boom_hidden");42const size_t k_module_size = 3784;43 44ModuleSpec GetTestModuleSpec();45 46class MockProcess : public Process {47public:48  MockProcess(TargetSP target_sp, ListenerSP listener_sp)49      : Process(target_sp, listener_sp) {}50 51  llvm::StringRef GetPluginName() override { return k_process_plugin; };52 53  bool CanDebug(TargetSP target, bool plugin_specified_by_name) override {54    return true;55  }56 57  Status DoDestroy() override { return Status(); }58 59  void RefreshStateAfterStop() override {}60 61  bool DoUpdateThreadList(ThreadList &old_thread_list,62                          ThreadList &new_thread_list) override {63    return false;64  }65 66  size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,67                      Status &error) override {68    return 0;69  }70 71  bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch,72                     ModuleSpec &module_spec) override {73    module_spec = GetTestModuleSpec();74    return true;75  }76};77 78FileSpec GetTestDir() {79  const auto *info = UnitTest::GetInstance()->current_test_info();80  FileSpec test_dir = HostInfo::GetProcessTempDir();81  test_dir.AppendPathComponent(std::string(info->test_case_name()) + "-" +82                               info->name());83  std::error_code ec = llvm::sys::fs::create_directory(test_dir.GetPath());84  EXPECT_FALSE(ec);85  return test_dir;86}87 88FileSpec GetRemotePath() {89  FileSpec fs("/", FileSpec::Style::posix);90  fs.AppendPathComponent("bin");91  fs.AppendPathComponent(k_module_file);92  return fs;93}94 95FileSpec GetUuidView(FileSpec spec) {96  spec.AppendPathComponent(k_platform_dir);97  spec.AppendPathComponent(k_cache_dir);98  spec.AppendPathComponent(k_module_uuid);99  spec.AppendPathComponent(k_module_file);100  return spec;101}102 103void BuildEmptyCacheDir(const FileSpec &test_dir) {104  FileSpec cache_dir(test_dir);105  cache_dir.AppendPathComponent(k_platform_dir);106  cache_dir.AppendPathComponent(k_cache_dir);107  std::error_code ec = llvm::sys::fs::create_directories(cache_dir.GetPath());108  EXPECT_FALSE(ec);109}110 111FileSpec BuildCacheDir(const FileSpec &test_dir) {112  FileSpec uuid_view = GetUuidView(test_dir);113  std::error_code ec =114      llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());115  EXPECT_FALSE(ec);116  ec = llvm::sys::fs::copy_file(GetInputFilePath(k_module_file),117                                uuid_view.GetPath().c_str());118  EXPECT_FALSE(ec);119  return uuid_view;120}121 122FileSpec GetSymFileSpec(const FileSpec &uuid_view) {123  return FileSpec(uuid_view.GetPath() + ".sym");124}125 126FileSpec BuildCacheDirWithSymbol(const FileSpec &test_dir) {127  FileSpec uuid_view = BuildCacheDir(test_dir);128  std::error_code ec =129      llvm::sys::fs::copy_file(GetInputFilePath(k_symbol_file),130                               GetSymFileSpec(uuid_view).GetPath().c_str());131  EXPECT_FALSE(ec);132  return uuid_view;133}134 135FileSpec BuildCacheDirWithBreakpadSymbol(const FileSpec &test_dir) {136  FileSpec uuid_view = BuildCacheDir(test_dir);137  std::error_code ec =138      llvm::sys::fs::copy_file(GetInputFilePath(k_breakpad_symbol_file),139                               GetSymFileSpec(uuid_view).GetPath().c_str());140  EXPECT_FALSE(ec);141  return uuid_view;142}143 144ModuleSpec GetTestModuleSpec() {145  ModuleSpec module_spec(GetRemotePath(), ArchSpec(k_arch));146  module_spec.GetUUID().SetFromStringRef(k_module_uuid);147  module_spec.SetObjectSize(k_module_size);148  return module_spec;149}150 151void CheckModule(const ModuleSP &module_sp) {152  ASSERT_TRUE(module_sp);153  ASSERT_EQ(module_sp->GetUUID().GetAsString(), k_module_uuid);154  ASSERT_EQ(module_sp->GetObjectOffset(), 0U);155  ASSERT_EQ(module_sp->GetPlatformFileSpec(), GetRemotePath());156}157 158SymbolContextList FindFunctions(const ModuleSP &module_sp,159                                const llvm::StringRef &name) {160  SymbolContextList sc_list;161  ModuleFunctionSearchOptions function_options;162  function_options.include_symbols = true;163  function_options.include_inlines = true;164  FunctionNameType type = static_cast<FunctionNameType>(eSymbolTypeCode);165  module_sp->FindFunctions(ConstString(name), CompilerDeclContext(), type,166                           function_options, sc_list);167  return sc_list;168}169 170void CheckStrippedSymbol(const ModuleSP &module_sp) {171  SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol);172  EXPECT_EQ(1U, sc_list.GetSize());173 174  sc_list = FindFunctions(module_sp, k_hidden_function_symbol);175  EXPECT_EQ(0U, sc_list.GetSize());176}177 178void CheckUnstrippedSymbol(const ModuleSP &module_sp) {179  SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol);180  EXPECT_EQ(1U, sc_list.GetSize());181 182  sc_list = FindFunctions(module_sp, k_hidden_function_symbol);183  EXPECT_EQ(1U, sc_list.GetSize());184}185 186ProcessSP MockProcessCreateInstance(TargetSP target_sp, ListenerSP listener_sp,187                                    const FileSpec *crash_file_path,188                                    bool can_connect) {189  return std::make_shared<MockProcess>(target_sp, listener_sp);190}191 192class LocateModuleCallbackTest : public testing::Test {193  SubsystemRAII<FileSystem, HostInfo, ObjectFileBreakpad, ObjectFileELF,194                PlatformAndroid, PlatformLinux, SymbolFileBreakpad,195                SymbolFileSymtab>196      subsystems;197 198public:199  void SetUp() override {200    m_test_dir = GetTestDir();201 202    // Set module cache directory for PlatformAndroid.203    PlatformAndroid::GetGlobalPlatformProperties().SetModuleCacheDirectory(204        m_test_dir);205 206    // Create Debugger.207    ArchSpec host_arch("i386-pc-linux");208    Platform::SetHostPlatform(209        platform_linux::PlatformLinux::CreateInstance(true, &host_arch));210    m_debugger_sp = Debugger::CreateInstance();211    EXPECT_TRUE(m_debugger_sp);212 213    // Create PlatformAndroid.214    ArchSpec arch(k_arch);215    m_platform_sp = PlatformAndroid::CreateInstance(true, &arch);216    EXPECT_TRUE(m_platform_sp);217 218    // Create Target.219    m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,220                                                eLoadDependentsNo,221                                                m_platform_sp, m_target_sp);222    EXPECT_TRUE(m_target_sp);223 224    // Create MockProcess.225    PluginManager::RegisterPlugin(k_process_plugin, "",226                                  MockProcessCreateInstance);227    m_process_sp =228        m_target_sp->CreateProcess(Listener::MakeListener("test-listener"),229                                   k_process_plugin, /*crash_file=*/nullptr,230                                   /*can_connect=*/true);231    EXPECT_TRUE(m_process_sp);232 233    m_module_spec = GetTestModuleSpec();234    m_module_spec_without_uuid = ModuleSpec(GetRemotePath(), ArchSpec(k_arch));235  }236 237  void TearDown() override {238    if (m_module_sp)239      ModuleList::RemoveSharedModule(m_module_sp);240  }241 242  void CheckNoCallback() {243    EXPECT_FALSE(m_platform_sp->GetLocateModuleCallback());244    EXPECT_EQ(m_callback_call_count, 0);245  }246 247  void CheckCallbackArgs(const ModuleSpec &module_spec,248                         FileSpec &module_file_spec, FileSpec &symbol_file_spec,249                         const ModuleSpec &expected_module_spec,250                         int expected_callback_call_count) {251    EXPECT_TRUE(expected_module_spec.Matches(module_spec,252                                             /*exact_arch_match=*/true));253    EXPECT_FALSE(module_file_spec);254    EXPECT_FALSE(symbol_file_spec);255 256    EXPECT_EQ(++m_callback_call_count, expected_callback_call_count);257  }258 259  void CheckCallbackArgsWithUUID(const ModuleSpec &module_spec,260                                 FileSpec &module_file_spec,261                                 FileSpec &symbol_file_spec,262                                 int expected_callback_call_count) {263    CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec,264                      m_module_spec, expected_callback_call_count);265    EXPECT_TRUE(module_spec.GetUUID().IsValid());266  }267 268  void CheckCallbackArgsWithoutUUID(const ModuleSpec &module_spec,269                                    FileSpec &module_file_spec,270                                    FileSpec &symbol_file_spec,271                                    int expected_callback_call_count) {272    CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec,273                      m_module_spec_without_uuid, expected_callback_call_count);274    EXPECT_FALSE(module_spec.GetUUID().IsValid());275  }276 277protected:278  FileSpec m_test_dir;279  DebuggerSP m_debugger_sp;280  PlatformSP m_platform_sp;281  TargetSP m_target_sp;282  ProcessSP m_process_sp;283  ModuleSpec m_module_spec;284  ModuleSpec m_module_spec_without_uuid;285  ModuleSP m_module_sp;286  int m_callback_call_count = 0;287};288 289} // namespace290 291TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModule) {292  // The module file is cached, and the locate module callback is not set.293  // GetOrCreateModule should succeed to return the module from the cache.294  FileSpec uuid_view = BuildCacheDir(m_test_dir);295 296  CheckNoCallback();297 298  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);299  CheckModule(m_module_sp);300  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);301  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());302  CheckStrippedSymbol(m_module_sp);303}304 305TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModuleAndSymbol) {306  // The module and symbol files are cached, and the locate module callback is307  // not set. GetOrCreateModule should succeed to return the module from the308  // cache with the symbol.309  FileSpec uuid_view = BuildCacheDirWithSymbol(m_test_dir);310 311  CheckNoCallback();312 313  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);314  CheckModule(m_module_sp);315  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);316  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view));317  CheckUnstrippedSymbol(m_module_sp);318}319 320TEST_F(LocateModuleCallbackTest,321       GetOrCreateModuleWithCachedModuleAndBreakpadSymbol) {322  // The module file and breakpad symbol file are cached, and the locate module323  // callback is not set. GetOrCreateModule should succeed to return the module324  // from the cache with the symbol.325  FileSpec uuid_view = BuildCacheDirWithBreakpadSymbol(m_test_dir);326 327  CheckNoCallback();328 329  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);330  CheckModule(m_module_sp);331  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);332  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view));333  CheckUnstrippedSymbol(m_module_sp);334}335 336TEST_F(LocateModuleCallbackTest, GetOrCreateModuleFailure) {337  // The cache dir is empty, and the locate module callback is not set.338  // GetOrCreateModule should fail because PlatformAndroid tries to download the339  // module and fails.340  BuildEmptyCacheDir(m_test_dir);341 342  CheckNoCallback();343 344  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);345  ASSERT_FALSE(m_module_sp);346}347 348TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureNoCache) {349  // The cache dir is empty, also the locate module callback fails for some350  // reason. GetOrCreateModule should fail because PlatformAndroid tries to351  // download the module and fails.352  BuildEmptyCacheDir(m_test_dir);353 354  int callback_call_count = 0;355  m_platform_sp->SetLocateModuleCallback(356      [this, &callback_call_count](const ModuleSpec &module_spec,357                                   FileSpec &module_file_spec,358                                   FileSpec &symbol_file_spec) {359        CheckCallbackArgsWithUUID(module_spec, module_file_spec,360                                  symbol_file_spec, ++callback_call_count);361        return Status::FromErrorString("The locate module callback failed");362      });363 364  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);365  ASSERT_EQ(callback_call_count, 3);366  ASSERT_FALSE(m_module_sp);367}368 369TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureCached) {370  // The module file is cached, so GetOrCreateModule should succeed to return371  // the module from the cache even though the locate module callback fails for372  // some reason.373  FileSpec uuid_view = BuildCacheDir(m_test_dir);374 375  int callback_call_count = 0;376  m_platform_sp->SetLocateModuleCallback(377      [this, &callback_call_count](const ModuleSpec &module_spec,378                                   FileSpec &module_file_spec,379                                   FileSpec &symbol_file_spec) {380        CheckCallbackArgsWithUUID(module_spec, module_file_spec,381                                  symbol_file_spec, ++callback_call_count);382        return Status::FromErrorString("The locate module callback failed");383      });384 385  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);386  ASSERT_EQ(callback_call_count, 3);387  CheckModule(m_module_sp);388  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);389  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());390  CheckStrippedSymbol(m_module_sp);391}392 393TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNoFiles) {394  // The module file is cached, so GetOrCreateModule should succeed to return395  // the module from the cache even though the locate module callback returns396  // no files.397  FileSpec uuid_view = BuildCacheDir(m_test_dir);398 399  int callback_call_count = 0;400  m_platform_sp->SetLocateModuleCallback(401      [this, &callback_call_count](const ModuleSpec &module_spec,402                                   FileSpec &module_file_spec,403                                   FileSpec &symbol_file_spec) {404        CheckCallbackArgsWithUUID(module_spec, module_file_spec,405                                  symbol_file_spec, ++callback_call_count);406        // The locate module callback succeeds but it does not set407        // module_file_spec nor symbol_file_spec.408        return Status();409      });410 411  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);412  ASSERT_EQ(callback_call_count, 3);413  CheckModule(m_module_sp);414  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);415  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());416  CheckStrippedSymbol(m_module_sp);417  ModuleList::RemoveSharedModule(m_module_sp);418}419 420TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentModule) {421  // The module file is cached, so GetOrCreateModule should succeed to return422  // the module from the cache even though the locate module callback returns423  // non-existent module file.424  FileSpec uuid_view = BuildCacheDir(m_test_dir);425 426  int callback_call_count = 0;427  m_platform_sp->SetLocateModuleCallback(428      [this, &callback_call_count](const ModuleSpec &module_spec,429                                   FileSpec &module_file_spec,430                                   FileSpec &symbol_file_spec) {431        CheckCallbackArgsWithUUID(module_spec, module_file_spec,432                                  symbol_file_spec, ++callback_call_count);433        module_file_spec.SetPath("/this path does not exist");434        return Status();435      });436 437  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);438  ASSERT_EQ(callback_call_count, 3);439  CheckModule(m_module_sp);440  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);441  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());442  CheckStrippedSymbol(m_module_sp);443  ModuleList::RemoveSharedModule(m_module_sp);444}445 446TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentSymbol) {447  // The module file is cached, so GetOrCreateModule should succeed to return448  // the module from the cache even though the locate module callback returns449  // non-existent symbol file.450  FileSpec uuid_view = BuildCacheDir(m_test_dir);451 452  int callback_call_count = 0;453  m_platform_sp->SetLocateModuleCallback(454      [this, &callback_call_count](const ModuleSpec &module_spec,455                                   FileSpec &module_file_spec,456                                   FileSpec &symbol_file_spec) {457        CheckCallbackArgsWithUUID(module_spec, module_file_spec,458                                  symbol_file_spec, ++callback_call_count);459        // The locate module callback returns a right module file.460        module_file_spec.SetPath(GetInputFilePath(k_module_file));461        // But it returns non-existent symbols file.462        symbol_file_spec.SetPath("/this path does not exist");463        return Status();464      });465 466  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);467  ASSERT_EQ(callback_call_count, 3);468  CheckModule(m_module_sp);469  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);470  ASSERT_TRUE(m_module_sp->GetSymbolFileFileSpec().GetPath().empty());471  CheckStrippedSymbol(m_module_sp);472  ModuleList::RemoveSharedModule(m_module_sp);473}474 475TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackSuccessWithModule) {476  // The locate module callback returns a module file, GetOrCreateModule should477  // succeed to return the module from the Inputs directory.478  BuildEmptyCacheDir(m_test_dir);479 480  m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,481                                                FileSpec &module_file_spec,482                                                FileSpec &symbol_file_spec) {483    CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,484                              1);485    module_file_spec.SetPath(GetInputFilePath(k_module_file));486    return Status();487  });488 489  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);490  CheckModule(m_module_sp);491  ASSERT_EQ(m_module_sp->GetFileSpec(),492            FileSpec(GetInputFilePath(k_module_file)));493  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());494  CheckStrippedSymbol(m_module_sp);495  ModuleList::RemoveSharedModule(m_module_sp);496}497 498TEST_F(LocateModuleCallbackTest,499       GetOrCreateModuleCallbackSuccessWithSymbolAsModule) {500  // The locate module callback returns the symbol file as a module file. It501  // should work since the sections and UUID of the symbol file are the exact502  // same with the module file, GetOrCreateModule should succeed to return the503  // module with the symbol file from Inputs directory.504  BuildEmptyCacheDir(m_test_dir);505 506  m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,507                                                FileSpec &module_file_spec,508                                                FileSpec &symbol_file_spec) {509    CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,510                              1);511    module_file_spec.SetPath(GetInputFilePath(k_symbol_file));512    return Status();513  });514 515  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);516  CheckModule(m_module_sp);517  ASSERT_EQ(m_module_sp->GetFileSpec(),518            FileSpec(GetInputFilePath(k_symbol_file)));519  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());520  CheckUnstrippedSymbol(m_module_sp);521  ModuleList::RemoveSharedModule(m_module_sp);522}523 524TEST_F(LocateModuleCallbackTest,525       GetOrCreateModuleCallbackSuccessWithSymbolAsModuleAndSymbol) {526  // The locate module callback returns a symbol file as both a module file and527  // a symbol file. It should work since the sections and UUID of the symbol528  // file are the exact same with the module file, GetOrCreateModule should529  // succeed to return the module with the symbol file from Inputs directory.530  BuildEmptyCacheDir(m_test_dir);531 532  m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,533                                                FileSpec &module_file_spec,534                                                FileSpec &symbol_file_spec) {535    CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,536                              1);537    module_file_spec.SetPath(GetInputFilePath(k_symbol_file));538    symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));539    return Status();540  });541 542  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);543  CheckModule(m_module_sp);544  ASSERT_EQ(m_module_sp->GetFileSpec(),545            FileSpec(GetInputFilePath(k_symbol_file)));546  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),547            FileSpec(GetInputFilePath(k_symbol_file)));548  CheckUnstrippedSymbol(m_module_sp);549  ModuleList::RemoveSharedModule(m_module_sp);550}551 552TEST_F(LocateModuleCallbackTest,553       GetOrCreateModuleCallbackSuccessWithModuleAndSymbol) {554  // The locate module callback returns a module file and a symbol file,555  // GetOrCreateModule should succeed to return the module from Inputs556  // directory, along with the symbol file.557  BuildEmptyCacheDir(m_test_dir);558 559  m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,560                                                FileSpec &module_file_spec,561                                                FileSpec &symbol_file_spec) {562    CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,563                              1);564    module_file_spec.SetPath(GetInputFilePath(k_module_file));565    symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));566    return Status();567  });568 569  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);570  CheckModule(m_module_sp);571  ASSERT_EQ(m_module_sp->GetFileSpec(),572            FileSpec(GetInputFilePath(k_module_file)));573  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),574            FileSpec(GetInputFilePath(k_symbol_file)));575  CheckUnstrippedSymbol(m_module_sp);576  ModuleList::RemoveSharedModule(m_module_sp);577}578 579TEST_F(LocateModuleCallbackTest,580       GetOrCreateModuleCallbackSuccessWithModuleAndBreakpadSymbol) {581  // The locate module callback returns a module file and a breakpad symbol582  // file, GetOrCreateModule should succeed to return the module with the symbol583  // file from Inputs directory.584  BuildEmptyCacheDir(m_test_dir);585 586  m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,587                                                FileSpec &module_file_spec,588                                                FileSpec &symbol_file_spec) {589    CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,590                              1);591    module_file_spec.SetPath(GetInputFilePath(k_module_file));592    symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));593    return Status();594  });595 596  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);597  CheckModule(m_module_sp);598  ASSERT_EQ(m_module_sp->GetFileSpec(),599            FileSpec(GetInputFilePath(k_module_file)));600  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),601            FileSpec(GetInputFilePath(k_breakpad_symbol_file)));602  CheckUnstrippedSymbol(m_module_sp);603  ModuleList::RemoveSharedModule(m_module_sp);604}605 606TEST_F(LocateModuleCallbackTest,607       GetOrCreateModuleCallbackSuccessWithOnlySymbol) {608  // The get callback returns only a symbol file, and the module is cached,609  // GetOrCreateModule should succeed to return the module from the cache610  // along with the symbol file from the Inputs directory.611  FileSpec uuid_view = BuildCacheDir(m_test_dir);612 613  int callback_call_count = 0;614  m_platform_sp->SetLocateModuleCallback(615      [this, &callback_call_count](const ModuleSpec &module_spec,616                                   FileSpec &module_file_spec,617                                   FileSpec &symbol_file_spec) {618        CheckCallbackArgsWithUUID(module_spec, module_file_spec,619                                  symbol_file_spec, ++callback_call_count);620        symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));621        return Status();622      });623 624  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);625  ASSERT_EQ(callback_call_count, 3);626  CheckModule(m_module_sp);627  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);628  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),629            FileSpec(GetInputFilePath(k_symbol_file)));630  CheckUnstrippedSymbol(m_module_sp);631  ModuleList::RemoveSharedModule(m_module_sp);632}633 634TEST_F(LocateModuleCallbackTest,635       GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbol) {636  // The get callback returns only a breakpad symbol file, and the module is637  // cached, GetOrCreateModule should succeed to return the module from the638  // cache along with the symbol file from the Inputs directory.639  FileSpec uuid_view = BuildCacheDir(m_test_dir);640 641  int callback_call_count = 0;642  m_platform_sp->SetLocateModuleCallback(643      [this, &callback_call_count](const ModuleSpec &module_spec,644                                   FileSpec &module_file_spec,645                                   FileSpec &symbol_file_spec) {646        CheckCallbackArgsWithUUID(module_spec, module_file_spec,647                                  symbol_file_spec, ++callback_call_count);648        symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));649        return Status();650      });651 652  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);653  ASSERT_EQ(callback_call_count, 3);654  CheckModule(m_module_sp);655  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);656  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),657            FileSpec(GetInputFilePath(k_breakpad_symbol_file)));658  CheckUnstrippedSymbol(m_module_sp);659  ModuleList::RemoveSharedModule(m_module_sp);660}661 662TEST_F(LocateModuleCallbackTest,663       GetOrCreateModuleCallbackSuccessWithMultipleSymbols) {664  // The get callback returns only a symbol file. The first call returns665  // a breakpad symbol file and the second call returns a symbol file.666  // Also the module is cached, so GetOrCreateModule should succeed to return667  // the module from the cache along with the breakpad symbol file from the668  // Inputs directory because GetOrCreateModule will use the first symbol file669  // from the callback.670  FileSpec uuid_view = BuildCacheDir(m_test_dir);671 672  int callback_call_count = 0;673  m_platform_sp->SetLocateModuleCallback(674      [this, &callback_call_count](const ModuleSpec &module_spec,675                                   FileSpec &module_file_spec,676                                   FileSpec &symbol_file_spec) {677        CheckCallbackArgsWithUUID(module_spec, module_file_spec,678                                  symbol_file_spec, ++callback_call_count);679        symbol_file_spec.SetPath(GetInputFilePath(680            callback_call_count == 1 ? k_breakpad_symbol_file : k_symbol_file));681        return Status();682      });683 684  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);685  ASSERT_EQ(callback_call_count, 3);686  CheckModule(m_module_sp);687  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);688  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),689            FileSpec(GetInputFilePath(k_breakpad_symbol_file)));690  CheckUnstrippedSymbol(m_module_sp);691  ModuleList::RemoveSharedModule(m_module_sp);692}693 694TEST_F(LocateModuleCallbackTest,695       GetOrCreateModuleNoCacheWithCallbackOnlySymbol) {696  // The get callback returns only a symbol file, but the module is not697  // cached, GetOrCreateModule should fail because of the missing module.698  BuildEmptyCacheDir(m_test_dir);699 700  int callback_call_count = 0;701  m_platform_sp->SetLocateModuleCallback(702      [this, &callback_call_count](const ModuleSpec &module_spec,703                                   FileSpec &module_file_spec,704                                   FileSpec &symbol_file_spec) {705        CheckCallbackArgsWithUUID(module_spec, module_file_spec,706                                  symbol_file_spec, ++callback_call_count);707        symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));708        return Status();709      });710 711  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);712  ASSERT_EQ(callback_call_count, 3);713  ASSERT_FALSE(m_module_sp);714}715 716TEST_F(LocateModuleCallbackTest,717       GetOrCreateModuleNoCacheWithCallbackOnlyBreakpadSymbol) {718  // The get callback returns only a breakpad symbol file, but the module is not719  // cached, GetOrCreateModule should fail because of the missing module.720  BuildEmptyCacheDir(m_test_dir);721 722  int callback_call_count = 0;723  m_platform_sp->SetLocateModuleCallback(724      [this, &callback_call_count](const ModuleSpec &module_spec,725                                   FileSpec &module_file_spec,726                                   FileSpec &symbol_file_spec) {727        CheckCallbackArgsWithUUID(module_spec, module_file_spec,728                                  symbol_file_spec, ++callback_call_count);729        symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));730        return Status();731      });732 733  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);734  ASSERT_EQ(callback_call_count, 3);735  ASSERT_FALSE(m_module_sp);736}737 738TEST_F(LocateModuleCallbackTest,739       GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID) {740  // This is a simulation for Android remote platform debugging.741  // The locate module callback first call fails because module_spec does not742  // have UUID. Then, the callback second call returns a module file because the743  // platform resolved the module_spec UUID from the target process.744  // GetOrCreateModule should succeed to return the module from the Inputs745  // directory.746  BuildEmptyCacheDir(m_test_dir);747 748  int callback_call_count = 0;749  m_platform_sp->SetLocateModuleCallback(750      [this, &callback_call_count](const ModuleSpec &module_spec,751                                   FileSpec &module_file_spec,752                                   FileSpec &symbol_file_spec) {753        callback_call_count++;754        if (callback_call_count == 1) {755          // The module_spec does not have UUID on the first call.756          CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,757                                       symbol_file_spec, callback_call_count);758          return Status::FromErrorString("Ignored empty UUID");759        } else {760          // The module_spec has UUID on the second call.761          CheckCallbackArgsWithUUID(module_spec, module_file_spec,762                                    symbol_file_spec, callback_call_count);763          module_file_spec.SetPath(GetInputFilePath(k_module_file));764          return Status();765        }766      });767 768  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,769                                               /*notify=*/false);770  ASSERT_EQ(callback_call_count, 2);771  CheckModule(m_module_sp);772  ASSERT_EQ(m_module_sp->GetFileSpec(),773            FileSpec(GetInputFilePath(k_module_file)));774  ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());775  CheckStrippedSymbol(m_module_sp);776  ModuleList::RemoveSharedModule(m_module_sp);777}778 779TEST_F(LocateModuleCallbackTest,780       GetOrCreateModuleCallbackSuccessWithSymbolByPlatformUUID) {781  // Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID,782  // but with a symbol file. GetOrCreateModule should succeed to return the783  // module file and the symbol file from the Inputs directory.784  BuildEmptyCacheDir(m_test_dir);785 786  int callback_call_count = 0;787  m_platform_sp->SetLocateModuleCallback(788      [this, &callback_call_count](const ModuleSpec &module_spec,789                                   FileSpec &module_file_spec,790                                   FileSpec &symbol_file_spec) {791        callback_call_count++;792        if (callback_call_count == 1) {793          // The module_spec does not have UUID on the first call.794          CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,795                                       symbol_file_spec, callback_call_count);796          return Status::FromErrorString("Ignored empty UUID");797        } else {798          // The module_spec has UUID on the second call.799          CheckCallbackArgsWithUUID(module_spec, module_file_spec,800                                    symbol_file_spec, callback_call_count);801          module_file_spec.SetPath(GetInputFilePath(k_module_file));802          symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));803          return Status();804        }805      });806 807  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,808                                               /*notify=*/false);809  ASSERT_EQ(callback_call_count, 2);810  CheckModule(m_module_sp);811  ASSERT_EQ(m_module_sp->GetFileSpec(),812            FileSpec(GetInputFilePath(k_module_file)));813  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),814            FileSpec(GetInputFilePath(k_symbol_file)));815  CheckUnstrippedSymbol(m_module_sp);816  ModuleList::RemoveSharedModule(m_module_sp);817}818 819TEST_F(LocateModuleCallbackTest,820       GetOrCreateModuleCallbackSuccessWithBreakpadSymbolByPlatformUUID) {821  // Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID,822  // but with a breakpad symbol file. GetOrCreateModule should succeed to return823  // the module file and the symbol file from the Inputs directory.824  BuildEmptyCacheDir(m_test_dir);825 826  int callback_call_count = 0;827  m_platform_sp->SetLocateModuleCallback(828      [this, &callback_call_count](const ModuleSpec &module_spec,829                                   FileSpec &module_file_spec,830                                   FileSpec &symbol_file_spec) {831        callback_call_count++;832        if (callback_call_count == 1) {833          // The module_spec does not have UUID on the first call.834          CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,835                                       symbol_file_spec, callback_call_count);836          return Status::FromErrorString("Ignored empty UUID");837        } else {838          // The module_spec has UUID on the second call.839          CheckCallbackArgsWithUUID(module_spec, module_file_spec,840                                    symbol_file_spec, callback_call_count);841          module_file_spec.SetPath(GetInputFilePath(k_module_file));842          symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));843          return Status();844        }845      });846 847  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,848                                               /*notify=*/false);849  ASSERT_EQ(callback_call_count, 2);850  CheckModule(m_module_sp);851  ASSERT_EQ(m_module_sp->GetFileSpec(),852            FileSpec(GetInputFilePath(k_module_file)));853  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),854            FileSpec(GetInputFilePath(k_breakpad_symbol_file)));855  CheckUnstrippedSymbol(m_module_sp);856  ModuleList::RemoveSharedModule(m_module_sp);857}858 859TEST_F(LocateModuleCallbackTest,860       GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbolByPlatformUUID) {861  // This is a simulation for Android remote platform debugging.862  // The locate module callback first call fails because module_spec does not863  // have UUID. Then, the callback second call returns a breakpad symbol file864  // for the UUID from the target process. GetOrCreateModule should succeed to865  // return the module from the cache along with the symbol file from the Inputs866  // directory.867  FileSpec uuid_view = BuildCacheDir(m_test_dir);868 869  int callback_call_count = 0;870  m_platform_sp->SetLocateModuleCallback(871      [this, &callback_call_count](const ModuleSpec &module_spec,872                                   FileSpec &module_file_spec,873                                   FileSpec &symbol_file_spec) {874        callback_call_count++;875        if (callback_call_count == 1) {876          // The module_spec does not have UUID on the first call.877          CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,878                                       symbol_file_spec, callback_call_count);879          return Status::FromErrorString("Ignored empty UUID");880        } else {881          // The module_spec has UUID on the second call.882          CheckCallbackArgsWithUUID(module_spec, module_file_spec,883                                    symbol_file_spec, callback_call_count);884          symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));885          return Status();886        }887      });888 889  m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,890                                               /*notify=*/false);891  ASSERT_EQ(callback_call_count, 2);892  CheckModule(m_module_sp);893  ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);894  ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),895            FileSpec(GetInputFilePath(k_breakpad_symbol_file)));896  CheckUnstrippedSymbol(m_module_sp);897  ModuleList::RemoveSharedModule(m_module_sp);898}899