| 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::FromErrorString(str: "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 | |