StringMapEntry.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Testing/ADT/StringMapEntry.h ----------------------------------===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_TESTING_ADT_STRINGMAPENTRY_H_
  14. #define LLVM_TESTING_ADT_STRINGMAPENTRY_H_
  15. #include "llvm/ADT/StringMapEntry.h"
  16. #include "gmock/gmock.h"
  17. #include <ostream>
  18. #include <type_traits>
  19. namespace llvm {
  20. namespace detail {
  21. template <typename T, typename = std::void_t<>>
  22. struct CanOutputToOStream : std::false_type {};
  23. template <typename T>
  24. struct CanOutputToOStream<T, std::void_t<decltype(std::declval<std::ostream &>()
  25. << std::declval<T>())>>
  26. : std::true_type {};
  27. } // namespace detail
  28. /// Support for printing to std::ostream, for use with e.g. producing more
  29. /// useful error messages with Google Test.
  30. template <typename T>
  31. std::ostream &operator<<(std::ostream &OS, const StringMapEntry<T> &E) {
  32. OS << "{\"" << E.getKey().data() << "\": ";
  33. if constexpr (detail::CanOutputToOStream<decltype(E.getValue())>::value) {
  34. OS << E.getValue();
  35. } else {
  36. OS << "non-printable value";
  37. }
  38. return OS << "}";
  39. }
  40. namespace detail {
  41. template <typename StringMapEntryT>
  42. class StringMapEntryMatcherImpl
  43. : public testing::MatcherInterface<StringMapEntryT> {
  44. public:
  45. using ValueT = typename std::remove_reference_t<StringMapEntryT>::ValueType;
  46. template <typename KeyMatcherT, typename ValueMatcherT>
  47. StringMapEntryMatcherImpl(KeyMatcherT KeyMatcherArg,
  48. ValueMatcherT ValueMatcherArg)
  49. : KeyMatcher(
  50. testing::SafeMatcherCast<const std::string &>(KeyMatcherArg)),
  51. ValueMatcher(
  52. testing::SafeMatcherCast<const ValueT &>(ValueMatcherArg)) {}
  53. void DescribeTo(std::ostream *OS) const override {
  54. *OS << "has a string key that ";
  55. KeyMatcher.DescribeTo(OS);
  56. *OS << ", and has a value that ";
  57. ValueMatcher.DescribeTo(OS);
  58. }
  59. void DescribeNegationTo(std::ostream *OS) const override {
  60. *OS << "has a string key that ";
  61. KeyMatcher.DescribeNegationTo(OS);
  62. *OS << ", or has a value that ";
  63. ValueMatcher.DescribeNegationTo(OS);
  64. }
  65. bool
  66. MatchAndExplain(StringMapEntryT Entry,
  67. testing::MatchResultListener *ResultListener) const override {
  68. testing::StringMatchResultListener KeyListener;
  69. if (!KeyMatcher.MatchAndExplain(Entry.getKey().data(), &KeyListener)) {
  70. *ResultListener << ("which has a string key " +
  71. (KeyListener.str().empty() ? "that doesn't match"
  72. : KeyListener.str()));
  73. return false;
  74. }
  75. testing::StringMatchResultListener ValueListener;
  76. if (!ValueMatcher.MatchAndExplain(Entry.getValue(), &ValueListener)) {
  77. *ResultListener << ("which has a value " + (ValueListener.str().empty()
  78. ? "that doesn't match"
  79. : ValueListener.str()));
  80. return false;
  81. }
  82. *ResultListener << "which is a match";
  83. return true;
  84. }
  85. private:
  86. const testing::Matcher<const std::string &> KeyMatcher;
  87. const testing::Matcher<const ValueT &> ValueMatcher;
  88. };
  89. template <typename KeyMatcherT, typename ValueMatcherT>
  90. class StringMapEntryMatcher {
  91. public:
  92. StringMapEntryMatcher(KeyMatcherT KMArg, ValueMatcherT VMArg)
  93. : KM(std::move(KMArg)), VM(std::move(VMArg)) {}
  94. template <typename StringMapEntryT>
  95. operator testing::Matcher<StringMapEntryT>() const { // NOLINT
  96. return testing::Matcher<StringMapEntryT>(
  97. new StringMapEntryMatcherImpl<const StringMapEntryT &>(KM, VM));
  98. }
  99. private:
  100. const KeyMatcherT KM;
  101. const ValueMatcherT VM;
  102. };
  103. } // namespace detail
  104. /// Returns a gMock matcher that matches a `StringMapEntry` whose string key
  105. /// matches `KeyMatcher`, and whose value matches `ValueMatcher`.
  106. template <typename KeyMatcherT, typename ValueMatcherT>
  107. detail::StringMapEntryMatcher<KeyMatcherT, ValueMatcherT>
  108. IsStringMapEntry(KeyMatcherT KM, ValueMatcherT VM) {
  109. return detail::StringMapEntryMatcher<KeyMatcherT, ValueMatcherT>(
  110. std::move(KM), std::move(VM));
  111. }
  112. } // namespace llvm
  113. #endif
  114. #ifdef __GNUC__
  115. #pragma GCC diagnostic pop
  116. #endif