mirror of
https://github.com/google/googletest.git
synced 2025-03-10 09:16:48 +00:00
Makes WhenSorted() support associative containers (by billydonahue@google.com).
This commit is contained in:
parent
1f122a06e6
commit
a9a59e06dd
@ -2189,7 +2189,10 @@ class WhenSortedByMatcher {
|
|||||||
GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
|
GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
|
||||||
typedef typename LhsView::type LhsStlContainer;
|
typedef typename LhsView::type LhsStlContainer;
|
||||||
typedef typename LhsView::const_reference LhsStlContainerReference;
|
typedef typename LhsView::const_reference LhsStlContainerReference;
|
||||||
typedef typename LhsStlContainer::value_type LhsValue;
|
// Transforms std::pair<const Key, Value> into std::pair<Key, Value>
|
||||||
|
// so that we can match associative containers.
|
||||||
|
typedef typename RemoveConstFromKey<
|
||||||
|
typename LhsStlContainer::value_type>::type LhsValue;
|
||||||
|
|
||||||
Impl(const Comparator& comparator, const ContainerMatcher& matcher)
|
Impl(const Comparator& comparator, const ContainerMatcher& matcher)
|
||||||
: comparator_(comparator), matcher_(matcher) {}
|
: comparator_(comparator), matcher_(matcher) {}
|
||||||
|
@ -473,6 +473,20 @@ class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
|
|||||||
// StlContainer with a reference type.
|
// StlContainer with a reference type.
|
||||||
template <typename T> class StlContainerView<T&>;
|
template <typename T> class StlContainerView<T&>;
|
||||||
|
|
||||||
|
// A type transform to remove constness from the first part of a pair.
|
||||||
|
// Pairs like that are used as the value_type of associative containers,
|
||||||
|
// and this transform produces a similar but assignable pair.
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveConstFromKey {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Partially specialized to remove constness from std::pair<const K, V>.
|
||||||
|
template <typename K, typename V>
|
||||||
|
struct RemoveConstFromKey<std::pair<const K, V> > {
|
||||||
|
typedef std::pair<K, V> type;
|
||||||
|
};
|
||||||
|
|
||||||
// Mapping from booleans to types. Similar to boost::bool_<kValue> and
|
// Mapping from booleans to types. Similar to boost::bool_<kValue> and
|
||||||
// std::integral_constant<bool, kValue>.
|
// std::integral_constant<bool, kValue>.
|
||||||
template <bool kValue>
|
template <bool kValue>
|
||||||
|
@ -37,8 +37,10 @@
|
|||||||
#include "gmock/gmock-more-matchers.h"
|
#include "gmock/gmock-more-matchers.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <deque>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -4012,6 +4014,165 @@ TEST(WhenSortedTest, WorksForNonEmptyContainer) {
|
|||||||
EXPECT_THAT(words, Not(WhenSorted(ElementsAre("3", "1", "2", "2"))));
|
EXPECT_THAT(words, Not(WhenSorted(ElementsAre("3", "1", "2", "2"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForMapTypes) {
|
||||||
|
map<string, int> word_counts;
|
||||||
|
word_counts["and"] = 1;
|
||||||
|
word_counts["the"] = 1;
|
||||||
|
word_counts["buffalo"] = 2;
|
||||||
|
EXPECT_THAT(word_counts, WhenSorted(ElementsAre(
|
||||||
|
Pair("and", 1), Pair("buffalo", 2), Pair("the", 1))));
|
||||||
|
EXPECT_THAT(word_counts, Not(WhenSorted(ElementsAre(
|
||||||
|
Pair("and", 1), Pair("the", 1), Pair("buffalo", 2)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForMultiMapTypes) {
|
||||||
|
multimap<int, int> ifib;
|
||||||
|
ifib.insert(make_pair(8, 6));
|
||||||
|
ifib.insert(make_pair(2, 3));
|
||||||
|
ifib.insert(make_pair(1, 1));
|
||||||
|
ifib.insert(make_pair(3, 4));
|
||||||
|
ifib.insert(make_pair(1, 2));
|
||||||
|
ifib.insert(make_pair(5, 5));
|
||||||
|
EXPECT_THAT(ifib, WhenSorted(ElementsAre(Pair(1, 1),
|
||||||
|
Pair(1, 2),
|
||||||
|
Pair(2, 3),
|
||||||
|
Pair(3, 4),
|
||||||
|
Pair(5, 5),
|
||||||
|
Pair(8, 6))));
|
||||||
|
EXPECT_THAT(ifib, Not(WhenSorted(ElementsAre(Pair(8, 6),
|
||||||
|
Pair(2, 3),
|
||||||
|
Pair(1, 1),
|
||||||
|
Pair(3, 4),
|
||||||
|
Pair(1, 2),
|
||||||
|
Pair(5, 5)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForPolymorphicMatcher) {
|
||||||
|
std::deque<int> d;
|
||||||
|
d.push_back(2);
|
||||||
|
d.push_back(1);
|
||||||
|
EXPECT_THAT(d, WhenSorted(ElementsAre(1, 2)));
|
||||||
|
EXPECT_THAT(d, Not(WhenSorted(ElementsAre(2, 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForVectorConstRefMatcher) {
|
||||||
|
std::deque<int> d;
|
||||||
|
d.push_back(2);
|
||||||
|
d.push_back(1);
|
||||||
|
Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2);
|
||||||
|
EXPECT_THAT(d, WhenSorted(vector_match));
|
||||||
|
Matcher<const std::vector<int>&> not_vector_match = ElementsAre(2, 1);
|
||||||
|
EXPECT_THAT(d, Not(WhenSorted(not_vector_match)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deliberately bare pseudo-container.
|
||||||
|
// Offers only begin() and end() accessors, yielding InputIterator.
|
||||||
|
template <typename T>
|
||||||
|
class Streamlike {
|
||||||
|
private:
|
||||||
|
class ConstIter;
|
||||||
|
public:
|
||||||
|
typedef ConstIter const_iterator;
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
template <typename InIter>
|
||||||
|
Streamlike(InIter first, InIter last) : remainder_(first, last) {}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return const_iterator(this, remainder_.begin());
|
||||||
|
}
|
||||||
|
const_iterator end() const {
|
||||||
|
return const_iterator(this, remainder_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ConstIter : public std::iterator<std::input_iterator_tag,
|
||||||
|
value_type,
|
||||||
|
ptrdiff_t,
|
||||||
|
const value_type&,
|
||||||
|
const value_type*> {
|
||||||
|
public:
|
||||||
|
ConstIter(const Streamlike* s,
|
||||||
|
typename std::list<value_type>::iterator pos)
|
||||||
|
: s_(s), pos_(pos) {}
|
||||||
|
|
||||||
|
const value_type& operator*() const { return *pos_; }
|
||||||
|
const value_type* operator->() const { return &*pos_; }
|
||||||
|
ConstIter& operator++() {
|
||||||
|
s_->remainder_.erase(pos_++);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// *iter++ is required to work (see std::istreambuf_iterator).
|
||||||
|
// (void)iter++ is also required to work.
|
||||||
|
class PostIncrProxy {
|
||||||
|
public:
|
||||||
|
explicit PostIncrProxy(const value_type& value) : value_(value) {}
|
||||||
|
value_type operator*() const { return value_; }
|
||||||
|
private:
|
||||||
|
value_type value_;
|
||||||
|
};
|
||||||
|
PostIncrProxy operator++(int) {
|
||||||
|
PostIncrProxy proxy(**this);
|
||||||
|
++(*this);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const ConstIter& a, const ConstIter& b) {
|
||||||
|
return a.s_ == b.s_ && a.pos_ == b.pos_;
|
||||||
|
}
|
||||||
|
friend bool operator!=(const ConstIter& a, const ConstIter& b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Streamlike* s_;
|
||||||
|
typename std::list<value_type>::iterator pos_;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const Streamlike& s) {
|
||||||
|
os << "[";
|
||||||
|
typedef typename std::list<value_type>::const_iterator Iter;
|
||||||
|
const char* sep = "";
|
||||||
|
for (Iter it = s.remainder_.begin(); it != s.remainder_.end(); ++it) {
|
||||||
|
os << sep << *it;
|
||||||
|
sep = ",";
|
||||||
|
}
|
||||||
|
os << "]";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable std::list<value_type> remainder_; // modified by iteration
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(StreamlikeTest, Iteration) {
|
||||||
|
const int a[5] = { 2, 1, 4, 5, 3 };
|
||||||
|
Streamlike<int> s(a, a + 5);
|
||||||
|
Streamlike<int>::const_iterator it = s.begin();
|
||||||
|
const int* ip = a;
|
||||||
|
while (it != s.end()) {
|
||||||
|
SCOPED_TRACE(ip - a);
|
||||||
|
EXPECT_EQ(*ip++, *it++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForStreamlike) {
|
||||||
|
// Streamlike 'container' provides only minimal iterator support.
|
||||||
|
// Its iterators are tagged with input_iterator_tag.
|
||||||
|
const int a[5] = { 2, 1, 4, 5, 3 };
|
||||||
|
Streamlike<int> s(a, a + 5);
|
||||||
|
EXPECT_THAT(s, WhenSorted(ElementsAre(1, 2, 3, 4, 5)));
|
||||||
|
EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WhenSortedTest, WorksForVectorConstRefMatcherOnStreamlike) {
|
||||||
|
const int a[5] = { 2, 1, 4, 5, 3 };
|
||||||
|
Streamlike<int> s(a, a + 5);
|
||||||
|
Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2, 3, 4, 5);
|
||||||
|
EXPECT_THAT(s, WhenSorted(vector_match));
|
||||||
|
EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3))));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests IsReadableTypeName().
|
// Tests IsReadableTypeName().
|
||||||
|
|
||||||
TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
|
TEST(IsReadableTypeNameTest, ReturnsTrueForShortNames) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user