1*01c3243fSZachary Turner #include "gtest/gtest.h"
2*01c3243fSZachary Turner 
3*01c3243fSZachary Turner #include "llvm/ADT/SmallString.h"
4*01c3243fSZachary Turner #include "llvm/Support/FileSystem.h"
5*01c3243fSZachary Turner #include "llvm/Support/Path.h"
6*01c3243fSZachary Turner 
7*01c3243fSZachary Turner #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
8*01c3243fSZachary Turner #include "lldb/Core/Module.h"
9*01c3243fSZachary Turner #include "lldb/Core/ModuleSpec.h"
10*01c3243fSZachary Turner #include "lldb/Host/HostInfo.h"
11*01c3243fSZachary Turner #include "lldb/Symbol/SymbolContext.h"
12*01c3243fSZachary Turner #include "lldb/Target/ModuleCache.h"
13*01c3243fSZachary Turner 
14*01c3243fSZachary Turner extern const char *TestMainArgv0;
15*01c3243fSZachary Turner 
16*01c3243fSZachary Turner using namespace lldb_private;
17*01c3243fSZachary Turner using namespace lldb;
18*01c3243fSZachary Turner 
19*01c3243fSZachary Turner namespace {
20*01c3243fSZachary Turner 
21*01c3243fSZachary Turner class ModuleCacheTest : public testing::Test {
22*01c3243fSZachary Turner public:
23*01c3243fSZachary Turner   static void SetUpTestCase();
24*01c3243fSZachary Turner 
25*01c3243fSZachary Turner   static void TearDownTestCase();
26*01c3243fSZachary Turner 
27*01c3243fSZachary Turner protected:
28*01c3243fSZachary Turner   static FileSpec s_cache_dir;
29*01c3243fSZachary Turner   static llvm::SmallString<128> s_test_executable;
30*01c3243fSZachary Turner 
31*01c3243fSZachary Turner   void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
32*01c3243fSZachary Turner                     bool expect_download);
33*01c3243fSZachary Turner };
34*01c3243fSZachary Turner }
35*01c3243fSZachary Turner 
36*01c3243fSZachary Turner FileSpec ModuleCacheTest::s_cache_dir;
37*01c3243fSZachary Turner llvm::SmallString<128> ModuleCacheTest::s_test_executable;
38*01c3243fSZachary Turner 
39*01c3243fSZachary Turner static const char dummy_hostname[] = "dummy_hostname";
40*01c3243fSZachary Turner static const char dummy_remote_dir[] = "bin";
41*01c3243fSZachary Turner static const char module_name[] = "TestModule.so";
42*01c3243fSZachary Turner static const char module_uuid[] =
43*01c3243fSZachary Turner     "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
44*01c3243fSZachary Turner static const uint32_t uuid_bytes = 20;
45*01c3243fSZachary Turner static const size_t module_size = 5602;
46*01c3243fSZachary Turner 
47*01c3243fSZachary Turner static FileSpec GetDummyRemotePath() {
48*01c3243fSZachary Turner   FileSpec fs("/", false, FileSpec::ePathSyntaxPosix);
49*01c3243fSZachary Turner   fs.AppendPathComponent(dummy_remote_dir);
50*01c3243fSZachary Turner   fs.AppendPathComponent(module_name);
51*01c3243fSZachary Turner   return fs;
52*01c3243fSZachary Turner }
53*01c3243fSZachary Turner 
54*01c3243fSZachary Turner static FileSpec GetUuidView(FileSpec spec) {
55*01c3243fSZachary Turner   spec.AppendPathComponent(".cache");
56*01c3243fSZachary Turner   spec.AppendPathComponent(module_uuid);
57*01c3243fSZachary Turner   spec.AppendPathComponent(module_name);
58*01c3243fSZachary Turner   return spec;
59*01c3243fSZachary Turner }
60*01c3243fSZachary Turner 
61*01c3243fSZachary Turner static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
62*01c3243fSZachary Turner   spec.AppendPathComponent(hostname);
63*01c3243fSZachary Turner   spec.AppendPathComponent(dummy_remote_dir);
64*01c3243fSZachary Turner   spec.AppendPathComponent(module_name);
65*01c3243fSZachary Turner   return spec;
66*01c3243fSZachary Turner }
67*01c3243fSZachary Turner 
68*01c3243fSZachary Turner void ModuleCacheTest::SetUpTestCase() {
69*01c3243fSZachary Turner   HostInfo::Initialize();
70*01c3243fSZachary Turner   ObjectFileELF::Initialize();
71*01c3243fSZachary Turner 
72*01c3243fSZachary Turner   FileSpec tmpdir_spec;
73*01c3243fSZachary Turner   HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, s_cache_dir);
74*01c3243fSZachary Turner 
75*01c3243fSZachary Turner   llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
76*01c3243fSZachary Turner   s_test_executable = exe_folder;
77*01c3243fSZachary Turner   llvm::sys::path::append(s_test_executable, "Inputs", module_name);
78*01c3243fSZachary Turner }
79*01c3243fSZachary Turner 
80*01c3243fSZachary Turner void ModuleCacheTest::TearDownTestCase() {
81*01c3243fSZachary Turner   ObjectFileELF::Terminate();
82*01c3243fSZachary Turner   HostInfo::Terminate();
83*01c3243fSZachary Turner }
84*01c3243fSZachary Turner 
85*01c3243fSZachary Turner static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
86*01c3243fSZachary Turner   FileSpec uuid_view = GetUuidView(cache_dir);
87*01c3243fSZachary Turner   EXPECT_TRUE(uuid_view.Exists()) << "uuid_view is: " << uuid_view.GetCString();
88*01c3243fSZachary Turner   EXPECT_EQ(module_size, uuid_view.GetByteSize());
89*01c3243fSZachary Turner 
90*01c3243fSZachary Turner   FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
91*01c3243fSZachary Turner   EXPECT_TRUE(sysroot_view.Exists()) << "sysroot_view is: "
92*01c3243fSZachary Turner                                      << sysroot_view.GetCString();
93*01c3243fSZachary Turner   EXPECT_EQ(module_size, sysroot_view.GetByteSize());
94*01c3243fSZachary Turner }
95*01c3243fSZachary Turner 
96*01c3243fSZachary Turner void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
97*01c3243fSZachary Turner                                    const char *hostname, bool expect_download) {
98*01c3243fSZachary Turner   ModuleCache mc;
99*01c3243fSZachary Turner   ModuleSpec module_spec;
100*01c3243fSZachary Turner   module_spec.GetFileSpec() = GetDummyRemotePath();
101*01c3243fSZachary Turner   module_spec.GetUUID().SetFromCString(module_uuid, uuid_bytes);
102*01c3243fSZachary Turner   module_spec.SetObjectSize(module_size);
103*01c3243fSZachary Turner   ModuleSP module_sp;
104*01c3243fSZachary Turner   bool did_create;
105*01c3243fSZachary Turner   bool download_called = false;
106*01c3243fSZachary Turner 
107*01c3243fSZachary Turner   Error error = mc.GetAndPut(
108*01c3243fSZachary Turner       cache_dir, hostname, module_spec,
109*01c3243fSZachary Turner       [this, &download_called](const ModuleSpec &module_spec,
110*01c3243fSZachary Turner                                const FileSpec &tmp_download_file_spec) {
111*01c3243fSZachary Turner         download_called = true;
112*01c3243fSZachary Turner         EXPECT_STREQ(GetDummyRemotePath().GetCString(),
113*01c3243fSZachary Turner                      module_spec.GetFileSpec().GetCString());
114*01c3243fSZachary Turner         std::error_code ec = llvm::sys::fs::copy_file(
115*01c3243fSZachary Turner             s_test_executable, tmp_download_file_spec.GetCString());
116*01c3243fSZachary Turner         EXPECT_FALSE(ec);
117*01c3243fSZachary Turner         return Error();
118*01c3243fSZachary Turner       },
119*01c3243fSZachary Turner       [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
120*01c3243fSZachary Turner         return Error("Not supported.");
121*01c3243fSZachary Turner       },
122*01c3243fSZachary Turner       module_sp, &did_create);
123*01c3243fSZachary Turner   EXPECT_EQ(expect_download, download_called);
124*01c3243fSZachary Turner 
125*01c3243fSZachary Turner   EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
126*01c3243fSZachary Turner   EXPECT_TRUE(did_create);
127*01c3243fSZachary Turner   ASSERT_TRUE(bool(module_sp));
128*01c3243fSZachary Turner 
129*01c3243fSZachary Turner   SymbolContextList sc_list;
130*01c3243fSZachary Turner   EXPECT_EQ(1u, module_sp->FindFunctionSymbols(ConstString("boom"),
131*01c3243fSZachary Turner                                                eFunctionNameTypeFull, sc_list));
132*01c3243fSZachary Turner   EXPECT_STREQ(GetDummyRemotePath().GetCString(),
133*01c3243fSZachary Turner                module_sp->GetPlatformFileSpec().GetCString());
134*01c3243fSZachary Turner   EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
135*01c3243fSZachary Turner }
136*01c3243fSZachary Turner 
137*01c3243fSZachary Turner TEST_F(ModuleCacheTest, GetAndPut) {
138*01c3243fSZachary Turner   FileSpec test_cache_dir = s_cache_dir;
139*01c3243fSZachary Turner   test_cache_dir.AppendPathComponent("GetAndPut");
140*01c3243fSZachary Turner 
141*01c3243fSZachary Turner   const bool expect_download = true;
142*01c3243fSZachary Turner   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
143*01c3243fSZachary Turner   VerifyDiskState(test_cache_dir, dummy_hostname);
144*01c3243fSZachary Turner }
145*01c3243fSZachary Turner 
146*01c3243fSZachary Turner TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
147*01c3243fSZachary Turner   FileSpec test_cache_dir = s_cache_dir;
148*01c3243fSZachary Turner   test_cache_dir.AppendPathComponent("GetAndPutUuidExists");
149*01c3243fSZachary Turner 
150*01c3243fSZachary Turner   FileSpec uuid_view = GetUuidView(test_cache_dir);
151*01c3243fSZachary Turner   std::error_code ec =
152*01c3243fSZachary Turner       llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
153*01c3243fSZachary Turner   ASSERT_FALSE(ec);
154*01c3243fSZachary Turner   ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString());
155*01c3243fSZachary Turner   ASSERT_FALSE(ec);
156*01c3243fSZachary Turner 
157*01c3243fSZachary Turner   const bool expect_download = false;
158*01c3243fSZachary Turner   TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
159*01c3243fSZachary Turner   VerifyDiskState(test_cache_dir, dummy_hostname);
160*01c3243fSZachary Turner }
161*01c3243fSZachary Turner 
162*01c3243fSZachary Turner TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
163*01c3243fSZachary Turner   FileSpec test_cache_dir = s_cache_dir;
164*01c3243fSZachary Turner   test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");
165*01c3243fSZachary Turner 
166*01c3243fSZachary Turner   const bool expect_download = true;
167*01c3243fSZachary Turner   TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
168*01c3243fSZachary Turner   VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
169*01c3243fSZachary Turner }
170