blob: 3ca7b15e1d3c87413e258542c342e583a7d1e5e5 [file] [log] [blame] [edit]
//===----------------------------------------------------------------------===//
//
// 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.
///
/// The ValueMatcher class was created using the gtest guide found here:
// https://google.github.io/googletest/gmock_cook_book.html#writing-new-monomorphic-matchers
//===----------------------------------------------------------------------===//
#ifndef LLDB_UNITTESTS_EXPRESSION_VALUEMATCHER_H
#define LLDB_UNITTESTS_EXPRESSION_VALUEMATCHER_H
#include "lldb/Core/Value.h"
#include "lldb/Utility/Scalar.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
#include <cstdint>
#include <vector>
namespace lldb_private {
/// Custom printer for Value objects to make test failures more readable.
void PrintTo(const Value &val, std::ostream *os);
/// Custom matcher for Value.
///
/// It matches against an expected value_type, and context_type.
/// For HostAddress value types it will match the expected contents of
/// the host buffer. For other value types it matches against an expected
/// scalar value.
class ValueMatcher {
public:
ValueMatcher(Value::ValueType value_type, const Scalar &expected_scalar,
Value::ContextType context_type)
: m_value_type(value_type), m_context_type(context_type),
m_expected_scalar(expected_scalar) {
assert(value_type == Value::ValueType::Scalar ||
value_type == Value::ValueType::FileAddress ||
value_type == Value::ValueType::LoadAddress);
}
ValueMatcher(Value::ValueType value_type,
const std::vector<uint8_t> &expected_bytes,
Value::ContextType context_type)
: m_value_type(value_type), m_context_type(context_type),
m_expected_bytes(expected_bytes) {
assert(value_type == Value::ValueType::HostAddress);
}
// Typedef to hook into the gtest matcher machinery.
using is_gtest_matcher = void;
bool MatchAndExplain(const Value &val, std::ostream *os) const;
void DescribeTo(std::ostream *os) const;
void DescribeNegationTo(std::ostream *os) const;
private:
Value::ValueType m_value_type = Value::ValueType::Invalid;
Value::ContextType m_context_type = Value::ContextType::Invalid;
Scalar m_expected_scalar;
std::vector<uint8_t> m_expected_bytes;
bool MatchAndExplainImpl(const Value &val, llvm::raw_ostream &os) const;
};
/// Matcher for Value with Scalar, FileAddress, or LoadAddress types.
/// Use with llvm::HasValue() to match Expected<Value>:
/// EXPECT_THAT_EXPECTED(result, llvm::HasValue(MatchScalarValue(...)));
testing::Matcher<Value> MatchScalarValue(Value::ValueType value_type,
const Scalar &expected_scalar,
Value::ContextType context_type);
/// Matcher for Value with HostAddress type.
/// Use with llvm::HasValue() to match Expected<Value>:
/// EXPECT_THAT_EXPECTED(result, llvm::HasValue(MatchHostValue(...)));
testing::Matcher<Value>
MatchHostValue(Value::ValueType value_type,
const std::vector<uint8_t> &expected_bytes,
Value::ContextType context_type);
/// Helper to match a Scalar value and context type.
/// Use with llvm::HasValue() to match Expected<Value>:
/// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsScalar(42)));
testing::Matcher<Value> IsScalar(const Scalar &expected_scalar,
Value::ContextType context_type);
/// Helper to match a LoadAddress value and context type.
/// Use with llvm::HasValue() to match Expected<Value>:
/// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsLoadAddress(0x1000)));
testing::Matcher<Value> IsLoadAddress(const Scalar &expected_address,
Value::ContextType context_type);
/// Helper to match a FileAddress value and context type.
/// Use with llvm::HasValue() to match Expected<Value>:
/// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsFileAddress(Scalar(0x1000))));
testing::Matcher<Value> IsFileAddress(const Scalar &expected_address,
Value::ContextType context_type);
/// Helper to match a HostAddress value and context type.
/// Use with llvm::HasValue() to match Expected<Value>:
/// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsHostValue({0x11, 0x22})));
testing::Matcher<Value> IsHostValue(const std::vector<uint8_t> &expected_bytes,
Value::ContextType context_type);
/// Helper to create a scalar because Scalar's operator==() is really picky.
Scalar GetScalar(unsigned bits, uint64_t value, bool sign);
/// Helper that combines IsScalar with llvm::HasValue for Expected<Value>.
/// Use it on an Expected<Value> like this:
/// EXPECT_THAT_EXPECTED(result, ExpectScalar(42));
llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>
ExpectScalar(const Scalar &expected_scalar,
Value::ContextType context_type = Value::ContextType::Invalid);
/// Helper that combines GetScalar with ExpectScalar to get a precise scalar.
/// Use it on an Expected<Value> like this:
/// EXPECT_THAT_EXPECTED(result, ExpectScalar(8, 42, true));
llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>
ExpectScalar(unsigned bits, uint64_t value, bool sign,
Value::ContextType context_type = Value::ContextType::Invalid);
/// Helper that combines IsLoadAddress with llvm::HasValue for Expected<Value>.
/// Use it on an Expected<Value> like this:
/// EXPECT_THAT_EXPECTED(result, ExpectLoadAddress(0x1000));
llvm::detail::ValueMatchesPoly<testing::Matcher<Value>> ExpectLoadAddress(
const Scalar &expected_address,
Value::ContextType context_type = Value::ContextType::Invalid);
/// Helper that combines IsFileAddress with llvm::HasValue for Expected<Value>.
/// Use it on an Expected<Value> like this:
/// EXPECT_THAT_EXPECTED(result, ExpectFileAddress(Scalar(0x2000)));
llvm::detail::ValueMatchesPoly<testing::Matcher<Value>> ExpectFileAddress(
const Scalar &expected_address,
Value::ContextType context_type = Value::ContextType::Invalid);
/// Helper that combines IsHostValue with llvm::HasValue for Expected<Value>.
/// Use it on an Expected<Value> like this:
/// EXPECT_THAT_EXPECTED(result, ExpectHostAddress({0x11, 0x22}));
llvm::detail::ValueMatchesPoly<testing::Matcher<Value>> ExpectHostAddress(
const std::vector<uint8_t> &expected_bytes,
Value::ContextType context_type = Value::ContextType::Invalid);
} // namespace lldb_private
#endif // LLDB_UNITTESTS_EXPRESSION_VALUEMATCHER_H