xref: /llvm-project/lldb/unittests/Target/ModuleCacheTest.cpp (revision 0642cd768b80665585c8500bed2933a3b99123dc)
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 
18 using namespace lldb_private;
19 using namespace lldb;
20 
21 namespace {
22 
23 class ModuleCacheTest : public testing::Test {
24   SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
25       subsystems;
26 
27 public:
28   void SetUp() override;
29 
30 protected:
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 
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 size_t module_size = 5602;
45 
46 static FileSpec GetDummyRemotePath() {
47   FileSpec fs("/", FileSpec::Style::posix);
48   fs.AppendPathComponent(dummy_remote_dir);
49   fs.AppendPathComponent(module_name);
50   return fs;
51 }
52 
53 static FileSpec GetUuidView(FileSpec spec) {
54   spec.AppendPathComponent(".cache");
55   spec.AppendPathComponent(module_uuid);
56   spec.AppendPathComponent(module_name);
57   return spec;
58 }
59 
60 static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
61   spec.AppendPathComponent(hostname);
62   spec.AppendPathComponent(dummy_remote_dir);
63   spec.AppendPathComponent(module_name);
64   return spec;
65 }
66 
67 void ModuleCacheTest::SetUp() {
68   s_cache_dir = HostInfo::GetProcessTempDir();
69   s_test_executable = GetInputFilePath(module_name);
70 }
71 
72 static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
73   FileSpec uuid_view = GetUuidView(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(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 
84 void 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       cache_dir, hostname, module_spec,
97       [&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             s_test_executable, tmp_download_file_spec.GetPath());
104         EXPECT_FALSE(ec);
105         return Status();
106       },
107       [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
108         return Status::FromErrorString("Not supported.");
109       },
110       module_sp, &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(ConstString("boom"), 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 
126 TEST_F(ModuleCacheTest, GetAndPut) {
127   FileSpec test_cache_dir = s_cache_dir;
128   test_cache_dir.AppendPathComponent("GetAndPut");
129 
130   const bool expect_download = true;
131   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
132   VerifyDiskState(test_cache_dir, dummy_hostname);
133 }
134 
135 TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
136   FileSpec test_cache_dir = s_cache_dir;
137   test_cache_dir.AppendPathComponent("GetAndPutUuidExists");
138 
139   FileSpec uuid_view = GetUuidView(test_cache_dir);
140   std::error_code ec =
141       llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
142   ASSERT_FALSE(ec);
143   ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetPath().c_str());
144   ASSERT_FALSE(ec);
145 
146   const bool expect_download = false;
147   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
148   VerifyDiskState(test_cache_dir, dummy_hostname);
149 }
150 
151 TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
152   FileSpec test_cache_dir = s_cache_dir;
153   test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");
154 
155   const bool expect_download = true;
156   TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
157   VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
158 }
159