1 //===-- LocateModuleCallbackTest.cpp --------------------------------------===//
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
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"
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
;
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
{
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
{
57 Status
DoDestroy() override
{ return Status(); }
59 void RefreshStateAfterStop() override
{}
61 bool DoUpdateThreadList(ThreadList
&old_thread_list
,
62 ThreadList
&new_thread_list
) override
{
66 size_t DoReadMemory(addr_t vm_addr
, void *buf
, size_t size
,
67 Status
&error
) override
{
71 bool GetModuleSpec(const FileSpec
&module_file_spec
, const ArchSpec
&arch
,
72 ModuleSpec
&module_spec
) override
{
73 module_spec
= GetTestModuleSpec();
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()) + "-" +
83 std::error_code ec
= llvm::sys::fs::create_directory(test_dir
.GetPath());
88 FileSpec
GetRemotePath() {
89 FileSpec
fs("/", FileSpec::Style::posix
);
90 fs
.AppendPathComponent("bin");
91 fs
.AppendPathComponent(k_module_file
);
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
);
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());
111 FileSpec
BuildCacheDir(const FileSpec
&test_dir
) {
112 FileSpec uuid_view
= GetUuidView(test_dir
);
114 llvm::sys::fs::create_directories(uuid_view
.GetDirectory().GetCString());
116 ec
= llvm::sys::fs::copy_file(GetInputFilePath(k_module_file
),
117 uuid_view
.GetPath().c_str());
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
);
129 llvm::sys::fs::copy_file(GetInputFilePath(k_symbol_file
),
130 GetSymFileSpec(uuid_view
).GetPath().c_str());
135 FileSpec
BuildCacheDirWithBreakpadSymbol(const FileSpec
&test_dir
) {
136 FileSpec uuid_view
= BuildCacheDir(test_dir
);
138 llvm::sys::fs::copy_file(GetInputFilePath(k_breakpad_symbol_file
),
139 GetSymFileSpec(uuid_view
).GetPath().c_str());
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
);
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
);
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
,
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
,
199 void SetUp() override
{
200 m_test_dir
= GetTestDir();
202 // Set module cache directory for PlatformAndroid.
203 PlatformAndroid::GetGlobalPlatformProperties().SetModuleCacheDirectory(
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
);
219 m_debugger_sp
->GetTargetList().CreateTarget(*m_debugger_sp
, "", arch
,
221 m_platform_sp
, m_target_sp
);
222 EXPECT_TRUE(m_target_sp
);
224 // Create MockProcess.
225 PluginManager::RegisterPlugin(k_process_plugin
, "",
226 MockProcessCreateInstance
);
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
{
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());
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;
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
);
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
);
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
);
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
340 BuildEmptyCacheDir(m_test_dir
);
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("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
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("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
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.
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");
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");
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
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("Ignored empty UUID");
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
));
768 m_module_sp
= m_target_sp
->GetOrCreateModule(m_module_spec_without_uuid
,
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("Ignored empty UUID");
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
));
807 m_module_sp
= m_target_sp
->GetOrCreateModule(m_module_spec_without_uuid
,
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("Ignored empty UUID");
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
));
847 m_module_sp
= m_target_sp
->GetOrCreateModule(m_module_spec_without_uuid
,
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
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("Ignored empty UUID");
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
));
889 m_module_sp
= m_target_sp
->GetOrCreateModule(m_module_spec_without_uuid
,
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
);