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 #include "TestingSupport/TestUtilities.h" 14 15 using namespace lldb_private; 16 using namespace lldb; 17 18 namespace { 19 20 class ModuleCacheTest : public testing::Test { 21 public: 22 static void SetUpTestCase(); 23 24 static void TearDownTestCase(); 25 26 protected: 27 static FileSpec s_cache_dir; 28 static std::string s_test_executable; 29 30 void TryGetAndPut(const FileSpec &cache_dir, const char *hostname, 31 bool expect_download); 32 }; 33 } 34 35 FileSpec ModuleCacheTest::s_cache_dir; 36 std::string ModuleCacheTest::s_test_executable; 37 38 static const char dummy_hostname[] = "dummy_hostname"; 39 static const char dummy_remote_dir[] = "bin"; 40 static const char module_name[] = "TestModule.so"; 41 static const char module_uuid[] = 42 "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476"; 43 static const uint32_t uuid_bytes = 20; 44 static const size_t module_size = 5602; 45 46 static FileSpec GetDummyRemotePath() { 47 FileSpec fs("/", false, FileSpec::ePathSyntaxPosix); 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::SetUpTestCase() { 68 HostInfo::Initialize(); 69 ObjectFileELF::Initialize(); 70 71 FileSpec tmpdir_spec; 72 HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, s_cache_dir); 73 s_test_executable = GetInputFilePath(module_name); 74 } 75 76 void ModuleCacheTest::TearDownTestCase() { 77 ObjectFileELF::Terminate(); 78 HostInfo::Terminate(); 79 } 80 81 static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) { 82 FileSpec uuid_view = GetUuidView(cache_dir); 83 EXPECT_TRUE(uuid_view.Exists()) << "uuid_view is: " << uuid_view.GetCString(); 84 EXPECT_EQ(module_size, uuid_view.GetByteSize()); 85 86 FileSpec sysroot_view = GetSysrootView(cache_dir, hostname); 87 EXPECT_TRUE(sysroot_view.Exists()) << "sysroot_view is: " 88 << sysroot_view.GetCString(); 89 EXPECT_EQ(module_size, sysroot_view.GetByteSize()); 90 } 91 92 void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir, 93 const char *hostname, bool expect_download) { 94 ModuleCache mc; 95 ModuleSpec module_spec; 96 module_spec.GetFileSpec() = GetDummyRemotePath(); 97 module_spec.GetUUID().SetFromCString(module_uuid, uuid_bytes); 98 module_spec.SetObjectSize(module_size); 99 ModuleSP module_sp; 100 bool did_create; 101 bool download_called = false; 102 103 Status error = mc.GetAndPut( 104 cache_dir, hostname, module_spec, 105 [&download_called](const ModuleSpec &module_spec, 106 const FileSpec &tmp_download_file_spec) { 107 download_called = true; 108 EXPECT_STREQ(GetDummyRemotePath().GetCString(), 109 module_spec.GetFileSpec().GetCString()); 110 std::error_code ec = llvm::sys::fs::copy_file( 111 s_test_executable, tmp_download_file_spec.GetCString()); 112 EXPECT_FALSE(ec); 113 return Status(); 114 }, 115 [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) { 116 return Status("Not supported."); 117 }, 118 module_sp, &did_create); 119 EXPECT_EQ(expect_download, download_called); 120 121 EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString(); 122 EXPECT_TRUE(did_create); 123 ASSERT_TRUE(bool(module_sp)); 124 125 SymbolContextList sc_list; 126 EXPECT_EQ(1u, module_sp->FindFunctionSymbols(ConstString("boom"), 127 eFunctionNameTypeFull, sc_list)); 128 EXPECT_STREQ(GetDummyRemotePath().GetCString(), 129 module_sp->GetPlatformFileSpec().GetCString()); 130 EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str()); 131 } 132 133 TEST_F(ModuleCacheTest, GetAndPut) { 134 FileSpec test_cache_dir = s_cache_dir; 135 test_cache_dir.AppendPathComponent("GetAndPut"); 136 137 const bool expect_download = true; 138 TryGetAndPut(test_cache_dir, dummy_hostname, expect_download); 139 VerifyDiskState(test_cache_dir, dummy_hostname); 140 } 141 142 TEST_F(ModuleCacheTest, GetAndPutUuidExists) { 143 FileSpec test_cache_dir = s_cache_dir; 144 test_cache_dir.AppendPathComponent("GetAndPutUuidExists"); 145 146 FileSpec uuid_view = GetUuidView(test_cache_dir); 147 std::error_code ec = 148 llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString()); 149 ASSERT_FALSE(ec); 150 ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString()); 151 ASSERT_FALSE(ec); 152 153 const bool expect_download = false; 154 TryGetAndPut(test_cache_dir, dummy_hostname, expect_download); 155 VerifyDiskState(test_cache_dir, dummy_hostname); 156 } 157 158 TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) { 159 FileSpec test_cache_dir = s_cache_dir; 160 test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname"); 161 162 const bool expect_download = true; 163 TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download); 164 VerifyDiskState(test_cache_dir, "tab_colon_asterisk_"); 165 } 166