899 lines
37 KiB
C++
899 lines
37 KiB
C++
|
//===-- LocateModuleCallbackTest.cpp --------------------------------------===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
|
||
|
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
|
||
|
#include "Plugins/Platform/Android/PlatformAndroid.h"
|
||
|
#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
|
||
|
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
|
||
|
#include "TestingSupport/SubsystemRAII.h"
|
||
|
#include "TestingSupport/TestUtilities.h"
|
||
|
#include "lldb/Core/Debugger.h"
|
||
|
#include "lldb/Core/PluginManager.h"
|
||
|
#include "lldb/Host/HostInfo.h"
|
||
|
#include "lldb/Target/Target.h"
|
||
|
#include "gmock/gmock.h"
|
||
|
|
||
|
using namespace lldb;
|
||
|
using namespace lldb_private;
|
||
|
using namespace lldb_private::platform_android;
|
||
|
using namespace lldb_private::platform_linux;
|
||
|
using namespace lldb_private::breakpad;
|
||
|
using namespace testing;
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
constexpr llvm::StringLiteral k_process_plugin("mock-process-plugin");
|
||
|
constexpr llvm::StringLiteral k_platform_dir("remote-android");
|
||
|
constexpr llvm::StringLiteral k_cache_dir(".cache");
|
||
|
constexpr llvm::StringLiteral k_module_file("AndroidModule.so");
|
||
|
constexpr llvm::StringLiteral k_symbol_file("AndroidModule.unstripped.so");
|
||
|
constexpr llvm::StringLiteral k_breakpad_symbol_file("AndroidModule.so.sym");
|
||
|
constexpr llvm::StringLiteral k_arch("aarch64-none-linux");
|
||
|
constexpr llvm::StringLiteral
|
||
|
k_module_uuid("80008338-82A0-51E5-5922-C905D23890DA-BDDEFECC");
|
||
|
constexpr llvm::StringLiteral k_function_symbol("boom");
|
||
|
constexpr llvm::StringLiteral k_hidden_function_symbol("boom_hidden");
|
||
|
const size_t k_module_size = 3784;
|
||
|
|
||
|
ModuleSpec GetTestModuleSpec();
|
||
|
|
||
|
class MockProcess : public Process {
|
||
|
public:
|
||
|
MockProcess(TargetSP target_sp, ListenerSP listener_sp)
|
||
|
: Process(target_sp, listener_sp) {}
|
||
|
|
||
|
llvm::StringRef GetPluginName() override { return k_process_plugin; };
|
||
|
|
||
|
bool CanDebug(TargetSP target, bool plugin_specified_by_name) override {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
Status DoDestroy() override { return Status(); }
|
||
|
|
||
|
void RefreshStateAfterStop() override {}
|
||
|
|
||
|
bool DoUpdateThreadList(ThreadList &old_thread_list,
|
||
|
ThreadList &new_thread_list) override {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
|
||
|
Status &error) override {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch,
|
||
|
ModuleSpec &module_spec) override {
|
||
|
module_spec = GetTestModuleSpec();
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
FileSpec GetTestDir() {
|
||
|
const auto *info = UnitTest::GetInstance()->current_test_info();
|
||
|
FileSpec test_dir = HostInfo::GetProcessTempDir();
|
||
|
test_dir.AppendPathComponent(std::string(info->test_case_name()) + "-" +
|
||
|
info->name());
|
||
|
std::error_code ec = llvm::sys::fs::create_directory(test_dir.GetPath());
|
||
|
EXPECT_FALSE(ec);
|
||
|
return test_dir;
|
||
|
}
|
||
|
|
||
|
FileSpec GetRemotePath() {
|
||
|
FileSpec fs("/", FileSpec::Style::posix);
|
||
|
fs.AppendPathComponent("bin");
|
||
|
fs.AppendPathComponent(k_module_file);
|
||
|
return fs;
|
||
|
}
|
||
|
|
||
|
FileSpec GetUuidView(FileSpec spec) {
|
||
|
spec.AppendPathComponent(k_platform_dir);
|
||
|
spec.AppendPathComponent(k_cache_dir);
|
||
|
spec.AppendPathComponent(k_module_uuid);
|
||
|
spec.AppendPathComponent(k_module_file);
|
||
|
return spec;
|
||
|
}
|
||
|
|
||
|
void BuildEmptyCacheDir(const FileSpec &test_dir) {
|
||
|
FileSpec cache_dir(test_dir);
|
||
|
cache_dir.AppendPathComponent(k_platform_dir);
|
||
|
cache_dir.AppendPathComponent(k_cache_dir);
|
||
|
std::error_code ec = llvm::sys::fs::create_directories(cache_dir.GetPath());
|
||
|
EXPECT_FALSE(ec);
|
||
|
}
|
||
|
|
||
|
FileSpec BuildCacheDir(const FileSpec &test_dir) {
|
||
|
FileSpec uuid_view = GetUuidView(test_dir);
|
||
|
std::error_code ec =
|
||
|
llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
|
||
|
EXPECT_FALSE(ec);
|
||
|
ec = llvm::sys::fs::copy_file(GetInputFilePath(k_module_file),
|
||
|
uuid_view.GetPath().c_str());
|
||
|
EXPECT_FALSE(ec);
|
||
|
return uuid_view;
|
||
|
}
|
||
|
|
||
|
FileSpec GetSymFileSpec(const FileSpec &uuid_view) {
|
||
|
return FileSpec(uuid_view.GetPath() + ".sym");
|
||
|
}
|
||
|
|
||
|
FileSpec BuildCacheDirWithSymbol(const FileSpec &test_dir) {
|
||
|
FileSpec uuid_view = BuildCacheDir(test_dir);
|
||
|
std::error_code ec =
|
||
|
llvm::sys::fs::copy_file(GetInputFilePath(k_symbol_file),
|
||
|
GetSymFileSpec(uuid_view).GetPath().c_str());
|
||
|
EXPECT_FALSE(ec);
|
||
|
return uuid_view;
|
||
|
}
|
||
|
|
||
|
FileSpec BuildCacheDirWithBreakpadSymbol(const FileSpec &test_dir) {
|
||
|
FileSpec uuid_view = BuildCacheDir(test_dir);
|
||
|
std::error_code ec =
|
||
|
llvm::sys::fs::copy_file(GetInputFilePath(k_breakpad_symbol_file),
|
||
|
GetSymFileSpec(uuid_view).GetPath().c_str());
|
||
|
EXPECT_FALSE(ec);
|
||
|
return uuid_view;
|
||
|
}
|
||
|
|
||
|
ModuleSpec GetTestModuleSpec() {
|
||
|
ModuleSpec module_spec(GetRemotePath(), ArchSpec(k_arch));
|
||
|
module_spec.GetUUID().SetFromStringRef(k_module_uuid);
|
||
|
module_spec.SetObjectSize(k_module_size);
|
||
|
return module_spec;
|
||
|
}
|
||
|
|
||
|
void CheckModule(const ModuleSP &module_sp) {
|
||
|
ASSERT_TRUE(module_sp);
|
||
|
ASSERT_EQ(module_sp->GetUUID().GetAsString(), k_module_uuid);
|
||
|
ASSERT_EQ(module_sp->GetObjectOffset(), 0U);
|
||
|
ASSERT_EQ(module_sp->GetPlatformFileSpec(), GetRemotePath());
|
||
|
}
|
||
|
|
||
|
SymbolContextList FindFunctions(const ModuleSP &module_sp,
|
||
|
const llvm::StringRef &name) {
|
||
|
SymbolContextList sc_list;
|
||
|
ModuleFunctionSearchOptions function_options;
|
||
|
function_options.include_symbols = true;
|
||
|
function_options.include_inlines = true;
|
||
|
FunctionNameType type = static_cast<FunctionNameType>(eSymbolTypeCode);
|
||
|
module_sp->FindFunctions(ConstString(name), CompilerDeclContext(), type,
|
||
|
function_options, sc_list);
|
||
|
return sc_list;
|
||
|
}
|
||
|
|
||
|
void CheckStrippedSymbol(const ModuleSP &module_sp) {
|
||
|
SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol);
|
||
|
EXPECT_EQ(1U, sc_list.GetSize());
|
||
|
|
||
|
sc_list = FindFunctions(module_sp, k_hidden_function_symbol);
|
||
|
EXPECT_EQ(0U, sc_list.GetSize());
|
||
|
}
|
||
|
|
||
|
void CheckUnstrippedSymbol(const ModuleSP &module_sp) {
|
||
|
SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol);
|
||
|
EXPECT_EQ(1U, sc_list.GetSize());
|
||
|
|
||
|
sc_list = FindFunctions(module_sp, k_hidden_function_symbol);
|
||
|
EXPECT_EQ(1U, sc_list.GetSize());
|
||
|
}
|
||
|
|
||
|
ProcessSP MockProcessCreateInstance(TargetSP target_sp, ListenerSP listener_sp,
|
||
|
const FileSpec *crash_file_path,
|
||
|
bool can_connect) {
|
||
|
return std::make_shared<MockProcess>(target_sp, listener_sp);
|
||
|
}
|
||
|
|
||
|
class LocateModuleCallbackTest : public testing::Test {
|
||
|
SubsystemRAII<FileSystem, HostInfo, ObjectFileBreakpad, ObjectFileELF,
|
||
|
PlatformAndroid, PlatformLinux, SymbolFileBreakpad,
|
||
|
SymbolFileSymtab>
|
||
|
subsystems;
|
||
|
|
||
|
public:
|
||
|
void SetUp() override {
|
||
|
m_test_dir = GetTestDir();
|
||
|
|
||
|
// Set module cache directory for PlatformAndroid.
|
||
|
PlatformAndroid::GetGlobalPlatformProperties().SetModuleCacheDirectory(
|
||
|
m_test_dir);
|
||
|
|
||
|
// Create Debugger.
|
||
|
ArchSpec host_arch("i386-pc-linux");
|
||
|
Platform::SetHostPlatform(
|
||
|
platform_linux::PlatformLinux::CreateInstance(true, &host_arch));
|
||
|
m_debugger_sp = Debugger::CreateInstance();
|
||
|
EXPECT_TRUE(m_debugger_sp);
|
||
|
|
||
|
// Create PlatformAndroid.
|
||
|
ArchSpec arch(k_arch);
|
||
|
m_platform_sp = PlatformAndroid::CreateInstance(true, &arch);
|
||
|
EXPECT_TRUE(m_platform_sp);
|
||
|
|
||
|
// Create Target.
|
||
|
m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,
|
||
|
eLoadDependentsNo,
|
||
|
m_platform_sp, m_target_sp);
|
||
|
EXPECT_TRUE(m_target_sp);
|
||
|
|
||
|
// Create MockProcess.
|
||
|
PluginManager::RegisterPlugin(k_process_plugin, "",
|
||
|
MockProcessCreateInstance);
|
||
|
m_process_sp =
|
||
|
m_target_sp->CreateProcess(Listener::MakeListener("test-listener"),
|
||
|
k_process_plugin, /*crash_file=*/nullptr,
|
||
|
/*can_connect=*/true);
|
||
|
EXPECT_TRUE(m_process_sp);
|
||
|
|
||
|
m_module_spec = GetTestModuleSpec();
|
||
|
m_module_spec_without_uuid = ModuleSpec(GetRemotePath(), ArchSpec(k_arch));
|
||
|
}
|
||
|
|
||
|
void TearDown() override {
|
||
|
if (m_module_sp)
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
void CheckNoCallback() {
|
||
|
EXPECT_FALSE(m_platform_sp->GetLocateModuleCallback());
|
||
|
EXPECT_EQ(m_callback_call_count, 0);
|
||
|
}
|
||
|
|
||
|
void CheckCallbackArgs(const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec, FileSpec &symbol_file_spec,
|
||
|
const ModuleSpec &expected_module_spec,
|
||
|
int expected_callback_call_count) {
|
||
|
EXPECT_TRUE(expected_module_spec.Matches(module_spec,
|
||
|
/*exact_arch_match=*/true));
|
||
|
EXPECT_FALSE(module_file_spec);
|
||
|
EXPECT_FALSE(symbol_file_spec);
|
||
|
|
||
|
EXPECT_EQ(++m_callback_call_count, expected_callback_call_count);
|
||
|
}
|
||
|
|
||
|
void CheckCallbackArgsWithUUID(const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec,
|
||
|
int expected_callback_call_count) {
|
||
|
CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec,
|
||
|
m_module_spec, expected_callback_call_count);
|
||
|
EXPECT_TRUE(module_spec.GetUUID().IsValid());
|
||
|
}
|
||
|
|
||
|
void CheckCallbackArgsWithoutUUID(const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec,
|
||
|
int expected_callback_call_count) {
|
||
|
CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec,
|
||
|
m_module_spec_without_uuid, expected_callback_call_count);
|
||
|
EXPECT_FALSE(module_spec.GetUUID().IsValid());
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
FileSpec m_test_dir;
|
||
|
DebuggerSP m_debugger_sp;
|
||
|
PlatformSP m_platform_sp;
|
||
|
TargetSP m_target_sp;
|
||
|
ProcessSP m_process_sp;
|
||
|
ModuleSpec m_module_spec;
|
||
|
ModuleSpec m_module_spec_without_uuid;
|
||
|
ModuleSP m_module_sp;
|
||
|
int m_callback_call_count = 0;
|
||
|
};
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModule) {
|
||
|
// The module file is cached, and the locate module callback is not set.
|
||
|
// GetOrCreateModule should succeed to return the module from the cache.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
CheckNoCallback();
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModuleAndSymbol) {
|
||
|
// The module and symbol files are cached, and the locate module callback is
|
||
|
// not set. GetOrCreateModule should succeed to return the module from the
|
||
|
// cache with the symbol.
|
||
|
FileSpec uuid_view = BuildCacheDirWithSymbol(m_test_dir);
|
||
|
|
||
|
CheckNoCallback();
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleWithCachedModuleAndBreakpadSymbol) {
|
||
|
// The module file and breakpad symbol file are cached, and the locate module
|
||
|
// callback is not set. GetOrCreateModule should succeed to return the module
|
||
|
// from the cache with the symbol.
|
||
|
FileSpec uuid_view = BuildCacheDirWithBreakpadSymbol(m_test_dir);
|
||
|
|
||
|
CheckNoCallback();
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleFailure) {
|
||
|
// The cache dir is empty, and the locate module callback is not set.
|
||
|
// GetOrCreateModule should fail because PlatformAndroid tries to download the
|
||
|
// module and fails.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
CheckNoCallback();
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_FALSE(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureNoCache) {
|
||
|
// The cache dir is empty, also the locate module callback fails for some
|
||
|
// reason. GetOrCreateModule should fail because PlatformAndroid tries to
|
||
|
// download the module and fails.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
return Status("The locate module callback failed");
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
ASSERT_FALSE(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureCached) {
|
||
|
// The module file is cached, so GetOrCreateModule should succeed to return
|
||
|
// the module from the cache even though the locate module callback fails for
|
||
|
// some reason.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
return Status("The locate module callback failed");
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNoFiles) {
|
||
|
// The module file is cached, so GetOrCreateModule should succeed to return
|
||
|
// the module from the cache even though the locate module callback returns
|
||
|
// no files.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
// The locate module callback succeeds but it does not set
|
||
|
// module_file_spec nor symbol_file_spec.
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentModule) {
|
||
|
// The module file is cached, so GetOrCreateModule should succeed to return
|
||
|
// the module from the cache even though the locate module callback returns
|
||
|
// non-existent module file.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
module_file_spec.SetPath("/this path does not exist");
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentSymbol) {
|
||
|
// The module file is cached, so GetOrCreateModule should succeed to return
|
||
|
// the module from the cache even though the locate module callback returns
|
||
|
// non-existent symbol file.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
// The locate module callback returns a right module file.
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
// But it returns non-existent symbols file.
|
||
|
symbol_file_spec.SetPath("/this path does not exist");
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_TRUE(m_module_sp->GetSymbolFileFileSpec().GetPath().empty());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackSuccessWithModule) {
|
||
|
// The locate module callback returns a module file, GetOrCreateModule should
|
||
|
// succeed to return the module from the Inputs directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
|
||
|
1);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_module_file)));
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithSymbolAsModule) {
|
||
|
// The locate module callback returns the symbol file as a module file. It
|
||
|
// should work since the sections and UUID of the symbol file are the exact
|
||
|
// same with the module file, GetOrCreateModule should succeed to return the
|
||
|
// module with the symbol file from Inputs directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
|
||
|
1);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_symbol_file)));
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithSymbolAsModuleAndSymbol) {
|
||
|
// The locate module callback returns a symbol file as both a module file and
|
||
|
// a symbol file. It should work since the sections and UUID of the symbol
|
||
|
// file are the exact same with the module file, GetOrCreateModule should
|
||
|
// succeed to return the module with the symbol file from Inputs directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
|
||
|
1);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_symbol_file)));
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithModuleAndSymbol) {
|
||
|
// The locate module callback returns a module file and a symbol file,
|
||
|
// GetOrCreateModule should succeed to return the module from Inputs
|
||
|
// directory, along with the symbol file.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
|
||
|
1);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_module_file)));
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithModuleAndBreakpadSymbol) {
|
||
|
// The locate module callback returns a module file and a breakpad symbol
|
||
|
// file, GetOrCreateModule should succeed to return the module with the symbol
|
||
|
// file from Inputs directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
|
||
|
1);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_module_file)));
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithOnlySymbol) {
|
||
|
// The get callback returns only a symbol file, and the module is cached,
|
||
|
// GetOrCreateModule should succeed to return the module from the cache
|
||
|
// along with the symbol file from the Inputs directory.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbol) {
|
||
|
// The get callback returns only a breakpad symbol file, and the module is
|
||
|
// cached, GetOrCreateModule should succeed to return the module from the
|
||
|
// cache along with the symbol file from the Inputs directory.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithMultipleSymbols) {
|
||
|
// The get callback returns only a symbol file. The first call returns
|
||
|
// a breakpad symbol file and the second call returns a symbol file.
|
||
|
// Also the module is cached, so GetOrCreateModule should succeed to return
|
||
|
// the module from the cache along with the breakpad symbol file from the
|
||
|
// Inputs directory because GetOrCreateModule will use the first symbol file
|
||
|
// from the callback.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(
|
||
|
callback_call_count == 1 ? k_breakpad_symbol_file : k_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleNoCacheWithCallbackOnlySymbol) {
|
||
|
// The get callback returns only a symbol file, but the module is not
|
||
|
// cached, GetOrCreateModule should fail because of the missing module.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
ASSERT_FALSE(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleNoCacheWithCallbackOnlyBreakpadSymbol) {
|
||
|
// The get callback returns only a breakpad symbol file, but the module is not
|
||
|
// cached, GetOrCreateModule should fail because of the missing module.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, ++callback_call_count);
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
|
||
|
return Status();
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
ASSERT_FALSE(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID) {
|
||
|
// This is a simulation for Android remote platform debugging.
|
||
|
// The locate module callback first call fails because module_spec does not
|
||
|
// have UUID. Then, the callback second call returns a module file because the
|
||
|
// platform resolved the module_spec UUID from the target process.
|
||
|
// GetOrCreateModule should succeed to return the module from the Inputs
|
||
|
// directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
callback_call_count++;
|
||
|
if (callback_call_count == 1) {
|
||
|
// The module_spec does not have UUID on the first call.
|
||
|
CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
return Status("Ignored empty UUID");
|
||
|
} else {
|
||
|
// The module_spec has UUID on the second call.
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
return Status();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
|
||
|
/*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_module_file)));
|
||
|
ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
|
||
|
CheckStrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithSymbolByPlatformUUID) {
|
||
|
// Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID,
|
||
|
// but with a symbol file. GetOrCreateModule should succeed to return the
|
||
|
// module file and the symbol file from the Inputs directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
callback_call_count++;
|
||
|
if (callback_call_count == 1) {
|
||
|
// The module_spec does not have UUID on the first call.
|
||
|
CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
return Status("Ignored empty UUID");
|
||
|
} else {
|
||
|
// The module_spec has UUID on the second call.
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
|
||
|
return Status();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
|
||
|
/*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_module_file)));
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithBreakpadSymbolByPlatformUUID) {
|
||
|
// Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID,
|
||
|
// but with a breakpad symbol file. GetOrCreateModule should succeed to return
|
||
|
// the module file and the symbol file from the Inputs directory.
|
||
|
BuildEmptyCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
callback_call_count++;
|
||
|
if (callback_call_count == 1) {
|
||
|
// The module_spec does not have UUID on the first call.
|
||
|
CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
return Status("Ignored empty UUID");
|
||
|
} else {
|
||
|
// The module_spec has UUID on the second call.
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
module_file_spec.SetPath(GetInputFilePath(k_module_file));
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
|
||
|
return Status();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
|
||
|
/*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_module_file)));
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|
||
|
|
||
|
TEST_F(LocateModuleCallbackTest,
|
||
|
GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbolByPlatformUUID) {
|
||
|
// This is a simulation for Android remote platform debugging.
|
||
|
// The locate module callback first call fails because module_spec does not
|
||
|
// have UUID. Then, the callback second call returns a breakpad symbol file
|
||
|
// for the UUID from the target process. GetOrCreateModule should succeed to
|
||
|
// return the module from the cache along with the symbol file from the Inputs
|
||
|
// directory.
|
||
|
FileSpec uuid_view = BuildCacheDir(m_test_dir);
|
||
|
|
||
|
int callback_call_count = 0;
|
||
|
m_platform_sp->SetLocateModuleCallback(
|
||
|
[this, &callback_call_count](const ModuleSpec &module_spec,
|
||
|
FileSpec &module_file_spec,
|
||
|
FileSpec &symbol_file_spec) {
|
||
|
callback_call_count++;
|
||
|
if (callback_call_count == 1) {
|
||
|
// The module_spec does not have UUID on the first call.
|
||
|
CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
return Status("Ignored empty UUID");
|
||
|
} else {
|
||
|
// The module_spec has UUID on the second call.
|
||
|
CheckCallbackArgsWithUUID(module_spec, module_file_spec,
|
||
|
symbol_file_spec, callback_call_count);
|
||
|
symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
|
||
|
return Status();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
|
||
|
/*notify=*/false);
|
||
|
ASSERT_EQ(callback_call_count, 2);
|
||
|
CheckModule(m_module_sp);
|
||
|
ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
|
||
|
ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
|
||
|
FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
|
||
|
CheckUnstrippedSymbol(m_module_sp);
|
||
|
ModuleList::RemoveSharedModule(m_module_sp);
|
||
|
}
|