llvm-project/lldb/unittests/Target/RemoteAwarePlatformTest.cpp

93 lines
3.3 KiB
C++
Raw Normal View History

//===-- RemoteAwarePlatformTest.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Target/RemoteAwarePlatform.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using namespace lldb_private;
using namespace lldb;
using namespace testing;
class RemoteAwarePlatformTester : public RemoteAwarePlatform {
public:
using RemoteAwarePlatform::RemoteAwarePlatform;
MOCK_METHOD0(GetDescription, llvm::StringRef());
MOCK_METHOD0(GetPluginName, llvm::StringRef());
MOCK_METHOD1(GetSupportedArchitectures,
std::vector<ArchSpec>(const ArchSpec &process_host_arch));
MOCK_METHOD4(Attach,
ProcessSP(ProcessAttachInfo &, Debugger &, Target *, Status &));
MOCK_METHOD0(CalculateTrapHandlerSymbolNames, void());
[lldb] Refactor Platform::ResolveExecutable Module resolution is probably the most complex piece of lldb [citation needed], with numerous levels of abstraction, each one implementing various retry and fallback strategies. It is also a very repetitive, with only small differences between "host", "remote-and-connected" and "remote-but-not-(yet)-connected" scenarios. The goal of this patch (first in series) is to reduce the number of abstractions, and deduplicate the code. One of the reasons for this complexity is the tension between the desire to offload the process of module resolution to the remote platform instance (that's how most other platform methods work), and the desire to keep it local to the outer platform class (its easier to subclass the outer class, and it generally makes more sense). This patch resolves that conflict in favour of doing everything in the outer class. The gdb-remote (our only remote platform) implementation of ResolveExecutable was not doing anything gdb-specific, and was rather similar to the other implementations of that method (any divergence is most likely the result of fixes not being applied everywhere rather than intentional). It does this by excising the remote platform out of the resolution codepath. The gdb-remote implementation of ResolveExecutable is moved to Platform::ResolveRemoteExecutable, and the (only) call site is redirected to that. On its own, this does not achieve (much), but it creates new opportunities for layer peeling and code sharing, since all of the code now lives closer together. Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 23:32:57 +08:00
MOCK_METHOD2(ResolveRemoteExecutable,
std::pair<Status, ModuleSP>(const ModuleSpec &,
const FileSpecList *));
Status ResolveRemoteExecutable(
const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) /*override*/ {
auto pair = ResolveRemoteExecutable(module_spec, module_search_paths_ptr);
exe_module_sp = pair.second;
return pair.first;
}
void SetRemotePlatform(lldb::PlatformSP platform) {
m_remote_platform_sp = platform;
}
};
class TargetPlatformTester : public Platform {
public:
using Platform::Platform;
MOCK_METHOD0(GetDescription, llvm::StringRef());
MOCK_METHOD0(GetPluginName, llvm::StringRef());
MOCK_METHOD1(GetSupportedArchitectures,
std::vector<ArchSpec>(const ArchSpec &process_host_arch));
MOCK_METHOD4(Attach,
ProcessSP(ProcessAttachInfo &, Debugger &, Target *, Status &));
MOCK_METHOD0(CalculateTrapHandlerSymbolNames, void());
MOCK_METHOD0(GetUserIDResolver, UserIDResolver &());
};
namespace {
class RemoteAwarePlatformTest : public testing::Test {
public:
static void SetUpTestCase() { FileSystem::Initialize(); }
static void TearDownTestCase() { FileSystem::Terminate(); }
};
} // namespace
TEST_F(RemoteAwarePlatformTest, TestResolveExecutabelOnClientByPlatform) {
ModuleSpec executable_spec;
ModuleSP expected_executable(new Module(executable_spec));
RemoteAwarePlatformTester platform(false);
static const ArchSpec process_host_arch;
EXPECT_CALL(platform, GetSupportedArchitectures(process_host_arch))
.WillRepeatedly(Return(std::vector<ArchSpec>()));
[lldb] Refactor Platform::ResolveExecutable Module resolution is probably the most complex piece of lldb [citation needed], with numerous levels of abstraction, each one implementing various retry and fallback strategies. It is also a very repetitive, with only small differences between "host", "remote-and-connected" and "remote-but-not-(yet)-connected" scenarios. The goal of this patch (first in series) is to reduce the number of abstractions, and deduplicate the code. One of the reasons for this complexity is the tension between the desire to offload the process of module resolution to the remote platform instance (that's how most other platform methods work), and the desire to keep it local to the outer platform class (its easier to subclass the outer class, and it generally makes more sense). This patch resolves that conflict in favour of doing everything in the outer class. The gdb-remote (our only remote platform) implementation of ResolveExecutable was not doing anything gdb-specific, and was rather similar to the other implementations of that method (any divergence is most likely the result of fixes not being applied everywhere rather than intentional). It does this by excising the remote platform out of the resolution codepath. The gdb-remote implementation of ResolveExecutable is moved to Platform::ResolveRemoteExecutable, and the (only) call site is redirected to that. On its own, this does not achieve (much), but it creates new opportunities for layer peeling and code sharing, since all of the code now lives closer together. Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 23:32:57 +08:00
EXPECT_CALL(platform, ResolveRemoteExecutable(_, _))
.WillRepeatedly(Return(std::make_pair(Status(), expected_executable)));
[lldb] Refactor Platform::ResolveExecutable Module resolution is probably the most complex piece of lldb [citation needed], with numerous levels of abstraction, each one implementing various retry and fallback strategies. It is also a very repetitive, with only small differences between "host", "remote-and-connected" and "remote-but-not-(yet)-connected" scenarios. The goal of this patch (first in series) is to reduce the number of abstractions, and deduplicate the code. One of the reasons for this complexity is the tension between the desire to offload the process of module resolution to the remote platform instance (that's how most other platform methods work), and the desire to keep it local to the outer platform class (its easier to subclass the outer class, and it generally makes more sense). This patch resolves that conflict in favour of doing everything in the outer class. The gdb-remote (our only remote platform) implementation of ResolveExecutable was not doing anything gdb-specific, and was rather similar to the other implementations of that method (any divergence is most likely the result of fixes not being applied everywhere rather than intentional). It does this by excising the remote platform out of the resolution codepath. The gdb-remote implementation of ResolveExecutable is moved to Platform::ResolveRemoteExecutable, and the (only) call site is redirected to that. On its own, this does not achieve (much), but it creates new opportunities for layer peeling and code sharing, since all of the code now lives closer together. Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 23:32:57 +08:00
platform.SetRemotePlatform(std::make_shared<TargetPlatformTester>(false));
ModuleSP resolved_sp;
lldb_private::Status status =
platform.ResolveExecutable(executable_spec, resolved_sp, nullptr);
ASSERT_TRUE(status.Success());
EXPECT_EQ(expected_executable.get(), resolved_sp.get());
}