[nfc][Driver] Remove {{(.exe)?}} from sanitizer test (#121160)
[llvm-project.git] / lldb / unittests / Target / LocateModuleCallbackTest.cpp
blob6ffa41b16b4ff87cd25f266f7f7e59d084dfc05d
1 //===-- LocateModuleCallbackTest.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
10 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
11 #include "Plugins/Platform/Android/PlatformAndroid.h"
12 #include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
13 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
14 #include "TestingSupport/SubsystemRAII.h"
15 #include "TestingSupport/TestUtilities.h"
16 #include "lldb/Core/Debugger.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Host/HostInfo.h"
19 #include "lldb/Target/Target.h"
20 #include "gmock/gmock.h"
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace lldb_private::platform_android;
25 using namespace lldb_private::platform_linux;
26 using namespace lldb_private::breakpad;
27 using namespace testing;
29 namespace {
31 constexpr llvm::StringLiteral k_process_plugin("mock-process-plugin");
32 constexpr llvm::StringLiteral k_platform_dir("remote-android");
33 constexpr llvm::StringLiteral k_cache_dir(".cache");
34 constexpr llvm::StringLiteral k_module_file("AndroidModule.so");
35 constexpr llvm::StringLiteral k_symbol_file("AndroidModule.unstripped.so");
36 constexpr llvm::StringLiteral k_breakpad_symbol_file("AndroidModule.so.sym");
37 constexpr llvm::StringLiteral k_arch("aarch64-none-linux");
38 constexpr llvm::StringLiteral
39 k_module_uuid("80008338-82A0-51E5-5922-C905D23890DA-BDDEFECC");
40 constexpr llvm::StringLiteral k_function_symbol("boom");
41 constexpr llvm::StringLiteral k_hidden_function_symbol("boom_hidden");
42 const size_t k_module_size = 3784;
44 ModuleSpec GetTestModuleSpec();
46 class MockProcess : public Process {
47 public:
48 MockProcess(TargetSP target_sp, ListenerSP listener_sp)
49 : Process(target_sp, listener_sp) {}
51 llvm::StringRef GetPluginName() override { return k_process_plugin; };
53 bool CanDebug(TargetSP target, bool plugin_specified_by_name) override {
54 return true;
57 Status DoDestroy() override { return Status(); }
59 void RefreshStateAfterStop() override {}
61 bool DoUpdateThreadList(ThreadList &old_thread_list,
62 ThreadList &new_thread_list) override {
63 return false;
66 size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size,
67 Status &error) override {
68 return 0;
71 bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch,
72 ModuleSpec &module_spec) override {
73 module_spec = GetTestModuleSpec();
74 return true;
78 FileSpec GetTestDir() {
79 const auto *info = UnitTest::GetInstance()->current_test_info();
80 FileSpec test_dir = HostInfo::GetProcessTempDir();
81 test_dir.AppendPathComponent(std::string(info->test_case_name()) + "-" +
82 info->name());
83 std::error_code ec = llvm::sys::fs::create_directory(test_dir.GetPath());
84 EXPECT_FALSE(ec);
85 return test_dir;
88 FileSpec GetRemotePath() {
89 FileSpec fs("/", FileSpec::Style::posix);
90 fs.AppendPathComponent("bin");
91 fs.AppendPathComponent(k_module_file);
92 return fs;
95 FileSpec GetUuidView(FileSpec spec) {
96 spec.AppendPathComponent(k_platform_dir);
97 spec.AppendPathComponent(k_cache_dir);
98 spec.AppendPathComponent(k_module_uuid);
99 spec.AppendPathComponent(k_module_file);
100 return spec;
103 void BuildEmptyCacheDir(const FileSpec &test_dir) {
104 FileSpec cache_dir(test_dir);
105 cache_dir.AppendPathComponent(k_platform_dir);
106 cache_dir.AppendPathComponent(k_cache_dir);
107 std::error_code ec = llvm::sys::fs::create_directories(cache_dir.GetPath());
108 EXPECT_FALSE(ec);
111 FileSpec BuildCacheDir(const FileSpec &test_dir) {
112 FileSpec uuid_view = GetUuidView(test_dir);
113 std::error_code ec =
114 llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
115 EXPECT_FALSE(ec);
116 ec = llvm::sys::fs::copy_file(GetInputFilePath(k_module_file),
117 uuid_view.GetPath().c_str());
118 EXPECT_FALSE(ec);
119 return uuid_view;
122 FileSpec GetSymFileSpec(const FileSpec &uuid_view) {
123 return FileSpec(uuid_view.GetPath() + ".sym");
126 FileSpec BuildCacheDirWithSymbol(const FileSpec &test_dir) {
127 FileSpec uuid_view = BuildCacheDir(test_dir);
128 std::error_code ec =
129 llvm::sys::fs::copy_file(GetInputFilePath(k_symbol_file),
130 GetSymFileSpec(uuid_view).GetPath().c_str());
131 EXPECT_FALSE(ec);
132 return uuid_view;
135 FileSpec BuildCacheDirWithBreakpadSymbol(const FileSpec &test_dir) {
136 FileSpec uuid_view = BuildCacheDir(test_dir);
137 std::error_code ec =
138 llvm::sys::fs::copy_file(GetInputFilePath(k_breakpad_symbol_file),
139 GetSymFileSpec(uuid_view).GetPath().c_str());
140 EXPECT_FALSE(ec);
141 return uuid_view;
144 ModuleSpec GetTestModuleSpec() {
145 ModuleSpec module_spec(GetRemotePath(), ArchSpec(k_arch));
146 module_spec.GetUUID().SetFromStringRef(k_module_uuid);
147 module_spec.SetObjectSize(k_module_size);
148 return module_spec;
151 void CheckModule(const ModuleSP &module_sp) {
152 ASSERT_TRUE(module_sp);
153 ASSERT_EQ(module_sp->GetUUID().GetAsString(), k_module_uuid);
154 ASSERT_EQ(module_sp->GetObjectOffset(), 0U);
155 ASSERT_EQ(module_sp->GetPlatformFileSpec(), GetRemotePath());
158 SymbolContextList FindFunctions(const ModuleSP &module_sp,
159 const llvm::StringRef &name) {
160 SymbolContextList sc_list;
161 ModuleFunctionSearchOptions function_options;
162 function_options.include_symbols = true;
163 function_options.include_inlines = true;
164 FunctionNameType type = static_cast<FunctionNameType>(eSymbolTypeCode);
165 module_sp->FindFunctions(ConstString(name), CompilerDeclContext(), type,
166 function_options, sc_list);
167 return sc_list;
170 void CheckStrippedSymbol(const ModuleSP &module_sp) {
171 SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol);
172 EXPECT_EQ(1U, sc_list.GetSize());
174 sc_list = FindFunctions(module_sp, k_hidden_function_symbol);
175 EXPECT_EQ(0U, sc_list.GetSize());
178 void CheckUnstrippedSymbol(const ModuleSP &module_sp) {
179 SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol);
180 EXPECT_EQ(1U, sc_list.GetSize());
182 sc_list = FindFunctions(module_sp, k_hidden_function_symbol);
183 EXPECT_EQ(1U, sc_list.GetSize());
186 ProcessSP MockProcessCreateInstance(TargetSP target_sp, ListenerSP listener_sp,
187 const FileSpec *crash_file_path,
188 bool can_connect) {
189 return std::make_shared<MockProcess>(target_sp, listener_sp);
192 class LocateModuleCallbackTest : public testing::Test {
193 SubsystemRAII<FileSystem, HostInfo, ObjectFileBreakpad, ObjectFileELF,
194 PlatformAndroid, PlatformLinux, SymbolFileBreakpad,
195 SymbolFileSymtab>
196 subsystems;
198 public:
199 void SetUp() override {
200 m_test_dir = GetTestDir();
202 // Set module cache directory for PlatformAndroid.
203 PlatformAndroid::GetGlobalPlatformProperties().SetModuleCacheDirectory(
204 m_test_dir);
206 // Create Debugger.
207 ArchSpec host_arch("i386-pc-linux");
208 Platform::SetHostPlatform(
209 platform_linux::PlatformLinux::CreateInstance(true, &host_arch));
210 m_debugger_sp = Debugger::CreateInstance();
211 EXPECT_TRUE(m_debugger_sp);
213 // Create PlatformAndroid.
214 ArchSpec arch(k_arch);
215 m_platform_sp = PlatformAndroid::CreateInstance(true, &arch);
216 EXPECT_TRUE(m_platform_sp);
218 // Create Target.
219 m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,
220 eLoadDependentsNo,
221 m_platform_sp, m_target_sp);
222 EXPECT_TRUE(m_target_sp);
224 // Create MockProcess.
225 PluginManager::RegisterPlugin(k_process_plugin, "",
226 MockProcessCreateInstance);
227 m_process_sp =
228 m_target_sp->CreateProcess(Listener::MakeListener("test-listener"),
229 k_process_plugin, /*crash_file=*/nullptr,
230 /*can_connect=*/true);
231 EXPECT_TRUE(m_process_sp);
233 m_module_spec = GetTestModuleSpec();
234 m_module_spec_without_uuid = ModuleSpec(GetRemotePath(), ArchSpec(k_arch));
237 void TearDown() override {
238 if (m_module_sp)
239 ModuleList::RemoveSharedModule(m_module_sp);
242 void CheckNoCallback() {
243 EXPECT_FALSE(m_platform_sp->GetLocateModuleCallback());
244 EXPECT_EQ(m_callback_call_count, 0);
247 void CheckCallbackArgs(const ModuleSpec &module_spec,
248 FileSpec &module_file_spec, FileSpec &symbol_file_spec,
249 const ModuleSpec &expected_module_spec,
250 int expected_callback_call_count) {
251 EXPECT_TRUE(expected_module_spec.Matches(module_spec,
252 /*exact_arch_match=*/true));
253 EXPECT_FALSE(module_file_spec);
254 EXPECT_FALSE(symbol_file_spec);
256 EXPECT_EQ(++m_callback_call_count, expected_callback_call_count);
259 void CheckCallbackArgsWithUUID(const ModuleSpec &module_spec,
260 FileSpec &module_file_spec,
261 FileSpec &symbol_file_spec,
262 int expected_callback_call_count) {
263 CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec,
264 m_module_spec, expected_callback_call_count);
265 EXPECT_TRUE(module_spec.GetUUID().IsValid());
268 void CheckCallbackArgsWithoutUUID(const ModuleSpec &module_spec,
269 FileSpec &module_file_spec,
270 FileSpec &symbol_file_spec,
271 int expected_callback_call_count) {
272 CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec,
273 m_module_spec_without_uuid, expected_callback_call_count);
274 EXPECT_FALSE(module_spec.GetUUID().IsValid());
277 protected:
278 FileSpec m_test_dir;
279 DebuggerSP m_debugger_sp;
280 PlatformSP m_platform_sp;
281 TargetSP m_target_sp;
282 ProcessSP m_process_sp;
283 ModuleSpec m_module_spec;
284 ModuleSpec m_module_spec_without_uuid;
285 ModuleSP m_module_sp;
286 int m_callback_call_count = 0;
289 } // namespace
291 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModule) {
292 // The module file is cached, and the locate module callback is not set.
293 // GetOrCreateModule should succeed to return the module from the cache.
294 FileSpec uuid_view = BuildCacheDir(m_test_dir);
296 CheckNoCallback();
298 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
299 CheckModule(m_module_sp);
300 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
301 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
302 CheckStrippedSymbol(m_module_sp);
305 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModuleAndSymbol) {
306 // The module and symbol files are cached, and the locate module callback is
307 // not set. GetOrCreateModule should succeed to return the module from the
308 // cache with the symbol.
309 FileSpec uuid_view = BuildCacheDirWithSymbol(m_test_dir);
311 CheckNoCallback();
313 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
314 CheckModule(m_module_sp);
315 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
316 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view));
317 CheckUnstrippedSymbol(m_module_sp);
320 TEST_F(LocateModuleCallbackTest,
321 GetOrCreateModuleWithCachedModuleAndBreakpadSymbol) {
322 // The module file and breakpad symbol file are cached, and the locate module
323 // callback is not set. GetOrCreateModule should succeed to return the module
324 // from the cache with the symbol.
325 FileSpec uuid_view = BuildCacheDirWithBreakpadSymbol(m_test_dir);
327 CheckNoCallback();
329 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
330 CheckModule(m_module_sp);
331 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
332 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view));
333 CheckUnstrippedSymbol(m_module_sp);
336 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleFailure) {
337 // The cache dir is empty, and the locate module callback is not set.
338 // GetOrCreateModule should fail because PlatformAndroid tries to download the
339 // module and fails.
340 BuildEmptyCacheDir(m_test_dir);
342 CheckNoCallback();
344 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
345 ASSERT_FALSE(m_module_sp);
348 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureNoCache) {
349 // The cache dir is empty, also the locate module callback fails for some
350 // reason. GetOrCreateModule should fail because PlatformAndroid tries to
351 // download the module and fails.
352 BuildEmptyCacheDir(m_test_dir);
354 int callback_call_count = 0;
355 m_platform_sp->SetLocateModuleCallback(
356 [this, &callback_call_count](const ModuleSpec &module_spec,
357 FileSpec &module_file_spec,
358 FileSpec &symbol_file_spec) {
359 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
360 symbol_file_spec, ++callback_call_count);
361 return Status::FromErrorString("The locate module callback failed");
364 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
365 ASSERT_EQ(callback_call_count, 2);
366 ASSERT_FALSE(m_module_sp);
369 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureCached) {
370 // The module file is cached, so GetOrCreateModule should succeed to return
371 // the module from the cache even though the locate module callback fails for
372 // some reason.
373 FileSpec uuid_view = BuildCacheDir(m_test_dir);
375 int callback_call_count = 0;
376 m_platform_sp->SetLocateModuleCallback(
377 [this, &callback_call_count](const ModuleSpec &module_spec,
378 FileSpec &module_file_spec,
379 FileSpec &symbol_file_spec) {
380 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
381 symbol_file_spec, ++callback_call_count);
382 return Status::FromErrorString("The locate module callback failed");
385 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
386 ASSERT_EQ(callback_call_count, 2);
387 CheckModule(m_module_sp);
388 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
389 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
390 CheckStrippedSymbol(m_module_sp);
393 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNoFiles) {
394 // The module file is cached, so GetOrCreateModule should succeed to return
395 // the module from the cache even though the locate module callback returns
396 // no files.
397 FileSpec uuid_view = BuildCacheDir(m_test_dir);
399 int callback_call_count = 0;
400 m_platform_sp->SetLocateModuleCallback(
401 [this, &callback_call_count](const ModuleSpec &module_spec,
402 FileSpec &module_file_spec,
403 FileSpec &symbol_file_spec) {
404 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
405 symbol_file_spec, ++callback_call_count);
406 // The locate module callback succeeds but it does not set
407 // module_file_spec nor symbol_file_spec.
408 return Status();
411 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
412 ASSERT_EQ(callback_call_count, 2);
413 CheckModule(m_module_sp);
414 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
415 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
416 CheckStrippedSymbol(m_module_sp);
417 ModuleList::RemoveSharedModule(m_module_sp);
420 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentModule) {
421 // The module file is cached, so GetOrCreateModule should succeed to return
422 // the module from the cache even though the locate module callback returns
423 // non-existent module file.
424 FileSpec uuid_view = BuildCacheDir(m_test_dir);
426 int callback_call_count = 0;
427 m_platform_sp->SetLocateModuleCallback(
428 [this, &callback_call_count](const ModuleSpec &module_spec,
429 FileSpec &module_file_spec,
430 FileSpec &symbol_file_spec) {
431 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
432 symbol_file_spec, ++callback_call_count);
433 module_file_spec.SetPath("/this path does not exist");
434 return Status();
437 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
438 ASSERT_EQ(callback_call_count, 2);
439 CheckModule(m_module_sp);
440 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
441 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
442 CheckStrippedSymbol(m_module_sp);
443 ModuleList::RemoveSharedModule(m_module_sp);
446 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentSymbol) {
447 // The module file is cached, so GetOrCreateModule should succeed to return
448 // the module from the cache even though the locate module callback returns
449 // non-existent symbol file.
450 FileSpec uuid_view = BuildCacheDir(m_test_dir);
452 int callback_call_count = 0;
453 m_platform_sp->SetLocateModuleCallback(
454 [this, &callback_call_count](const ModuleSpec &module_spec,
455 FileSpec &module_file_spec,
456 FileSpec &symbol_file_spec) {
457 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
458 symbol_file_spec, ++callback_call_count);
459 // The locate module callback returns a right module file.
460 module_file_spec.SetPath(GetInputFilePath(k_module_file));
461 // But it returns non-existent symbols file.
462 symbol_file_spec.SetPath("/this path does not exist");
463 return Status();
466 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
467 ASSERT_EQ(callback_call_count, 2);
468 CheckModule(m_module_sp);
469 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
470 ASSERT_TRUE(m_module_sp->GetSymbolFileFileSpec().GetPath().empty());
471 CheckStrippedSymbol(m_module_sp);
472 ModuleList::RemoveSharedModule(m_module_sp);
475 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackSuccessWithModule) {
476 // The locate module callback returns a module file, GetOrCreateModule should
477 // succeed to return the module from the Inputs directory.
478 BuildEmptyCacheDir(m_test_dir);
480 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
481 FileSpec &module_file_spec,
482 FileSpec &symbol_file_spec) {
483 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
485 module_file_spec.SetPath(GetInputFilePath(k_module_file));
486 return Status();
489 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
490 CheckModule(m_module_sp);
491 ASSERT_EQ(m_module_sp->GetFileSpec(),
492 FileSpec(GetInputFilePath(k_module_file)));
493 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
494 CheckStrippedSymbol(m_module_sp);
495 ModuleList::RemoveSharedModule(m_module_sp);
498 TEST_F(LocateModuleCallbackTest,
499 GetOrCreateModuleCallbackSuccessWithSymbolAsModule) {
500 // The locate module callback returns the symbol file as a module file. It
501 // should work since the sections and UUID of the symbol file are the exact
502 // same with the module file, GetOrCreateModule should succeed to return the
503 // module with the symbol file from Inputs directory.
504 BuildEmptyCacheDir(m_test_dir);
506 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
507 FileSpec &module_file_spec,
508 FileSpec &symbol_file_spec) {
509 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
511 module_file_spec.SetPath(GetInputFilePath(k_symbol_file));
512 return Status();
515 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
516 CheckModule(m_module_sp);
517 ASSERT_EQ(m_module_sp->GetFileSpec(),
518 FileSpec(GetInputFilePath(k_symbol_file)));
519 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
520 CheckUnstrippedSymbol(m_module_sp);
521 ModuleList::RemoveSharedModule(m_module_sp);
524 TEST_F(LocateModuleCallbackTest,
525 GetOrCreateModuleCallbackSuccessWithSymbolAsModuleAndSymbol) {
526 // The locate module callback returns a symbol file as both a module file and
527 // a symbol file. It should work since the sections and UUID of the symbol
528 // file are the exact same with the module file, GetOrCreateModule should
529 // succeed to return the module with the symbol file from Inputs directory.
530 BuildEmptyCacheDir(m_test_dir);
532 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
533 FileSpec &module_file_spec,
534 FileSpec &symbol_file_spec) {
535 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
537 module_file_spec.SetPath(GetInputFilePath(k_symbol_file));
538 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
539 return Status();
542 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
543 CheckModule(m_module_sp);
544 ASSERT_EQ(m_module_sp->GetFileSpec(),
545 FileSpec(GetInputFilePath(k_symbol_file)));
546 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
547 FileSpec(GetInputFilePath(k_symbol_file)));
548 CheckUnstrippedSymbol(m_module_sp);
549 ModuleList::RemoveSharedModule(m_module_sp);
552 TEST_F(LocateModuleCallbackTest,
553 GetOrCreateModuleCallbackSuccessWithModuleAndSymbol) {
554 // The locate module callback returns a module file and a symbol file,
555 // GetOrCreateModule should succeed to return the module from Inputs
556 // directory, along with the symbol file.
557 BuildEmptyCacheDir(m_test_dir);
559 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
560 FileSpec &module_file_spec,
561 FileSpec &symbol_file_spec) {
562 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
564 module_file_spec.SetPath(GetInputFilePath(k_module_file));
565 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
566 return Status();
569 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
570 CheckModule(m_module_sp);
571 ASSERT_EQ(m_module_sp->GetFileSpec(),
572 FileSpec(GetInputFilePath(k_module_file)));
573 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
574 FileSpec(GetInputFilePath(k_symbol_file)));
575 CheckUnstrippedSymbol(m_module_sp);
576 ModuleList::RemoveSharedModule(m_module_sp);
579 TEST_F(LocateModuleCallbackTest,
580 GetOrCreateModuleCallbackSuccessWithModuleAndBreakpadSymbol) {
581 // The locate module callback returns a module file and a breakpad symbol
582 // file, GetOrCreateModule should succeed to return the module with the symbol
583 // file from Inputs directory.
584 BuildEmptyCacheDir(m_test_dir);
586 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec,
587 FileSpec &module_file_spec,
588 FileSpec &symbol_file_spec) {
589 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec,
591 module_file_spec.SetPath(GetInputFilePath(k_module_file));
592 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
593 return Status();
596 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
597 CheckModule(m_module_sp);
598 ASSERT_EQ(m_module_sp->GetFileSpec(),
599 FileSpec(GetInputFilePath(k_module_file)));
600 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
601 FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
602 CheckUnstrippedSymbol(m_module_sp);
603 ModuleList::RemoveSharedModule(m_module_sp);
606 TEST_F(LocateModuleCallbackTest,
607 GetOrCreateModuleCallbackSuccessWithOnlySymbol) {
608 // The get callback returns only a symbol file, and the module is cached,
609 // GetOrCreateModule should succeed to return the module from the cache
610 // along with the symbol file from the Inputs directory.
611 FileSpec uuid_view = BuildCacheDir(m_test_dir);
613 int callback_call_count = 0;
614 m_platform_sp->SetLocateModuleCallback(
615 [this, &callback_call_count](const ModuleSpec &module_spec,
616 FileSpec &module_file_spec,
617 FileSpec &symbol_file_spec) {
618 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
619 symbol_file_spec, ++callback_call_count);
620 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
621 return Status();
624 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
625 ASSERT_EQ(callback_call_count, 2);
626 CheckModule(m_module_sp);
627 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
628 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
629 FileSpec(GetInputFilePath(k_symbol_file)));
630 CheckUnstrippedSymbol(m_module_sp);
631 ModuleList::RemoveSharedModule(m_module_sp);
634 TEST_F(LocateModuleCallbackTest,
635 GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbol) {
636 // The get callback returns only a breakpad symbol file, and the module is
637 // cached, GetOrCreateModule should succeed to return the module from the
638 // cache along with the symbol file from the Inputs directory.
639 FileSpec uuid_view = BuildCacheDir(m_test_dir);
641 int callback_call_count = 0;
642 m_platform_sp->SetLocateModuleCallback(
643 [this, &callback_call_count](const ModuleSpec &module_spec,
644 FileSpec &module_file_spec,
645 FileSpec &symbol_file_spec) {
646 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
647 symbol_file_spec, ++callback_call_count);
648 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
649 return Status();
652 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
653 ASSERT_EQ(callback_call_count, 2);
654 CheckModule(m_module_sp);
655 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
656 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
657 FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
658 CheckUnstrippedSymbol(m_module_sp);
659 ModuleList::RemoveSharedModule(m_module_sp);
662 TEST_F(LocateModuleCallbackTest,
663 GetOrCreateModuleCallbackSuccessWithMultipleSymbols) {
664 // The get callback returns only a symbol file. The first call returns
665 // a breakpad symbol file and the second call returns a symbol file.
666 // Also the module is cached, so GetOrCreateModule should succeed to return
667 // the module from the cache along with the breakpad symbol file from the
668 // Inputs directory because GetOrCreateModule will use the first symbol file
669 // from the callback.
670 FileSpec uuid_view = BuildCacheDir(m_test_dir);
672 int callback_call_count = 0;
673 m_platform_sp->SetLocateModuleCallback(
674 [this, &callback_call_count](const ModuleSpec &module_spec,
675 FileSpec &module_file_spec,
676 FileSpec &symbol_file_spec) {
677 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
678 symbol_file_spec, ++callback_call_count);
679 symbol_file_spec.SetPath(GetInputFilePath(
680 callback_call_count == 1 ? k_breakpad_symbol_file : k_symbol_file));
681 return Status();
684 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
685 ASSERT_EQ(callback_call_count, 2);
686 CheckModule(m_module_sp);
687 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
688 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
689 FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
690 CheckUnstrippedSymbol(m_module_sp);
691 ModuleList::RemoveSharedModule(m_module_sp);
694 TEST_F(LocateModuleCallbackTest,
695 GetOrCreateModuleNoCacheWithCallbackOnlySymbol) {
696 // The get callback returns only a symbol file, but the module is not
697 // cached, GetOrCreateModule should fail because of the missing module.
698 BuildEmptyCacheDir(m_test_dir);
700 int callback_call_count = 0;
701 m_platform_sp->SetLocateModuleCallback(
702 [this, &callback_call_count](const ModuleSpec &module_spec,
703 FileSpec &module_file_spec,
704 FileSpec &symbol_file_spec) {
705 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
706 symbol_file_spec, ++callback_call_count);
707 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
708 return Status();
711 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
712 ASSERT_EQ(callback_call_count, 2);
713 ASSERT_FALSE(m_module_sp);
716 TEST_F(LocateModuleCallbackTest,
717 GetOrCreateModuleNoCacheWithCallbackOnlyBreakpadSymbol) {
718 // The get callback returns only a breakpad symbol file, but the module is not
719 // cached, GetOrCreateModule should fail because of the missing module.
720 BuildEmptyCacheDir(m_test_dir);
722 int callback_call_count = 0;
723 m_platform_sp->SetLocateModuleCallback(
724 [this, &callback_call_count](const ModuleSpec &module_spec,
725 FileSpec &module_file_spec,
726 FileSpec &symbol_file_spec) {
727 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
728 symbol_file_spec, ++callback_call_count);
729 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
730 return Status();
733 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false);
734 ASSERT_EQ(callback_call_count, 2);
735 ASSERT_FALSE(m_module_sp);
738 TEST_F(LocateModuleCallbackTest,
739 GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID) {
740 // This is a simulation for Android remote platform debugging.
741 // The locate module callback first call fails because module_spec does not
742 // have UUID. Then, the callback second call returns a module file because the
743 // platform resolved the module_spec UUID from the target process.
744 // GetOrCreateModule should succeed to return the module from the Inputs
745 // directory.
746 BuildEmptyCacheDir(m_test_dir);
748 int callback_call_count = 0;
749 m_platform_sp->SetLocateModuleCallback(
750 [this, &callback_call_count](const ModuleSpec &module_spec,
751 FileSpec &module_file_spec,
752 FileSpec &symbol_file_spec) {
753 callback_call_count++;
754 if (callback_call_count == 1) {
755 // The module_spec does not have UUID on the first call.
756 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
757 symbol_file_spec, callback_call_count);
758 return Status::FromErrorString("Ignored empty UUID");
759 } else {
760 // The module_spec has UUID on the second call.
761 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
762 symbol_file_spec, callback_call_count);
763 module_file_spec.SetPath(GetInputFilePath(k_module_file));
764 return Status();
768 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
769 /*notify=*/false);
770 ASSERT_EQ(callback_call_count, 2);
771 CheckModule(m_module_sp);
772 ASSERT_EQ(m_module_sp->GetFileSpec(),
773 FileSpec(GetInputFilePath(k_module_file)));
774 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec());
775 CheckStrippedSymbol(m_module_sp);
776 ModuleList::RemoveSharedModule(m_module_sp);
779 TEST_F(LocateModuleCallbackTest,
780 GetOrCreateModuleCallbackSuccessWithSymbolByPlatformUUID) {
781 // Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID,
782 // but with a symbol file. GetOrCreateModule should succeed to return the
783 // module file and the symbol file from the Inputs directory.
784 BuildEmptyCacheDir(m_test_dir);
786 int callback_call_count = 0;
787 m_platform_sp->SetLocateModuleCallback(
788 [this, &callback_call_count](const ModuleSpec &module_spec,
789 FileSpec &module_file_spec,
790 FileSpec &symbol_file_spec) {
791 callback_call_count++;
792 if (callback_call_count == 1) {
793 // The module_spec does not have UUID on the first call.
794 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
795 symbol_file_spec, callback_call_count);
796 return Status::FromErrorString("Ignored empty UUID");
797 } else {
798 // The module_spec has UUID on the second call.
799 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
800 symbol_file_spec, callback_call_count);
801 module_file_spec.SetPath(GetInputFilePath(k_module_file));
802 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file));
803 return Status();
807 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
808 /*notify=*/false);
809 ASSERT_EQ(callback_call_count, 2);
810 CheckModule(m_module_sp);
811 ASSERT_EQ(m_module_sp->GetFileSpec(),
812 FileSpec(GetInputFilePath(k_module_file)));
813 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
814 FileSpec(GetInputFilePath(k_symbol_file)));
815 CheckUnstrippedSymbol(m_module_sp);
816 ModuleList::RemoveSharedModule(m_module_sp);
819 TEST_F(LocateModuleCallbackTest,
820 GetOrCreateModuleCallbackSuccessWithBreakpadSymbolByPlatformUUID) {
821 // Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID,
822 // but with a breakpad symbol file. GetOrCreateModule should succeed to return
823 // the module file and the symbol file from the Inputs directory.
824 BuildEmptyCacheDir(m_test_dir);
826 int callback_call_count = 0;
827 m_platform_sp->SetLocateModuleCallback(
828 [this, &callback_call_count](const ModuleSpec &module_spec,
829 FileSpec &module_file_spec,
830 FileSpec &symbol_file_spec) {
831 callback_call_count++;
832 if (callback_call_count == 1) {
833 // The module_spec does not have UUID on the first call.
834 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
835 symbol_file_spec, callback_call_count);
836 return Status::FromErrorString("Ignored empty UUID");
837 } else {
838 // The module_spec has UUID on the second call.
839 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
840 symbol_file_spec, callback_call_count);
841 module_file_spec.SetPath(GetInputFilePath(k_module_file));
842 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
843 return Status();
847 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
848 /*notify=*/false);
849 ASSERT_EQ(callback_call_count, 2);
850 CheckModule(m_module_sp);
851 ASSERT_EQ(m_module_sp->GetFileSpec(),
852 FileSpec(GetInputFilePath(k_module_file)));
853 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
854 FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
855 CheckUnstrippedSymbol(m_module_sp);
856 ModuleList::RemoveSharedModule(m_module_sp);
859 TEST_F(LocateModuleCallbackTest,
860 GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbolByPlatformUUID) {
861 // This is a simulation for Android remote platform debugging.
862 // The locate module callback first call fails because module_spec does not
863 // have UUID. Then, the callback second call returns a breakpad symbol file
864 // for the UUID from the target process. GetOrCreateModule should succeed to
865 // return the module from the cache along with the symbol file from the Inputs
866 // directory.
867 FileSpec uuid_view = BuildCacheDir(m_test_dir);
869 int callback_call_count = 0;
870 m_platform_sp->SetLocateModuleCallback(
871 [this, &callback_call_count](const ModuleSpec &module_spec,
872 FileSpec &module_file_spec,
873 FileSpec &symbol_file_spec) {
874 callback_call_count++;
875 if (callback_call_count == 1) {
876 // The module_spec does not have UUID on the first call.
877 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec,
878 symbol_file_spec, callback_call_count);
879 return Status::FromErrorString("Ignored empty UUID");
880 } else {
881 // The module_spec has UUID on the second call.
882 CheckCallbackArgsWithUUID(module_spec, module_file_spec,
883 symbol_file_spec, callback_call_count);
884 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file));
885 return Status();
889 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid,
890 /*notify=*/false);
891 ASSERT_EQ(callback_call_count, 2);
892 CheckModule(m_module_sp);
893 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view);
894 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(),
895 FileSpec(GetInputFilePath(k_breakpad_symbol_file)));
896 CheckUnstrippedSymbol(m_module_sp);
897 ModuleList::RemoveSharedModule(m_module_sp);