xref: /llvm-project/lldb/unittests/Target/ModuleCacheTest.cpp (revision 01c3243fc1a20b5ddcb464a3183e5fd904d695a4)
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 "lldb/Core/Module.h"
9 #include "lldb/Core/ModuleSpec.h"
10 #include "lldb/Host/HostInfo.h"
11 #include "lldb/Symbol/SymbolContext.h"
12 #include "lldb/Target/ModuleCache.h"
13 
14 extern const char *TestMainArgv0;
15 
16 using namespace lldb_private;
17 using namespace lldb;
18 
19 namespace {
20 
21 class ModuleCacheTest : public testing::Test {
22 public:
23   static void SetUpTestCase();
24 
25   static void TearDownTestCase();
26 
27 protected:
28   static FileSpec s_cache_dir;
29   static llvm::SmallString<128> s_test_executable;
30 
31   void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
32                     bool expect_download);
33 };
34 }
35 
36 FileSpec ModuleCacheTest::s_cache_dir;
37 llvm::SmallString<128> ModuleCacheTest::s_test_executable;
38 
39 static const char dummy_hostname[] = "dummy_hostname";
40 static const char dummy_remote_dir[] = "bin";
41 static const char module_name[] = "TestModule.so";
42 static const char module_uuid[] =
43     "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
44 static const uint32_t uuid_bytes = 20;
45 static const size_t module_size = 5602;
46 
47 static FileSpec GetDummyRemotePath() {
48   FileSpec fs("/", false, FileSpec::ePathSyntaxPosix);
49   fs.AppendPathComponent(dummy_remote_dir);
50   fs.AppendPathComponent(module_name);
51   return fs;
52 }
53 
54 static FileSpec GetUuidView(FileSpec spec) {
55   spec.AppendPathComponent(".cache");
56   spec.AppendPathComponent(module_uuid);
57   spec.AppendPathComponent(module_name);
58   return spec;
59 }
60 
61 static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
62   spec.AppendPathComponent(hostname);
63   spec.AppendPathComponent(dummy_remote_dir);
64   spec.AppendPathComponent(module_name);
65   return spec;
66 }
67 
68 void ModuleCacheTest::SetUpTestCase() {
69   HostInfo::Initialize();
70   ObjectFileELF::Initialize();
71 
72   FileSpec tmpdir_spec;
73   HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, s_cache_dir);
74 
75   llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
76   s_test_executable = exe_folder;
77   llvm::sys::path::append(s_test_executable, "Inputs", module_name);
78 }
79 
80 void ModuleCacheTest::TearDownTestCase() {
81   ObjectFileELF::Terminate();
82   HostInfo::Terminate();
83 }
84 
85 static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
86   FileSpec uuid_view = GetUuidView(cache_dir);
87   EXPECT_TRUE(uuid_view.Exists()) << "uuid_view is: " << uuid_view.GetCString();
88   EXPECT_EQ(module_size, uuid_view.GetByteSize());
89 
90   FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
91   EXPECT_TRUE(sysroot_view.Exists()) << "sysroot_view is: "
92                                      << sysroot_view.GetCString();
93   EXPECT_EQ(module_size, sysroot_view.GetByteSize());
94 }
95 
96 void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
97                                    const char *hostname, bool expect_download) {
98   ModuleCache mc;
99   ModuleSpec module_spec;
100   module_spec.GetFileSpec() = GetDummyRemotePath();
101   module_spec.GetUUID().SetFromCString(module_uuid, uuid_bytes);
102   module_spec.SetObjectSize(module_size);
103   ModuleSP module_sp;
104   bool did_create;
105   bool download_called = false;
106 
107   Error error = mc.GetAndPut(
108       cache_dir, hostname, module_spec,
109       [this, &download_called](const ModuleSpec &module_spec,
110                                const FileSpec &tmp_download_file_spec) {
111         download_called = true;
112         EXPECT_STREQ(GetDummyRemotePath().GetCString(),
113                      module_spec.GetFileSpec().GetCString());
114         std::error_code ec = llvm::sys::fs::copy_file(
115             s_test_executable, tmp_download_file_spec.GetCString());
116         EXPECT_FALSE(ec);
117         return Error();
118       },
119       [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
120         return Error("Not supported.");
121       },
122       module_sp, &did_create);
123   EXPECT_EQ(expect_download, download_called);
124 
125   EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
126   EXPECT_TRUE(did_create);
127   ASSERT_TRUE(bool(module_sp));
128 
129   SymbolContextList sc_list;
130   EXPECT_EQ(1u, module_sp->FindFunctionSymbols(ConstString("boom"),
131                                                eFunctionNameTypeFull, sc_list));
132   EXPECT_STREQ(GetDummyRemotePath().GetCString(),
133                module_sp->GetPlatformFileSpec().GetCString());
134   EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
135 }
136 
137 TEST_F(ModuleCacheTest, GetAndPut) {
138   FileSpec test_cache_dir = s_cache_dir;
139   test_cache_dir.AppendPathComponent("GetAndPut");
140 
141   const bool expect_download = true;
142   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
143   VerifyDiskState(test_cache_dir, dummy_hostname);
144 }
145 
146 TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
147   FileSpec test_cache_dir = s_cache_dir;
148   test_cache_dir.AppendPathComponent("GetAndPutUuidExists");
149 
150   FileSpec uuid_view = GetUuidView(test_cache_dir);
151   std::error_code ec =
152       llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
153   ASSERT_FALSE(ec);
154   ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString());
155   ASSERT_FALSE(ec);
156 
157   const bool expect_download = false;
158   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
159   VerifyDiskState(test_cache_dir, dummy_hostname);
160 }
161 
162 TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
163   FileSpec test_cache_dir = s_cache_dir;
164   test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");
165 
166   const bool expect_download = true;
167   TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
168   VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
169 }
170