[llvm] f6b66cb - [llvm][Testing/ADT] Implement `IsStringMapEntry` testing matcher for verifying the entries in a `StringMap`.
Wei Yi Tee via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 1 10:31:27 PDT 2022
Author: Wei Yi Tee
Date: 2022-09-01T17:30:41Z
New Revision: f6b66cbc7df17c12ea2e5819705caf4e9e88747e
URL: https://github.com/llvm/llvm-project/commit/f6b66cbc7df17c12ea2e5819705caf4e9e88747e
DIFF: https://github.com/llvm/llvm-project/commit/f6b66cbc7df17c12ea2e5819705caf4e9e88747e.diff
LOG: [llvm][Testing/ADT] Implement `IsStringMapEntry` testing matcher for verifying the entries in a `StringMap`.
Reviewed By: gribozavr2, ymandel, sgatev
Differential Revision: https://reviews.llvm.org/D132753
Added:
llvm/unittests/Testing/ADT/StringMapEntryTest.cpp
Modified:
llvm/include/llvm/ADT/StringMapEntry.h
llvm/include/llvm/Testing/ADT/StringMapEntry.h
llvm/unittests/Testing/ADT/CMakeLists.txt
utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/StringMapEntry.h b/llvm/include/llvm/ADT/StringMapEntry.h
index d580cdcedc1b1..664340683fc6b 100644
--- a/llvm/include/llvm/ADT/StringMapEntry.h
+++ b/llvm/include/llvm/ADT/StringMapEntry.h
@@ -102,6 +102,8 @@ class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
public:
using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
+ using ValueType = ValueTy;
+
StringRef getKey() const {
return StringRef(getKeyData(), this->getKeyLength());
}
diff --git a/llvm/include/llvm/Testing/ADT/StringMapEntry.h b/llvm/include/llvm/Testing/ADT/StringMapEntry.h
index 0f7582cebcdbf..7649c30078181 100644
--- a/llvm/include/llvm/Testing/ADT/StringMapEntry.h
+++ b/llvm/include/llvm/Testing/ADT/StringMapEntry.h
@@ -10,6 +10,7 @@
#define LLVM_TESTING_ADT_STRINGMAPENTRY_H_
#include "llvm/ADT/StringMapEntry.h"
+#include "gmock/gmock.h"
#include <ostream>
#include <type_traits>
@@ -39,6 +40,90 @@ std::ostream &operator<<(std::ostream &OS, const StringMapEntry<T> &E) {
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
diff --git a/llvm/unittests/Testing/ADT/CMakeLists.txt b/llvm/unittests/Testing/ADT/CMakeLists.txt
index f57b61b9f3476..47d9e3afb58b5 100644
--- a/llvm/unittests/Testing/ADT/CMakeLists.txt
+++ b/llvm/unittests/Testing/ADT/CMakeLists.txt
@@ -3,5 +3,6 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_unittest(TestingADTTests
+ StringMapEntryTest.cpp
StringMapTest.cpp
)
diff --git a/llvm/unittests/Testing/ADT/StringMapEntryTest.cpp b/llvm/unittests/Testing/ADT/StringMapEntryTest.cpp
new file mode 100644
index 0000000000000..4bc77410ea70c
--- /dev/null
+++ b/llvm/unittests/Testing/ADT/StringMapEntryTest.cpp
@@ -0,0 +1,88 @@
+//===- StringMapEntryTest.cpp ---------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Testing/ADT/StringMapEntry.h"
+#include "llvm/ADT/StringMap.h"
+
+#include "gtest/gtest.h"
+#include <sstream>
+
+namespace llvm {
+namespace {
+
+using testing::Gt;
+using testing::Matcher;
+using testing::StrCaseEq;
+using testing::StringMatchResultListener;
+using testing::UnorderedElementsAre;
+
+template <typename T> std::string Describe(const Matcher<T> &M, bool Match) {
+ std::stringstream SS;
+ if (Match) {
+ M.DescribeTo(&SS);
+ } else {
+ M.DescribeNegationTo(&SS);
+ }
+ return SS.str();
+}
+
+template <typename T, typename V>
+std::string ExplainMatch(const Matcher<T> &Matcher, const V &Value) {
+ StringMatchResultListener Listener;
+ Matcher.MatchAndExplain(Value, &Listener);
+ return Listener.str();
+}
+
+TEST(IsStringMapEntryTest, InnerMatchersAreExactValues) {
+ llvm::StringMap<int> Map = {{"A", 1}};
+ EXPECT_THAT(*Map.find("A"), IsStringMapEntry("A", 1));
+}
+
+TEST(IsStringMapEntryTest, InnerMatchersAreOtherMatchers) {
+ llvm::StringMap<int> Map = {{"A", 1}};
+ EXPECT_THAT(*Map.find("A"), IsStringMapEntry(StrCaseEq("a"), Gt(0)));
+}
+
+TEST(IsStringMapEntryTest, UseAsInnerMatcher) {
+ llvm::StringMap<int> Map = {{"A", 1}, {"B", 2}};
+ EXPECT_THAT(Map, UnorderedElementsAre(IsStringMapEntry("A", 1),
+ IsStringMapEntry("B", 2)));
+}
+
+TEST(IsStringMapEntryTest, DescribeSelf) {
+ Matcher<llvm::StringMapEntry<int>> M = IsStringMapEntry("A", 1);
+ EXPECT_EQ(
+ R"(has a string key that is equal to "A", and has a value that is equal to 1)",
+ Describe(M, true));
+ EXPECT_EQ(
+ R"(has a string key that isn't equal to "A", or has a value that isn't equal to 1)",
+ Describe(M, false));
+}
+
+TEST(IsStringMapEntryTest, ExplainSelfMatchSuccess) {
+ llvm::StringMap<int> Map = {{"A", 1}};
+ Matcher<llvm::StringMapEntry<int>> M = IsStringMapEntry("A", 1);
+ EXPECT_EQ(R"(which is a match)", ExplainMatch(M, *Map.find("A")));
+}
+
+TEST(IsStringMapEntryTest, ExplainSelfMatchFailsOnKey) {
+ llvm::StringMap<int> Map = {{"B", 1}};
+ Matcher<llvm::StringMapEntry<int>> M = IsStringMapEntry("A", 1);
+ EXPECT_EQ(R"(which has a string key that doesn't match)",
+ ExplainMatch(M, *Map.find("B")));
+}
+
+TEST(IsStringMapEntryTest, ExplainSelfMatchFailsOnValue) {
+ llvm::StringMap<int> Map = {{"A", 2}};
+ Matcher<llvm::StringMapEntry<int>> M = IsStringMapEntry("A", 1);
+ EXPECT_EQ(R"(which has a value that doesn't match)",
+ ExplainMatch(M, *Map.find("A")));
+}
+
+} // namespace
+} // namespace llvm
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index 9bcb08f5ef73a..9bc56e9acd075 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -4188,7 +4188,10 @@ cc_library(
"include/llvm/Testing/ADT/*.h",
]),
copts = llvm_copts,
- deps = [":Support"],
+ deps = [
+ ":Support",
+ ":gmock",
+ ],
)
cc_library(
More information about the llvm-commits
mailing list