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