| //===- llvm/Testing/ADT/StringMapEntry.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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_TESTING_ADT_STRINGMAPENTRY_H_ |
| #define LLVM_TESTING_ADT_STRINGMAPENTRY_H_ |
| |
| #include "llvm/ADT/StringMapEntry.h" |
| #include "gmock/gmock.h" |
| #include <ostream> |
| #include <type_traits> |
| |
| namespace llvm { |
| namespace detail { |
| |
| template <typename T, typename = std::void_t<>> |
| struct CanOutputToOStream : std::false_type {}; |
| |
| template <typename T> |
| struct CanOutputToOStream<T, std::void_t<decltype(std::declval<std::ostream &>() |
| << std::declval<T>())>> |
| : std::true_type {}; |
| |
| } // namespace detail |
| |
| /// Support for printing to std::ostream, for use with e.g. producing more |
| /// useful error messages with Google Test. |
| template <typename T> |
| std::ostream &operator<<(std::ostream &OS, const StringMapEntry<T> &E) { |
| OS << "{\"" << E.getKey().data() << "\": "; |
| if constexpr (detail::CanOutputToOStream<decltype(E.getValue())>::value) { |
| OS << E.getValue(); |
| } else { |
| OS << "non-printable value"; |
| } |
| return OS << "}"; |
| } |
| |
| namespace detail { |
| |
| template <typename StringMapEntryT> |
| class StringMapEntryMatcherImpl |
| : public testing::MatcherInterface<StringMapEntryT> { |
| public: |
| using ValueT = typename std::remove_reference_t<StringMapEntryT>::ValueType; |
| |
| template <typename KeyMatcherT, typename ValueMatcherT> |
| StringMapEntryMatcherImpl(KeyMatcherT KeyMatcherArg, |
| ValueMatcherT ValueMatcherArg) |
| : KeyMatcher( |
| testing::SafeMatcherCast<const std::string &>(KeyMatcherArg)), |
| ValueMatcher( |
| testing::SafeMatcherCast<const ValueT &>(ValueMatcherArg)) {} |
| |
| void DescribeTo(std::ostream *OS) const override { |
| *OS << "has a string key that "; |
| KeyMatcher.DescribeTo(OS); |
| *OS << ", and has a value that "; |
| ValueMatcher.DescribeTo(OS); |
| } |
| |
| void DescribeNegationTo(std::ostream *OS) const override { |
| *OS << "has a string key that "; |
| KeyMatcher.DescribeNegationTo(OS); |
| *OS << ", or has a value that "; |
| ValueMatcher.DescribeNegationTo(OS); |
| } |
| |
| bool |
| MatchAndExplain(StringMapEntryT Entry, |
| testing::MatchResultListener *ResultListener) const override { |
| testing::StringMatchResultListener KeyListener; |
| if (!KeyMatcher.MatchAndExplain(Entry.getKey().data(), &KeyListener)) { |
| *ResultListener << ("which has a string key " + |
| (KeyListener.str().empty() ? "that doesn't match" |
| : KeyListener.str())); |
| return false; |
| } |
| testing::StringMatchResultListener ValueListener; |
| if (!ValueMatcher.MatchAndExplain(Entry.getValue(), &ValueListener)) { |
| *ResultListener << ("which has a value " + (ValueListener.str().empty() |
| ? "that doesn't match" |
| : ValueListener.str())); |
| return false; |
| } |
| *ResultListener << "which is a match"; |
| return true; |
| } |
| |
| private: |
| const testing::Matcher<const std::string &> KeyMatcher; |
| const testing::Matcher<const ValueT &> ValueMatcher; |
| }; |
| |
| template <typename KeyMatcherT, typename ValueMatcherT> |
| class StringMapEntryMatcher { |
| public: |
| StringMapEntryMatcher(KeyMatcherT KMArg, ValueMatcherT VMArg) |
| : KM(std::move(KMArg)), VM(std::move(VMArg)) {} |
| |
| template <typename StringMapEntryT> |
| operator testing::Matcher<StringMapEntryT>() const { // NOLINT |
| return testing::Matcher<StringMapEntryT>( |
| new StringMapEntryMatcherImpl<const StringMapEntryT &>(KM, VM)); |
| } |
| |
| private: |
| const KeyMatcherT KM; |
| const ValueMatcherT VM; |
| }; |
| |
| } // namespace detail |
| |
| /// Returns a gMock matcher that matches a `StringMapEntry` whose string key |
| /// matches `KeyMatcher`, and whose value matches `ValueMatcher`. |
| template <typename KeyMatcherT, typename ValueMatcherT> |
| detail::StringMapEntryMatcher<KeyMatcherT, ValueMatcherT> |
| IsStringMapEntry(KeyMatcherT KM, ValueMatcherT VM) { |
| return detail::StringMapEntryMatcher<KeyMatcherT, ValueMatcherT>( |
| std::move(KM), std::move(VM)); |
| } |
| |
| } // namespace llvm |
| |
| #endif |