Skip to content

Commit 0c6fe37

Browse files
committed
[lldb][Test] Add C++ tests for DumpValueObjectOptions and enums
DumpValueObjectOptions can only be created and modified from C++. This means it's currently only testable from Python by calling some command that happens to use one, and even so, you can't pick which options get chosen. So we have decent coverage for the major options that way, but I want to add more niche options that will be harder to test from Python (register field options). So this change adds some "unit tests", though it's stretching the definition to the point it's more "test written in C++". So we can test future options in isolation. Since I want to add options specific to enums, that's all it covers. There is a test class that sets up the type system so it will be easy to test other types in future (e.g. structs, which register fields also use).
1 parent f06c1ce commit 0c6fe37

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

lldb/unittests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ add_subdirectory(tools)
7373
add_subdirectory(UnwindAssembly)
7474
add_subdirectory(Utility)
7575
add_subdirectory(Thread)
76+
add_subdirectory(ValueObject)
7677

7778
if(LLDB_CAN_USE_DEBUGSERVER AND LLDB_TOOL_DEBUGSERVER_BUILD AND NOT LLDB_USE_SYSTEM_DEBUGSERVER)
7879
add_subdirectory(debugserver)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_lldb_unittest(LLDBValueObjectTests
2+
DumpValueObjectOptionsTests.cpp
3+
4+
LINK_LIBS
5+
lldbPluginPlatformLinux
6+
lldbPluginScriptInterpreterNone
7+
8+
LINK_COMPONENTS
9+
Support
10+
)
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//===-- DumpValueObjectOptionsTests.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+
//===----------------------------------------------------------------------===//
8+
9+
#include "Plugins/Platform/Linux/PlatformLinux.h"
10+
#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
11+
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12+
#include "TestingSupport/SubsystemRAII.h"
13+
#include "TestingSupport/Symbol/ClangTestUtils.h"
14+
#include "lldb/Core/Debugger.h"
15+
#include "lldb/Core/ValueObject.h"
16+
#include "lldb/Core/ValueObjectConstResult.h"
17+
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
18+
19+
#include "gtest/gtest.h"
20+
21+
using namespace lldb;
22+
using namespace lldb_private;
23+
24+
struct MockProcess : Process {
25+
MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
26+
: Process(target_sp, listener_sp) {}
27+
28+
llvm::StringRef GetPluginName() override { return "mock process"; }
29+
30+
bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override {
31+
return false;
32+
};
33+
34+
Status DoDestroy() override { return {}; }
35+
36+
void RefreshStateAfterStop() override {}
37+
38+
bool DoUpdateThreadList(ThreadList &old_thread_list,
39+
ThreadList &new_thread_list) override {
40+
return false;
41+
};
42+
43+
size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
44+
Status &error) override {
45+
// No need to read memory in these tests.
46+
return size;
47+
}
48+
};
49+
50+
class ValueObjectMockProcessTest : public ::testing::Test {
51+
public:
52+
void SetUp() override {
53+
ArchSpec arch("i386-pc-linux");
54+
Platform::SetHostPlatform(
55+
platform_linux::PlatformLinux::CreateInstance(true, &arch));
56+
m_debugger_sp = Debugger::CreateInstance();
57+
ASSERT_TRUE(m_debugger_sp);
58+
m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,
59+
eLoadDependentsNo,
60+
m_platform_sp, m_target_sp);
61+
ASSERT_TRUE(m_target_sp);
62+
ASSERT_TRUE(m_target_sp->GetArchitecture().IsValid());
63+
ASSERT_TRUE(m_platform_sp);
64+
m_listener_sp = Listener::MakeListener("dummy");
65+
m_process_sp = std::make_shared<MockProcess>(m_target_sp, m_listener_sp);
66+
ASSERT_TRUE(m_process_sp);
67+
m_exe_ctx = ExecutionContext(m_process_sp);
68+
69+
m_holder = std::make_unique<clang_utils::TypeSystemClangHolder>("test");
70+
m_type_system = m_holder->GetAST();
71+
}
72+
73+
ExecutionContext m_exe_ctx;
74+
TypeSystemClang *m_type_system;
75+
76+
private:
77+
SubsystemRAII<FileSystem, HostInfo, platform_linux::PlatformLinux,
78+
ScriptInterpreterNone>
79+
m_subsystems;
80+
81+
std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;
82+
lldb::DebuggerSP m_debugger_sp;
83+
lldb::TargetSP m_target_sp;
84+
lldb::PlatformSP m_platform_sp;
85+
lldb::ListenerSP m_listener_sp;
86+
lldb::ProcessSP m_process_sp;
87+
};
88+
89+
TEST_F(ValueObjectMockProcessTest, Enum) {
90+
CompilerType uint_type = m_type_system->GetBuiltinTypeForEncodingAndBitSize(
91+
lldb::eEncodingUint, 32);
92+
CompilerType enum_type = m_type_system->CreateEnumerationType(
93+
"test_enum", m_type_system->GetTranslationUnitDecl(),
94+
OptionalClangModuleID(), Declaration(), uint_type, false);
95+
96+
m_type_system->StartTagDeclarationDefinition(enum_type);
97+
Declaration decl;
98+
// Each value sets one bit in the enum, to make this a "bitfield like enum".
99+
m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, "test_2",
100+
2, 32);
101+
m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, "test_4",
102+
4, 32);
103+
m_type_system->CompleteTagDeclarationDefinition(enum_type);
104+
105+
std::vector<std::tuple<uint32_t, DumpValueObjectOptions, const char *>> enums{
106+
{0, {}, "(test_enum) test_var =\n"},
107+
{1, {}, "(test_enum) test_var = 0x1\n"},
108+
{2, {}, "(test_enum) test_var = test_2\n"},
109+
{4, {}, "(test_enum) test_var = test_4\n"},
110+
{6, {}, "(test_enum) test_var = test_2 | test_4\n"},
111+
{7, {}, "(test_enum) test_var = test_2 | test_4 | 0x1\n"},
112+
{8, {}, "(test_enum) test_var = 0x8\n"},
113+
{1, DumpValueObjectOptions().SetHideRootName(true), "(test_enum) 0x1\n"},
114+
{1, DumpValueObjectOptions().SetHideRootType(true), "test_var = 0x1\n"},
115+
{1, DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
116+
"0x1\n"},
117+
{1, DumpValueObjectOptions().SetHideName(true), "(test_enum) 0x1\n"},
118+
{1, DumpValueObjectOptions().SetHideValue(true),
119+
"(test_enum) test_var =\n"},
120+
{1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
121+
"(test_enum) \n"},
122+
};
123+
124+
StreamString strm;
125+
ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
126+
ConstString var_name("test_var");
127+
ByteOrder endian = endian::InlHostByteOrder();
128+
for (auto [value, options, expected] : enums) {
129+
DataExtractor data_extractor{&value, sizeof(value), endian, 4};
130+
ValueObjectConstResult::Create(exe_scope, enum_type, var_name,
131+
data_extractor)
132+
->Dump(strm, options);
133+
ASSERT_STREQ(strm.GetString().str().c_str(), expected);
134+
strm.Clear();
135+
}
136+
}

0 commit comments

Comments
 (0)