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