[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
This commit is contained in:
parent
2562991c36
commit
f6b66cbc7d
|
@ -102,6 +102,8 @@ class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
|
||||||
public:
|
public:
|
||||||
using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
|
using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
|
||||||
|
|
||||||
|
using ValueType = ValueTy;
|
||||||
|
|
||||||
StringRef getKey() const {
|
StringRef getKey() const {
|
||||||
return StringRef(getKeyData(), this->getKeyLength());
|
return StringRef(getKeyData(), this->getKeyLength());
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define LLVM_TESTING_ADT_STRINGMAPENTRY_H_
|
#define LLVM_TESTING_ADT_STRINGMAPENTRY_H_
|
||||||
|
|
||||||
#include "llvm/ADT/StringMapEntry.h"
|
#include "llvm/ADT/StringMapEntry.h"
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
@ -39,6 +40,90 @@ std::ostream &operator<<(std::ostream &OS, const StringMapEntry<T> &E) {
|
||||||
return OS << "}";
|
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
|
} // namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,5 +3,6 @@ set(LLVM_LINK_COMPONENTS
|
||||||
)
|
)
|
||||||
|
|
||||||
add_llvm_unittest(TestingADTTests
|
add_llvm_unittest(TestingADTTests
|
||||||
|
StringMapEntryTest.cpp
|
||||||
StringMapTest.cpp
|
StringMapTest.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
|
|
@ -4188,7 +4188,10 @@ cc_library(
|
||||||
"include/llvm/Testing/ADT/*.h",
|
"include/llvm/Testing/ADT/*.h",
|
||||||
]),
|
]),
|
||||||
copts = llvm_copts,
|
copts = llvm_copts,
|
||||||
deps = [":Support"],
|
deps = [
|
||||||
|
":Support",
|
||||||
|
":gmock",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
|
|
Loading…
Reference in New Issue