llvm-project/lldb/unittests/Target/ModuleCacheTest.cpp
Jaroslav Sevcik 1beffc1888 Support build-ids of other sizes than 16 in UUID::SetFromStringRef
SBTarget::AddModule currently handles the UUID parameter in a very
weird way: UUIDs with more than 16 bytes are trimmed to 16 bytes. On
the other hand, shorter-than-16-bytes UUIDs are completely ignored. In
this patch, we change the parsing code to handle UUIDs of arbitrary
size.

To support arbitrary size UUIDs in SBTarget::AddModule, this patch
changes UUID::SetFromStringRef to parse UUIDs of arbitrary length. We
subtly change the semantics of SetFromStringRef - SetFromStringRef now
only succeeds if the entire input is consumed to prevent some
prefix-parsing confusion. This is up for discussion, but I believe
this is more consistent - we always return false for invalid UUIDs
rather than sometimes truncating to a valid prefix. Also, all the
call-sites except the API and interpreter seem to expect to consume
the entire input.

This also adds tests for adding existing modules 4-, 16-, and 20-byte
build-ids. Finally, we took the liberty of testing the minidump
scenario we care about - removing placeholder module from minidump and
replacing it with the real module.

Reviewed By: labath, friss

Differential Revision: https://reviews.llvm.org/D80755
2020-06-07 10:03:41 +00:00

159 lines
5.2 KiB
C++

#include "gtest/gtest.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
#include "TestingSupport/SubsystemRAII.h"
#include "TestingSupport/TestUtilities.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ModuleCache.h"
using namespace lldb_private;
using namespace lldb;
namespace {
class ModuleCacheTest : public testing::Test {
SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
subsystems;
public:
void SetUp() override;
protected:
FileSpec s_cache_dir;
std::string s_test_executable;
void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
bool expect_download);
};
}
static const char dummy_hostname[] = "dummy_hostname";
static const char dummy_remote_dir[] = "bin";
static const char module_name[] = "TestModule.so";
static const char module_uuid[] =
"F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
static const size_t module_size = 5602;
static FileSpec GetDummyRemotePath() {
FileSpec fs("/", FileSpec::Style::posix);
fs.AppendPathComponent(dummy_remote_dir);
fs.AppendPathComponent(module_name);
return fs;
}
static FileSpec GetUuidView(FileSpec spec) {
spec.AppendPathComponent(".cache");
spec.AppendPathComponent(module_uuid);
spec.AppendPathComponent(module_name);
return spec;
}
static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
spec.AppendPathComponent(hostname);
spec.AppendPathComponent(dummy_remote_dir);
spec.AppendPathComponent(module_name);
return spec;
}
void ModuleCacheTest::SetUp() {
s_cache_dir = HostInfo::GetProcessTempDir();
s_test_executable = GetInputFilePath(module_name);
}
static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
FileSpec uuid_view = GetUuidView(cache_dir);
EXPECT_TRUE(FileSystem::Instance().Exists(uuid_view))
<< "uuid_view is: " << uuid_view.GetCString();
EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(uuid_view));
FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
EXPECT_TRUE(FileSystem::Instance().Exists(sysroot_view))
<< "sysroot_view is: " << sysroot_view.GetCString();
EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(sysroot_view));
}
void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
const char *hostname, bool expect_download) {
ModuleCache mc;
ModuleSpec module_spec;
module_spec.GetFileSpec() = GetDummyRemotePath();
module_spec.GetUUID().SetFromStringRef(module_uuid);
module_spec.SetObjectSize(module_size);
ModuleSP module_sp;
bool did_create;
bool download_called = false;
Status error = mc.GetAndPut(
cache_dir, hostname, module_spec,
[&download_called, this](const ModuleSpec &module_spec,
const FileSpec &tmp_download_file_spec) {
download_called = true;
EXPECT_STREQ(GetDummyRemotePath().GetCString(),
module_spec.GetFileSpec().GetCString());
std::error_code ec = llvm::sys::fs::copy_file(
s_test_executable, tmp_download_file_spec.GetCString());
EXPECT_FALSE(ec);
return Status();
},
[](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
return Status("Not supported.");
},
module_sp, &did_create);
EXPECT_EQ(expect_download, download_called);
EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
EXPECT_TRUE(did_create);
ASSERT_TRUE(bool(module_sp));
SymbolContextList sc_list;
module_sp->FindFunctionSymbols(ConstString("boom"), eFunctionNameTypeFull,
sc_list);
EXPECT_EQ(1u, sc_list.GetSize());
EXPECT_STREQ(GetDummyRemotePath().GetCString(),
module_sp->GetPlatformFileSpec().GetCString());
EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
}
TEST_F(ModuleCacheTest, GetAndPut) {
FileSpec test_cache_dir = s_cache_dir;
test_cache_dir.AppendPathComponent("GetAndPut");
const bool expect_download = true;
TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
VerifyDiskState(test_cache_dir, dummy_hostname);
}
TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
FileSpec test_cache_dir = s_cache_dir;
test_cache_dir.AppendPathComponent("GetAndPutUuidExists");
FileSpec uuid_view = GetUuidView(test_cache_dir);
std::error_code ec =
llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
ASSERT_FALSE(ec);
ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString());
ASSERT_FALSE(ec);
const bool expect_download = false;
TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
VerifyDiskState(test_cache_dir, dummy_hostname);
}
TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
FileSpec test_cache_dir = s_cache_dir;
test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");
const bool expect_download = true;
TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
}