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 uint32_t uuid_bytes = 20; 45 static const size_t module_size = 5602; 46 47 static FileSpec GetDummyRemotePath() { 48 FileSpec fs("/", FileSpec::Style::posix); 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::SetUp() { 69 s_cache_dir = HostInfo::GetProcessTempDir(); 70 s_test_executable = GetInputFilePath(module_name); 71 } 72 73 static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) { 74 FileSpec uuid_view = GetUuidView(cache_dir); 75 EXPECT_TRUE(FileSystem::Instance().Exists(uuid_view)) 76 << "uuid_view is: " << uuid_view.GetCString(); 77 EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(uuid_view)); 78 79 FileSpec sysroot_view = GetSysrootView(cache_dir, hostname); 80 EXPECT_TRUE(FileSystem::Instance().Exists(sysroot_view)) 81 << "sysroot_view is: " << sysroot_view.GetCString(); 82 EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(sysroot_view)); 83 } 84 85 void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir, 86 const char *hostname, bool expect_download) { 87 ModuleCache mc; 88 ModuleSpec module_spec; 89 module_spec.GetFileSpec() = GetDummyRemotePath(); 90 module_spec.GetUUID().SetFromStringRef(module_uuid, uuid_bytes); 91 module_spec.SetObjectSize(module_size); 92 ModuleSP module_sp; 93 bool did_create; 94 bool download_called = false; 95 96 Status error = mc.GetAndPut( 97 cache_dir, hostname, module_spec, 98 [&download_called, this](const ModuleSpec &module_spec, 99 const FileSpec &tmp_download_file_spec) { 100 download_called = true; 101 EXPECT_STREQ(GetDummyRemotePath().GetCString(), 102 module_spec.GetFileSpec().GetCString()); 103 std::error_code ec = llvm::sys::fs::copy_file( 104 s_test_executable, tmp_download_file_spec.GetCString()); 105 EXPECT_FALSE(ec); 106 return Status(); 107 }, 108 [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) { 109 return Status("Not supported."); 110 }, 111 module_sp, &did_create); 112 EXPECT_EQ(expect_download, download_called); 113 114 EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString(); 115 EXPECT_TRUE(did_create); 116 ASSERT_TRUE(bool(module_sp)); 117 118 SymbolContextList sc_list; 119 module_sp->FindFunctionSymbols(ConstString("boom"), eFunctionNameTypeFull, 120 sc_list); 121 EXPECT_EQ(1u, sc_list.GetSize()); 122 EXPECT_STREQ(GetDummyRemotePath().GetCString(), 123 module_sp->GetPlatformFileSpec().GetCString()); 124 EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str()); 125 } 126 127 TEST_F(ModuleCacheTest, GetAndPut) { 128 FileSpec test_cache_dir = s_cache_dir; 129 test_cache_dir.AppendPathComponent("GetAndPut"); 130 131 const bool expect_download = true; 132 TryGetAndPut(test_cache_dir, dummy_hostname, expect_download); 133 VerifyDiskState(test_cache_dir, dummy_hostname); 134 } 135 136 TEST_F(ModuleCacheTest, GetAndPutUuidExists) { 137 FileSpec test_cache_dir = s_cache_dir; 138 test_cache_dir.AppendPathComponent("GetAndPutUuidExists"); 139 140 FileSpec uuid_view = GetUuidView(test_cache_dir); 141 std::error_code ec = 142 llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString()); 143 ASSERT_FALSE(ec); 144 ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString()); 145 ASSERT_FALSE(ec); 146 147 const bool expect_download = false; 148 TryGetAndPut(test_cache_dir, dummy_hostname, expect_download); 149 VerifyDiskState(test_cache_dir, dummy_hostname); 150 } 151 152 TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) { 153 FileSpec test_cache_dir = s_cache_dir; 154 test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname"); 155 156 const bool expect_download = true; 157 TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download); 158 VerifyDiskState(test_cache_dir, "tab_colon_asterisk_"); 159 } 160