-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[lldb] Add a gtest matcher for lldb_private::Value #167427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This commit adds a new `ValueMatcher` class that can be used in gtest matching contexts to match against `lldb_private::Value` objects. We always match against the values `value_type` and `context_type`. For HostAddress values we will also match against the expected host buffer contents. For Scalar, FileAddress, and LoadAddress values we match against an expected Scalar value. The matcher is used to improve the quality of the tests in the `DwarfExpressionTest.cpp` file. Previously, the local `Evaluate` function would return an `Expected<Scalar>` value which makes it hard to verify that we actually get a Value of the expected type. Now we return an `Expected<Value>` so that we can match against the full value contents. The resulting change improves the quality of the existing checks and in some cases eliminates the need for special code to explicitly check value types.
|
@llvm/pr-subscribers-lldb Author: David Peixotto (dmpots) ChangesThis commit adds a new The matcher is used to improve the quality of the tests in the The resulting change improves the quality of the existing checks and in some cases eliminates the need for special code to explicitly check value types. Patch is 28.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/167427.diff 2 Files Affected:
diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 9d11060becfae..8c5568d9e4e65 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-
#include "lldb/Expression/DWARFExpression.h"
+#include "ValueMatcher.h"
#ifdef ARCH_AARCH64
#include "Plugins/ABI/AArch64/ABISysV_arm64.h"
#endif
@@ -135,40 +135,18 @@ class MockRegisterContext : public RegisterContext {
};
} // namespace
-static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr,
- lldb::ModuleSP module_sp = {},
- DWARFUnit *unit = nullptr,
- ExecutionContext *exe_ctx = nullptr,
- RegisterContext *reg_ctx = nullptr) {
+static llvm::Expected<Value> Evaluate(llvm::ArrayRef<uint8_t> expr,
+ lldb::ModuleSP module_sp = {},
+ DWARFUnit *unit = nullptr,
+ ExecutionContext *exe_ctx = nullptr,
+ RegisterContext *reg_ctx = nullptr) {
DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
/*addr_size*/ 4);
- llvm::Expected<Value> result = DWARFExpression::Evaluate(
- exe_ctx, reg_ctx, module_sp, extractor, unit, lldb::eRegisterKindLLDB,
- /*initial_value_ptr=*/nullptr,
- /*object_address_ptr=*/nullptr);
- if (!result)
- return result.takeError();
-
- switch (result->GetValueType()) {
- case Value::ValueType::Scalar:
- return result->GetScalar();
- case Value::ValueType::LoadAddress:
- return LLDB_INVALID_ADDRESS;
- case Value::ValueType::HostAddress: {
- // Convert small buffers to scalars to simplify the tests.
- DataBufferHeap &buf = result->GetBuffer();
- if (buf.GetByteSize() <= 8) {
- uint64_t val = 0;
- memcpy(&val, buf.GetBytes(), buf.GetByteSize());
- return Scalar(llvm::APInt(buf.GetByteSize() * 8, val, false));
- }
- }
- [[fallthrough]];
- default:
- break;
- }
- return llvm::createStringError("unsupported value type");
+ return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, extractor, unit,
+ lldb::eRegisterKindLLDB,
+ /*initial_value_ptr=*/nullptr,
+ /*object_address_ptr=*/nullptr);
}
class DWARFExpressionTester : public YAMLModuleTester {
@@ -177,18 +155,11 @@ class DWARFExpressionTester : public YAMLModuleTester {
: YAMLModuleTester(yaml_data, cu_index) {}
using YAMLModuleTester::YAMLModuleTester;
- llvm::Expected<Scalar> Eval(llvm::ArrayRef<uint8_t> expr) {
+ llvm::Expected<Value> Eval(llvm::ArrayRef<uint8_t> expr) {
return ::Evaluate(expr, m_module_sp, m_dwarf_unit);
}
};
-/// Unfortunately Scalar's operator==() is really picky.
-static Scalar GetScalar(unsigned bits, uint64_t value, bool sign) {
- Scalar scalar(value);
- scalar.TruncOrExtendTo(bits, sign);
- return scalar;
-}
-
/// This is needed for the tests that use a mock process.
class DWARFExpressionMockProcessTest : public ::testing::Test {
public:
@@ -255,48 +226,48 @@ class MockTarget : public Target {
TEST(DWARFExpression, DW_OP_pick) {
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 0}),
- llvm::HasValue(0));
+ ExpectScalar(0));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 1}),
- llvm::HasValue(1));
+ ExpectScalar(1));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit1, DW_OP_lit0, DW_OP_pick, 2}),
llvm::Failed());
}
TEST(DWARFExpression, DW_OP_const) {
// Extend to address size.
- EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x88}), llvm::HasValue(0x88));
+ EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x88}), ExpectScalar(0x88));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1s, 0x88}),
- llvm::HasValue(0xffffff88));
+ ExpectScalar(0xffffff88));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u, 0x47, 0x88}),
- llvm::HasValue(0x8847));
+ ExpectScalar(0x8847));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2s, 0x47, 0x88}),
- llvm::HasValue(0xffff8847));
+ ExpectScalar(0xffff8847));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4u, 0x44, 0x42, 0x47, 0x88}),
- llvm::HasValue(0x88474244));
+ ExpectScalar(0x88474244));
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const4s, 0x44, 0x42, 0x47, 0x88}),
- llvm::HasValue(0x88474244));
+ ExpectScalar(0x88474244));
// Truncate to address size.
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_const8u, 0x00, 0x11, 0x22, 0x33, 0x44, 0x42, 0x47, 0x88}),
- llvm::HasValue(0x33221100));
+ ExpectScalar(0x33221100));
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_const8s, 0x00, 0x11, 0x22, 0x33, 0x44, 0x42, 0x47, 0x88}),
- llvm::HasValue(0x33221100));
+ ExpectScalar(0x33221100));
// Don't truncate to address size for compatibility with clang (pr48087).
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_constu, 0x81, 0x82, 0x84, 0x88, 0x90, 0xa0, 0x40}),
- llvm::HasValue(0x01010101010101));
+ ExpectScalar(0x01010101010101));
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_consts, 0x81, 0x82, 0x84, 0x88, 0x90, 0xa0, 0x40}),
- llvm::HasValue(0xffff010101010101));
+ ExpectScalar(0xffff010101010101));
}
TEST(DWARFExpression, DW_OP_skip) {
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x42, DW_OP_skip, 0x02, 0x00,
DW_OP_const1u, 0xff}),
- llvm::HasValue(0x42));
+ ExpectScalar(0x42));
}
TEST(DWARFExpression, DW_OP_bra) {
@@ -309,7 +280,7 @@ TEST(DWARFExpression, DW_OP_bra) {
DW_OP_const1u, 0xff, // push 0xff
}),
// clang-format on
- llvm::HasValue(0x42));
+ ExpectScalar(0x42));
EXPECT_THAT_ERROR(Evaluate({DW_OP_bra, 0x01, 0x00}).takeError(),
llvm::Failed());
@@ -414,42 +385,42 @@ TEST(DWARFExpression, DW_OP_convert) {
EXPECT_THAT_EXPECTED(
t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, //
DW_OP_convert, offs_uint32_t, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(64, 0x44332211, not_signed)));
+ ExpectScalar(64, 0x44332211, not_signed));
// Zero-extend to 64 bits.
EXPECT_THAT_EXPECTED(
t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, //
DW_OP_convert, offs_uint64_t, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(64, 0x44332211, not_signed)));
+ ExpectScalar(64, 0x44332211, not_signed));
// Sign-extend to 64 bits.
EXPECT_THAT_EXPECTED(
t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, //
DW_OP_convert, offs_sint64_t, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(64, 0xffffffffffeeddcc, is_signed)));
+ ExpectScalar(64, 0xffffffffffeeddcc, is_signed));
// Sign-extend, then truncate.
EXPECT_THAT_EXPECTED(
t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, //
DW_OP_convert, offs_sint64_t, //
DW_OP_convert, offs_uint32_t, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed)));
+ ExpectScalar(32, 0xffeeddcc, not_signed));
// Truncate to default unspecified (pointer-sized) type.
EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, //
DW_OP_convert, offs_sint64_t, //
DW_OP_convert, 0x00, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed)));
+ ExpectScalar(32, 0xffeeddcc, not_signed));
// Truncate to 8 bits.
EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert,
offs_uchar, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(8, 'A', not_signed)));
+ ExpectScalar(8, 'A', not_signed));
// Also truncate to 8 bits.
EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert,
offs_schar, DW_OP_stack_value}),
- llvm::HasValue(GetScalar(8, 'A', is_signed)));
+ ExpectScalar(8, 'A', is_signed));
//
// Errors.
@@ -479,33 +450,21 @@ TEST(DWARFExpression, DW_OP_stack_value) {
TEST(DWARFExpression, DW_OP_piece) {
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const2u, 0x11, 0x22, DW_OP_piece, 2,
DW_OP_const2u, 0x33, 0x44, DW_OP_piece, 2}),
- llvm::HasValue(GetScalar(32, 0x44332211, true)));
+ ExpectHostAddress({0x11, 0x22, 0x33, 0x44}));
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_piece, 1, DW_OP_const1u, 0xff, DW_OP_piece, 1}),
// Note that the "00" should really be "undef", but we can't
// represent that yet.
- llvm::HasValue(GetScalar(16, 0xff00, true)));
-}
-
-TEST(DWARFExpression, DW_OP_piece_host_address) {
- static const uint8_t expr_data[] = {DW_OP_lit2, DW_OP_stack_value,
- DW_OP_piece, 40};
- llvm::ArrayRef<uint8_t> expr(expr_data, sizeof(expr_data));
- DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle, 4);
+ ExpectHostAddress({0x00, 0xff}));
// This tests if ap_int is extended to the right width.
// expect 40*8 = 320 bits size.
- llvm::Expected<Value> result =
- DWARFExpression::Evaluate(nullptr, nullptr, nullptr, extractor, nullptr,
- lldb::eRegisterKindDWARF, nullptr, nullptr);
- ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
- ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress);
- ASSERT_EQ(result->GetBuffer().GetByteSize(), 40ul);
- const uint8_t *data = result->GetBuffer().GetBytes();
- ASSERT_EQ(data[0], 2);
- for (int i = 1; i < 40; i++) {
- ASSERT_EQ(data[i], 0);
- }
+ std::vector<uint8_t> expected_host_buffer(40, 0);
+ expected_host_buffer[0] = 2;
+
+ EXPECT_THAT_EXPECTED(
+ Evaluate({{DW_OP_lit2, DW_OP_stack_value, DW_OP_piece, 40}}),
+ ExpectHostAddress(expected_host_buffer));
}
TEST(DWARFExpression, DW_OP_implicit_value) {
@@ -513,7 +472,7 @@ TEST(DWARFExpression, DW_OP_implicit_value) {
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_implicit_value, bytes, 0x11, 0x22, 0x33, 0x44}),
- llvm::HasValue(GetScalar(8 * bytes, 0x44332211, true)));
+ ExpectHostAddress({0x11, 0x22, 0x33, 0x44}));
}
TEST(DWARFExpression, DW_OP_unknown) {
@@ -548,20 +507,13 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) {
// Implicit location: *0x4.
EXPECT_THAT_EXPECTED(
Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx),
- llvm::HasValue(GetScalar(32, 0x07060504, false)));
+ ExpectScalar(32, 0x07060504, false));
// Memory location: *(*0x4).
- // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses.
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref}, {}, {}, &exe_ctx),
- llvm::HasValue(Scalar(LLDB_INVALID_ADDRESS)));
+ ExpectLoadAddress(0x07060504));
// Memory location: *0x4.
- // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses.
EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4}, {}, {}, &exe_ctx),
- llvm::HasValue(Scalar(4)));
- // Implicit location: *0x4.
- // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses.
- EXPECT_THAT_EXPECTED(
- Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx),
- llvm::HasValue(GetScalar(32, 0x07060504, false)));
+ ExpectScalar(Scalar(4)));
}
TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr) {
@@ -581,18 +533,9 @@ TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr) {
ExecutionContext exe_ctx(target_sp, false);
// DW_OP_addr takes a single operand of address size width:
- uint8_t expr[] = {DW_OP_addr, 0x40, 0x0, 0x0, 0x0};
- DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle,
- /*addr_size*/ 4);
-
- llvm::Expected<Value> result = DWARFExpression::Evaluate(
- &exe_ctx, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor,
- /*unit*/ nullptr, lldb::eRegisterKindLLDB,
- /*initial_value_ptr*/ nullptr,
- /*object_address_ptr*/ nullptr);
-
- ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
- ASSERT_EQ(result->GetValueType(), Value::ValueType::LoadAddress);
+ EXPECT_THAT_EXPECTED(
+ Evaluate({DW_OP_addr, 0x40, 0x0, 0x0, 0x0}, {}, {}, &exe_ctx),
+ ExpectLoadAddress(0x40));
}
TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) {
@@ -676,15 +619,11 @@ TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) {
DWARFExpression expr(extractor);
llvm::Expected<Value> result = evaluate(expr);
- ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
- ASSERT_EQ(result->GetValueType(), Value::ValueType::LoadAddress);
- ASSERT_EQ(result->GetScalar().UInt(), 0x5678u);
+ EXPECT_THAT_EXPECTED(result, ExpectLoadAddress(0x5678u));
ASSERT_TRUE(expr.Update_DW_OP_addr(dwarf_cu, 0xdeadbeef));
result = evaluate(expr);
- ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
- ASSERT_EQ(result->GetValueType(), Value::ValueType::LoadAddress);
- ASSERT_EQ(result->GetScalar().UInt(), 0xdeadbeefu);
+ EXPECT_THAT_EXPECTED(result, ExpectLoadAddress(0xdeadbeefu));
}
class CustomSymbolFileDWARF : public SymbolFileDWARF {
@@ -778,11 +717,12 @@ static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp,
RegisterContext *reg_ctx) {
// Test that expression extensions can be evaluated, for example
// DW_OP_WASM_location which is not currently handled by DWARFExpression:
- EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03
- 0x04, 0x00, 0x00, // index:u32
- 0x00, DW_OP_stack_value},
- module_sp, &dwarf_unit, nullptr, reg_ctx),
- llvm::HasValue(GetScalar(32, 42, false)));
+ EXPECT_THAT_EXPECTED(
+ Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03
+ 0x04, 0x00, 0x00, // index:u32
+ 0x00, DW_OP_stack_value},
+ module_sp, &dwarf_unit, nullptr, reg_ctx),
+ ExpectScalar(32, 42, false, Value::ContextType::RegisterInfo));
// Test that searches for opcodes work in the presence of extensions:
uint8_t expr[] = {DW_OP_WASM_location, 0x03, 0x04, 0x00, 0x00, 0x00,
@@ -1148,17 +1088,8 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) {
uint8_t expr[] = {DW_OP_addr, 0x40, 0x0, 0x0, 0x0, DW_OP_piece, 1,
DW_OP_addr, 0x50, 0x0, 0x0, 0x0, DW_OP_piece, 1};
- DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle,
- /*addr_size=*/4);
- llvm::Expected<Value> result = DWARFExpression::Evaluate(
- &exe_ctx, /*reg_ctx=*/nullptr, /*module_sp=*/{}, extractor,
- /*unit=*/nullptr, lldb::eRegisterKindLLDB,
- /*initial_value_ptr=*/nullptr,
- /*object_address_ptr=*/nullptr);
-
- ASSERT_THAT_EXPECTED(result, llvm::Succeeded());
- ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress);
- ASSERT_THAT(result->GetBuffer().GetData(), ElementsAre(0x11, 0x22));
+ EXPECT_THAT_EXPECTED(Evaluate(expr, {}, {}, &exe_ctx),
+ ExpectHostAddress({0x11, 0x22}));
}
/// A Process whose `ReadMemory` override queries a DenseMap.
@@ -1228,28 +1159,15 @@ TEST_F(DWARFExpressionMockProcessTestWithAArch, DW_op_deref_no_ptr_fixing) {
process_sp->GetThreadList().AddThread(thread);
auto evaluate_expr = [&](auto &expr_data) {
- DataExtractor extractor(expr_data, sizeof(expr_data),
- lldb::eByteOrderLittle,
- /*addr_size*/ 8);
- DWARFExpression expr(extractor);
-
ExecutionContext exe_ctx(process_sp);
- llvm::Expected<Value> result = DWARFExpression::Evaluate(
- &exe_ctx, reg_ctx_sp.get(), /*module_sp*/ nullptr, extractor,
- /*unit*/ nullptr, lldb::eRegisterKindLLDB,
- /*initial_value_ptr=*/nullptr,
- /*object_address_ptr=*/nullptr);
- return result;
+ return Evaluate(expr_data, {}, {}, &exe_ctx, reg_ctx_sp.get());
};
uint8_t expr_reg[] = {DW_OP_breg22, 0};
llvm::Expected<Value> result_reg = evaluate_expr(expr_reg);
- ASSERT_THAT_EXPECTED(result_reg, llvm::Succeeded());
- ASSERT_EQ(result_reg->GetValueType(), Value::ValueType::LoadAddress);
- ASSERT_EQ(result_reg->GetScalar().ULongLong(), addr);
+ EXPECT_THAT_EXPECTED(result_reg, ExpectLoadAddress(addr));
uint8_t expr_deref[] = {DW_OP_breg22, 0, DW_OP_deref};
llvm::Expected<Value> result_deref = evaluate_expr(expr_deref);
- ASSERT_THAT_EXPECTED(result_deref, llvm::Succeeded());
- ASSERT_EQ(result_deref->GetScalar().ULongLong(), expected_value);
+ EXPECT_THAT_EXPECTED(result_deref, ExpectLoadAddress(expected_value));
}
diff --git a/lldb/unittests/Expression/ValueMatcher.h b/lldb/unittests/Expression/ValueMatcher.h
new file mode 100644
index 0000000000000..38672bf054e0f
--- /dev/null
+++ b/lldb/unittests/Expression/ValueMatcher.h
@@ -0,0 +1,283 @@
+//===-- ValueMatcher.h ----------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file contains the definition of the ValueMatcher class which is a used
+/// to match lldb_private::Value in gtest assert/expect macros. It also contains
+/// several helper functions to create matchers for common Value types.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UNITTESTS_EXPRESSION_VALUEMATCHER_H
+#define LLDB_UNITTESTS_EXPRESSION_VALUEMATCHER_H
+
+#include "lldb/Core/Value.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Scalar.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <cstdint>
+#include <iomanip>
+#include <vector>
+
+namespace lldb_private {
+
+/// Helper function to format Value details to an ostream.
+///
+/// This is used for format the details coming from either a Value directly
+/// or the parts stored in the ValueMatcher object.
+inline void FormatValueDetails(std::ostream &os, Value::ValueType value_type,
+ Value::ContextType context_type,
+ const Scalar &scalar,
+ llvm::ArrayRef<uint8_t> buffer_data) {
+ os << "Value(";
+ os << "value_type=" << Value::GetValueTypeAsCString(value_type);
+ os << ", context_type=" << Value::GetContextTypeAsCString(context_type);
+
+ if (value_type == Value::ValueType::HostAddress) {
+ os << ", buffer=[";
+ for (size_t i = 0; i < std::min(buffer_data.size(), size_t(16)); ++i) {
+ if (i > 0)
+ os << " ";
+ os << std::hex << std::setw(2) << std::setfill('0')
+ << static_cast<int>(buffer_data[i]);
+ }
+ if (buffer_data.size() > 16) {
+ os << " ...";
+ }
+ os << std::dec << "] (" << buffer_data.size() << " bytes)";
+ } else {
+ std::string scalar_str;
+ llvm::raw_string_ostream scalar_os(scalar_str);
+ scalar_os << scalar;
+ os << ", value=" << scalar_os.str();
+ }
+ os << ")";
+}
+
+/// Custom printer for Value objects to make test failures more readable.
+inline void PrintTo(const Value &val, std::ostream *os) {
+ if (!os)
+ return...
[truncated]
|
This commit adds a new
ValueMatcherclass that can be used in gtest matching contexts to match againstlldb_private::Valueobjects. We always match against the valuesvalue_typeandcontext_type. For HostAddress values we will also match against the expected host buffer contents. For Scalar, FileAddress, and LoadAddress values we match against an expected Scalar value.The matcher is used to improve the quality of the tests in the
DwarfExpressionTest.cppfile. Previously, the localEvaluatefunction would return anExpected<Scalar>value which makes it hard to verify that we actually get a Value of the expected type without adding custom evaluation code. Now we return anExpected<Value>so that we can match against the full value contents.The resulting change improves the quality of the existing checks and in some cases eliminates the need for special code to explicitly check value types.