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(component: dummy_remote_dir); |
49 | fs.AppendPathComponent(component: module_name); |
50 | return fs; |
51 | } |
52 | |
53 | static 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 | |
60 | static 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 | |
67 | void ModuleCacheTest::SetUp() { |
68 | s_cache_dir = HostInfo::GetProcessTempDir(); |
69 | s_test_executable = GetInputFilePath(name: module_name); |
70 | } |
71 | |
72 | static 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 | |
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 | 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 | |
126 | TEST_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 | |
135 | TEST_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 | |
151 | TEST_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 | |