1//===-- NativeProcessTestUtils.cpp ------------------------------*- C++ -*-===//
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//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_UNITTESTS_TESTINGSUPPORT_HOST_NATIVEPROCESSTESTUTILS_H
10#define LLDB_UNITTESTS_TESTINGSUPPORT_HOST_NATIVEPROCESSTESTUTILS_H
11
12#include "lldb/Host/common/NativeProcessProtocol.h"
13#include "llvm/Testing/Support/Error.h"
14#include "gmock/gmock.h"
15
16using namespace lldb_private;
17using namespace lldb;
18using namespace testing;
19
20namespace lldb_private {
21
22class MockDelegate : public NativeProcessProtocol::NativeDelegate {
23public:
24 MOCK_METHOD1(InitializeDelegate, void(NativeProcessProtocol *Process));
25 MOCK_METHOD2(ProcessStateChanged,
26 void(NativeProcessProtocol *Process, StateType State));
27 MOCK_METHOD1(DidExec, void(NativeProcessProtocol *Process));
28 MOCK_METHOD2(NewSubprocessImpl,
29 void(NativeProcessProtocol *parent_process,
30 std::unique_ptr<NativeProcessProtocol> &child_process));
31 // This is a hack to avoid MOCK_METHOD2 incompatibility with std::unique_ptr
32 // passed as value.
33 void NewSubprocess(NativeProcessProtocol *parent_process,
34 std::unique_ptr<NativeProcessProtocol> child_process) {
35 NewSubprocessImpl(gmock_a0: parent_process, gmock_a1&: child_process);
36 }
37};
38
39// NB: This class doesn't use the override keyword to avoid
40// -Winconsistent-missing-override warnings from the compiler. The
41// inconsistency comes from the overriding definitions in the MOCK_*** macros.
42template <typename T> class MockProcess : public T {
43public:
44 MockProcess(NativeProcessProtocol::NativeDelegate &Delegate,
45 const ArchSpec &Arch, lldb::pid_t Pid = 1)
46 : T(Pid, -1, Delegate), Arch(Arch) {}
47
48 MOCK_METHOD1(Resume, Status(const ResumeActionList &ResumeActions));
49 MOCK_METHOD0(Halt, Status());
50 MOCK_METHOD0(Detach, Status());
51 MOCK_METHOD1(Signal, Status(int Signo));
52 MOCK_METHOD0(Kill, Status());
53 MOCK_METHOD0(GetSharedLibraryInfoAddress, addr_t());
54 MOCK_METHOD0(UpdateThreads, size_t());
55 MOCK_CONST_METHOD0(GetAuxvData,
56 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>());
57 MOCK_METHOD2(GetLoadedModuleFileSpec,
58 Status(const char *ModulePath, FileSpec &Spec));
59 MOCK_METHOD2(GetFileLoadAddress,
60 Status(const llvm::StringRef &FileName, addr_t &Addr));
61
62 const ArchSpec &GetArchitecture() const /*override*/ { return Arch; }
63 Status SetBreakpoint(lldb::addr_t Addr, uint32_t Size,
64 bool Hardware) /*override*/ {
65 if (Hardware)
66 return this->SetHardwareBreakpoint(Addr, Size);
67 else
68 return this->SetSoftwareBreakpoint(Addr, Size);
69 }
70
71 // Redirect base class Read/Write Memory methods to functions whose signatures
72 // are more mock-friendly.
73 Status ReadMemory(addr_t Addr, void *Buf, size_t Size,
74 size_t &BytesRead) /*override*/ {
75 auto ExpectedMemory = this->ReadMemory(Addr, Size);
76 if (!ExpectedMemory) {
77 BytesRead = 0;
78 return Status(ExpectedMemory.takeError());
79 }
80 BytesRead = ExpectedMemory->size();
81 assert(BytesRead <= Size);
82 std::memcpy(dest: Buf, src: ExpectedMemory->data(), n: BytesRead);
83 return Status();
84 }
85
86 Status WriteMemory(addr_t Addr, const void *Buf, size_t Size,
87 size_t &BytesWritten) /*override*/ {
88 auto ExpectedBytes = this->WriteMemory(
89 Addr, llvm::ArrayRef(static_cast<const uint8_t *>(Buf), Size));
90 if (!ExpectedBytes) {
91 BytesWritten = 0;
92 return Status(ExpectedBytes.takeError());
93 }
94 BytesWritten = *ExpectedBytes;
95 return Status();
96 }
97
98 MOCK_METHOD2(ReadMemory,
99 llvm::Expected<std::vector<uint8_t>>(addr_t Addr, size_t Size));
100 MOCK_METHOD2(WriteMemory,
101 llvm::Expected<size_t>(addr_t Addr,
102 llvm::ArrayRef<uint8_t> Data));
103
104 using T::GetSoftwareBreakpointTrapOpcode;
105 llvm::Expected<std::vector<uint8_t>> ReadMemoryWithoutTrap(addr_t Addr,
106 size_t Size) {
107 std::vector<uint8_t> Data(Size, 0);
108 size_t BytesRead;
109 Status ST =
110 T::ReadMemoryWithoutTrap(Addr, Data.data(), Data.size(), BytesRead);
111 if (ST.Fail())
112 return ST.ToError();
113 Data.resize(new_size: BytesRead);
114 return std::move(Data);
115 }
116
117private:
118 ArchSpec Arch;
119};
120
121class FakeMemory {
122public:
123 FakeMemory(llvm::ArrayRef<uint8_t> Data, addr_t start_addr = 0)
124 : Data(Data), m_start_addr(start_addr) {}
125
126 FakeMemory(const void *Data, size_t data_size, addr_t start_addr = 0)
127 : Data((const uint8_t *)Data, ((const uint8_t *)Data) + data_size),
128 m_start_addr(start_addr) {}
129
130 llvm::Expected<std::vector<uint8_t>> Read(addr_t Addr, size_t Size) {
131 Addr -= m_start_addr;
132 if (Addr >= Data.size())
133 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
134 Msg: "Address out of range.");
135 Size = std::min(a: Size, b: Data.size() - (size_t)Addr);
136 auto Begin = std::next(x: Data.begin(), n: Addr);
137 return std::vector<uint8_t>(Begin, std::next(x: Begin, n: Size));
138 }
139
140 llvm::Expected<size_t> Write(addr_t Addr, llvm::ArrayRef<uint8_t> Chunk) {
141 Addr -= m_start_addr;
142 if (Addr >= Data.size())
143 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
144 Msg: "Address out of range.");
145 size_t Size = std::min(a: Chunk.size(), b: Data.size() - (size_t)Addr);
146 std::copy_n(first: Chunk.begin(), n: Size, result: &Data[Addr]);
147 return Size;
148 }
149
150private:
151 std::vector<uint8_t> Data;
152 addr_t m_start_addr;
153};
154} // namespace lldb_private
155
156#endif
157

source code of lldb/unittests/TestingSupport/Host/NativeProcessTestUtils.h