//===----------------------------------------------------------------------===// // // 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 #include 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 &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 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: /// EXPECT_THAT_EXPECTED(result, llvm::HasValue(MatchScalarValue(...))); testing::Matcher 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: /// EXPECT_THAT_EXPECTED(result, llvm::HasValue(MatchHostValue(...))); testing::Matcher MatchHostValue(Value::ValueType value_type, const std::vector &expected_bytes, Value::ContextType context_type); /// Helper to match a Scalar value and context type. /// Use with llvm::HasValue() to match Expected: /// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsScalar(42))); testing::Matcher 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: /// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsLoadAddress(0x1000))); testing::Matcher 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: /// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsFileAddress(Scalar(0x1000)))); testing::Matcher 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: /// EXPECT_THAT_EXPECTED(result, llvm::HasValue(IsHostValue({0x11, 0x22}))); testing::Matcher IsHostValue(const std::vector &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. /// Use it on an Expected like this: /// EXPECT_THAT_EXPECTED(result, ExpectScalar(42)); llvm::detail::ValueMatchesPoly> 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 like this: /// EXPECT_THAT_EXPECTED(result, ExpectScalar(8, 42, true)); llvm::detail::ValueMatchesPoly> ExpectScalar(unsigned bits, uint64_t value, bool sign, Value::ContextType context_type = Value::ContextType::Invalid); /// Helper that combines IsLoadAddress with llvm::HasValue for Expected. /// Use it on an Expected like this: /// EXPECT_THAT_EXPECTED(result, ExpectLoadAddress(0x1000)); llvm::detail::ValueMatchesPoly> ExpectLoadAddress( const Scalar &expected_address, Value::ContextType context_type = Value::ContextType::Invalid); /// Helper that combines IsFileAddress with llvm::HasValue for Expected. /// Use it on an Expected like this: /// EXPECT_THAT_EXPECTED(result, ExpectFileAddress(Scalar(0x2000))); llvm::detail::ValueMatchesPoly> ExpectFileAddress( const Scalar &expected_address, Value::ContextType context_type = Value::ContextType::Invalid); /// Helper that combines IsHostValue with llvm::HasValue for Expected. /// Use it on an Expected like this: /// EXPECT_THAT_EXPECTED(result, ExpectHostAddress({0x11, 0x22})); llvm::detail::ValueMatchesPoly> ExpectHostAddress( const std::vector &expected_bytes, Value::ContextType context_type = Value::ContextType::Invalid); } // namespace lldb_private #endif // LLDB_UNITTESTS_EXPRESSION_VALUEMATCHER_H