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