101c3243fSZachary Turner #include "gtest/gtest.h"
201c3243fSZachary Turner 
301c3243fSZachary Turner #include "llvm/ADT/SmallString.h"
401c3243fSZachary Turner #include "llvm/Support/FileSystem.h"
501c3243fSZachary Turner #include "llvm/Support/Path.h"
601c3243fSZachary Turner 
701c3243fSZachary Turner #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
8*84a68569SPavel Labath #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
946376966SJonas Devlieghere #include "TestingSupport/TestUtilities.h"
1001c3243fSZachary Turner #include "lldb/Core/Module.h"
1101c3243fSZachary Turner #include "lldb/Core/ModuleSpec.h"
1246376966SJonas Devlieghere #include "lldb/Host/FileSystem.h"
1301c3243fSZachary Turner #include "lldb/Host/HostInfo.h"
1401c3243fSZachary Turner #include "lldb/Symbol/SymbolContext.h"
1501c3243fSZachary Turner #include "lldb/Target/ModuleCache.h"
1601c3243fSZachary Turner 
1701c3243fSZachary Turner using namespace lldb_private;
1801c3243fSZachary Turner using namespace lldb;
1901c3243fSZachary Turner 
2001c3243fSZachary Turner namespace {
2101c3243fSZachary Turner 
2201c3243fSZachary Turner class ModuleCacheTest : public testing::Test {
2301c3243fSZachary Turner public:
2401c3243fSZachary Turner   static void SetUpTestCase();
2501c3243fSZachary Turner 
2601c3243fSZachary Turner   static void TearDownTestCase();
2701c3243fSZachary Turner 
2801c3243fSZachary Turner protected:
2901c3243fSZachary Turner   static FileSpec s_cache_dir;
307ed3e22fSPavel Labath   static std::string s_test_executable;
3101c3243fSZachary Turner 
3201c3243fSZachary Turner   void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
3301c3243fSZachary Turner                     bool expect_download);
3401c3243fSZachary Turner };
3501c3243fSZachary Turner }
3601c3243fSZachary Turner 
3701c3243fSZachary Turner FileSpec ModuleCacheTest::s_cache_dir;
387ed3e22fSPavel Labath std::string ModuleCacheTest::s_test_executable;
3901c3243fSZachary Turner 
4001c3243fSZachary Turner static const char dummy_hostname[] = "dummy_hostname";
4101c3243fSZachary Turner static const char dummy_remote_dir[] = "bin";
4201c3243fSZachary Turner static const char module_name[] = "TestModule.so";
4301c3243fSZachary Turner static const char module_uuid[] =
4401c3243fSZachary Turner     "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
4501c3243fSZachary Turner static const uint32_t uuid_bytes = 20;
4601c3243fSZachary Turner static const size_t module_size = 5602;
4701c3243fSZachary Turner 
4801c3243fSZachary Turner static FileSpec GetDummyRemotePath() {
498f3be7a3SJonas Devlieghere   FileSpec fs("/", FileSpec::Style::posix);
5001c3243fSZachary Turner   fs.AppendPathComponent(dummy_remote_dir);
5101c3243fSZachary Turner   fs.AppendPathComponent(module_name);
5201c3243fSZachary Turner   return fs;
5301c3243fSZachary Turner }
5401c3243fSZachary Turner 
5501c3243fSZachary Turner static FileSpec GetUuidView(FileSpec spec) {
5601c3243fSZachary Turner   spec.AppendPathComponent(".cache");
5701c3243fSZachary Turner   spec.AppendPathComponent(module_uuid);
5801c3243fSZachary Turner   spec.AppendPathComponent(module_name);
5901c3243fSZachary Turner   return spec;
6001c3243fSZachary Turner }
6101c3243fSZachary Turner 
6201c3243fSZachary Turner static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
6301c3243fSZachary Turner   spec.AppendPathComponent(hostname);
6401c3243fSZachary Turner   spec.AppendPathComponent(dummy_remote_dir);
6501c3243fSZachary Turner   spec.AppendPathComponent(module_name);
6601c3243fSZachary Turner   return spec;
6701c3243fSZachary Turner }
6801c3243fSZachary Turner 
6901c3243fSZachary Turner void ModuleCacheTest::SetUpTestCase() {
7046376966SJonas Devlieghere   FileSystem::Initialize();
7101c3243fSZachary Turner   HostInfo::Initialize();
7201c3243fSZachary Turner   ObjectFileELF::Initialize();
73*84a68569SPavel Labath   SymbolFileSymtab::Initialize();
7401c3243fSZachary Turner 
7560f028ffSPavel Labath   s_cache_dir = HostInfo::GetProcessTempDir();
767ed3e22fSPavel Labath   s_test_executable = GetInputFilePath(module_name);
7701c3243fSZachary Turner }
7801c3243fSZachary Turner 
7901c3243fSZachary Turner void ModuleCacheTest::TearDownTestCase() {
80*84a68569SPavel Labath   SymbolFileSymtab::Terminate();
8101c3243fSZachary Turner   ObjectFileELF::Terminate();
8201c3243fSZachary Turner   HostInfo::Terminate();
8346376966SJonas Devlieghere   FileSystem::Terminate();
8401c3243fSZachary Turner }
8501c3243fSZachary Turner 
8601c3243fSZachary Turner static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
8701c3243fSZachary Turner   FileSpec uuid_view = GetUuidView(cache_dir);
88dbd7fabaSJonas Devlieghere   EXPECT_TRUE(FileSystem::Instance().Exists(uuid_view))
89dbd7fabaSJonas Devlieghere       << "uuid_view is: " << uuid_view.GetCString();
9059b78bcbSJonas Devlieghere   EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(uuid_view));
9101c3243fSZachary Turner 
9201c3243fSZachary Turner   FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
93dbd7fabaSJonas Devlieghere   EXPECT_TRUE(FileSystem::Instance().Exists(sysroot_view))
94dbd7fabaSJonas Devlieghere       << "sysroot_view is: " << sysroot_view.GetCString();
9559b78bcbSJonas Devlieghere   EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(sysroot_view));
9601c3243fSZachary Turner }
9701c3243fSZachary Turner 
9801c3243fSZachary Turner void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
9901c3243fSZachary Turner                                    const char *hostname, bool expect_download) {
10001c3243fSZachary Turner   ModuleCache mc;
10101c3243fSZachary Turner   ModuleSpec module_spec;
10201c3243fSZachary Turner   module_spec.GetFileSpec() = GetDummyRemotePath();
103a174bcbfSPavel Labath   module_spec.GetUUID().SetFromStringRef(module_uuid, uuid_bytes);
10401c3243fSZachary Turner   module_spec.SetObjectSize(module_size);
10501c3243fSZachary Turner   ModuleSP module_sp;
10601c3243fSZachary Turner   bool did_create;
10701c3243fSZachary Turner   bool download_called = false;
10801c3243fSZachary Turner 
10997206d57SZachary Turner   Status error = mc.GetAndPut(
11001c3243fSZachary Turner       cache_dir, hostname, module_spec,
111c7933341SVedant Kumar       [&download_called](const ModuleSpec &module_spec,
11201c3243fSZachary Turner                          const FileSpec &tmp_download_file_spec) {
11301c3243fSZachary Turner         download_called = true;
11401c3243fSZachary Turner         EXPECT_STREQ(GetDummyRemotePath().GetCString(),
11501c3243fSZachary Turner                      module_spec.GetFileSpec().GetCString());
11601c3243fSZachary Turner         std::error_code ec = llvm::sys::fs::copy_file(
11701c3243fSZachary Turner             s_test_executable, tmp_download_file_spec.GetCString());
11801c3243fSZachary Turner         EXPECT_FALSE(ec);
11997206d57SZachary Turner         return Status();
12001c3243fSZachary Turner       },
12101c3243fSZachary Turner       [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
12297206d57SZachary Turner         return Status("Not supported.");
12301c3243fSZachary Turner       },
12401c3243fSZachary Turner       module_sp, &did_create);
12501c3243fSZachary Turner   EXPECT_EQ(expect_download, download_called);
12601c3243fSZachary Turner 
12701c3243fSZachary Turner   EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
12801c3243fSZachary Turner   EXPECT_TRUE(did_create);
12901c3243fSZachary Turner   ASSERT_TRUE(bool(module_sp));
13001c3243fSZachary Turner 
13101c3243fSZachary Turner   SymbolContextList sc_list;
13201c3243fSZachary Turner   EXPECT_EQ(1u, module_sp->FindFunctionSymbols(ConstString("boom"),
13301c3243fSZachary Turner                                                eFunctionNameTypeFull, sc_list));
13401c3243fSZachary Turner   EXPECT_STREQ(GetDummyRemotePath().GetCString(),
13501c3243fSZachary Turner                module_sp->GetPlatformFileSpec().GetCString());
13601c3243fSZachary Turner   EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
13701c3243fSZachary Turner }
13801c3243fSZachary Turner 
13901c3243fSZachary Turner TEST_F(ModuleCacheTest, GetAndPut) {
14001c3243fSZachary Turner   FileSpec test_cache_dir = s_cache_dir;
14101c3243fSZachary Turner   test_cache_dir.AppendPathComponent("GetAndPut");
14201c3243fSZachary Turner 
14301c3243fSZachary Turner   const bool expect_download = true;
14401c3243fSZachary Turner   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
14501c3243fSZachary Turner   VerifyDiskState(test_cache_dir, dummy_hostname);
14601c3243fSZachary Turner }
14701c3243fSZachary Turner 
14801c3243fSZachary Turner TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
14901c3243fSZachary Turner   FileSpec test_cache_dir = s_cache_dir;
15001c3243fSZachary Turner   test_cache_dir.AppendPathComponent("GetAndPutUuidExists");
15101c3243fSZachary Turner 
15201c3243fSZachary Turner   FileSpec uuid_view = GetUuidView(test_cache_dir);
15301c3243fSZachary Turner   std::error_code ec =
15401c3243fSZachary Turner       llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
15501c3243fSZachary Turner   ASSERT_FALSE(ec);
15601c3243fSZachary Turner   ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString());
15701c3243fSZachary Turner   ASSERT_FALSE(ec);
15801c3243fSZachary Turner 
15901c3243fSZachary Turner   const bool expect_download = false;
16001c3243fSZachary Turner   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
16101c3243fSZachary Turner   VerifyDiskState(test_cache_dir, dummy_hostname);
16201c3243fSZachary Turner }
16301c3243fSZachary Turner 
16401c3243fSZachary Turner TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
16501c3243fSZachary Turner   FileSpec test_cache_dir = s_cache_dir;
16601c3243fSZachary Turner   test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");
16701c3243fSZachary Turner 
16801c3243fSZachary Turner   const bool expect_download = true;
16901c3243fSZachary Turner   TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
17001c3243fSZachary Turner   VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
17101c3243fSZachary Turner }
172