1#include "gtest/gtest.h"
2
3#include "llvm/ADT/SmallString.h"
4#include "llvm/Support/FileSystem.h"
5#include "llvm/Support/Path.h"
6
7#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
8#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
9#include "TestingSupport/SubsystemRAII.h"
10#include "TestingSupport/TestUtilities.h"
11#include "lldb/Core/Module.h"
12#include "lldb/Core/ModuleSpec.h"
13#include "lldb/Host/FileSystem.h"
14#include "lldb/Host/HostInfo.h"
15#include "lldb/Symbol/SymbolContext.h"
16#include "lldb/Target/ModuleCache.h"
17
18using namespace lldb_private;
19using namespace lldb;
20
21namespace {
22
23class ModuleCacheTest : public testing::Test {
24 SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
25 subsystems;
26
27public:
28 void SetUp() override;
29
30protected:
31 FileSpec s_cache_dir;
32 std::string s_test_executable;
33
34 void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
35 bool expect_download);
36};
37}
38
39static const char dummy_hostname[] = "dummy_hostname";
40static const char dummy_remote_dir[] = "bin";
41static const char module_name[] = "TestModule.so";
42static const char module_uuid[] =
43 "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
44static const size_t module_size = 5602;
45
46static FileSpec GetDummyRemotePath() {
47 FileSpec fs("/", FileSpec::Style::posix);
48 fs.AppendPathComponent(component: dummy_remote_dir);
49 fs.AppendPathComponent(component: module_name);
50 return fs;
51}
52
53static FileSpec GetUuidView(FileSpec spec) {
54 spec.AppendPathComponent(component: ".cache");
55 spec.AppendPathComponent(component: module_uuid);
56 spec.AppendPathComponent(component: module_name);
57 return spec;
58}
59
60static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
61 spec.AppendPathComponent(component: hostname);
62 spec.AppendPathComponent(component: dummy_remote_dir);
63 spec.AppendPathComponent(component: module_name);
64 return spec;
65}
66
67void ModuleCacheTest::SetUp() {
68 s_cache_dir = HostInfo::GetProcessTempDir();
69 s_test_executable = GetInputFilePath(name: module_name);
70}
71
72static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
73 FileSpec uuid_view = GetUuidView(spec: cache_dir);
74 EXPECT_TRUE(FileSystem::Instance().Exists(uuid_view))
75 << "uuid_view is: " << uuid_view.GetPath();
76 EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(uuid_view));
77
78 FileSpec sysroot_view = GetSysrootView(spec: cache_dir, hostname);
79 EXPECT_TRUE(FileSystem::Instance().Exists(sysroot_view))
80 << "sysroot_view is: " << sysroot_view.GetPath();
81 EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(sysroot_view));
82}
83
84void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
85 const char *hostname, bool expect_download) {
86 ModuleCache mc;
87 ModuleSpec module_spec;
88 module_spec.GetFileSpec() = GetDummyRemotePath();
89 module_spec.GetUUID().SetFromStringRef(module_uuid);
90 module_spec.SetObjectSize(module_size);
91 ModuleSP module_sp;
92 bool did_create;
93 bool download_called = false;
94
95 Status error = mc.GetAndPut(
96 root_dir_spec: cache_dir, hostname, module_spec,
97 module_downloader: [&download_called, this](const ModuleSpec &module_spec,
98 const FileSpec &tmp_download_file_spec) {
99 download_called = true;
100 EXPECT_STREQ(GetDummyRemotePath().GetPath().c_str(),
101 module_spec.GetFileSpec().GetPath().c_str());
102 std::error_code ec = llvm::sys::fs::copy_file(
103 From: s_test_executable, To: tmp_download_file_spec.GetPath());
104 EXPECT_FALSE(ec);
105 return Status();
106 },
107 symfile_downloader: [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
108 return Status("Not supported.");
109 },
110 cached_module_sp&: module_sp, did_create_ptr: &did_create);
111 EXPECT_EQ(expect_download, download_called);
112
113 EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
114 EXPECT_TRUE(did_create);
115 ASSERT_TRUE(bool(module_sp));
116
117 SymbolContextList sc_list;
118 module_sp->FindFunctionSymbols(name: ConstString("boom"), name_type_mask: eFunctionNameTypeFull,
119 sc_list);
120 EXPECT_EQ(1u, sc_list.GetSize());
121 EXPECT_STREQ(GetDummyRemotePath().GetPath().c_str(),
122 module_sp->GetPlatformFileSpec().GetPath().c_str());
123 EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
124}
125
126TEST_F(ModuleCacheTest, GetAndPut) {
127 FileSpec test_cache_dir = s_cache_dir;
128 test_cache_dir.AppendPathComponent(component: "GetAndPut");
129
130 const bool expect_download = true;
131 TryGetAndPut(cache_dir: test_cache_dir, hostname: dummy_hostname, expect_download);
132 VerifyDiskState(cache_dir: test_cache_dir, hostname: dummy_hostname);
133}
134
135TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
136 FileSpec test_cache_dir = s_cache_dir;
137 test_cache_dir.AppendPathComponent(component: "GetAndPutUuidExists");
138
139 FileSpec uuid_view = GetUuidView(spec: test_cache_dir);
140 std::error_code ec =
141 llvm::sys::fs::create_directories(path: uuid_view.GetDirectory().GetCString());
142 ASSERT_FALSE(ec);
143 ec = llvm::sys::fs::copy_file(From: s_test_executable, To: uuid_view.GetPath().c_str());
144 ASSERT_FALSE(ec);
145
146 const bool expect_download = false;
147 TryGetAndPut(cache_dir: test_cache_dir, hostname: dummy_hostname, expect_download);
148 VerifyDiskState(cache_dir: test_cache_dir, hostname: dummy_hostname);
149}
150
151TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
152 FileSpec test_cache_dir = s_cache_dir;
153 test_cache_dir.AppendPathComponent(component: "GetAndPutStrangeHostname");
154
155 const bool expect_download = true;
156 TryGetAndPut(cache_dir: test_cache_dir, hostname: "tab\tcolon:asterisk*", expect_download);
157 VerifyDiskState(cache_dir: test_cache_dir, hostname: "tab_colon_asterisk_");
158}
159

source code of lldb/unittests/Target/ModuleCacheTest.cpp