Adds Each(m) (by Wojtek Moczydlowski); removes scripts/test/Makefile (by Zhanyong Wan); pulls in gtest r424.

This commit is contained in:
zhanyong.wan 2010-04-22 23:37:47 +00:00
parent 090c4830dd
commit 33605ba454
4 changed files with 222 additions and 91 deletions

View File

@ -137,9 +137,7 @@ EXTRA_DIST += include/gmock/gmock-generated-actions.h.pump \
include/gmock/internal/gmock-generated-internal-utils.h.pump
# Script for fusing Google Mock and Google Test source files.
EXTRA_DIST += \
scripts/fuse_gmock_files.py \
scripts/test/Makefile
EXTRA_DIST += scripts/fuse_gmock_files.py
# The Google Mock Generator tool from the cppclean project.
EXTRA_DIST += \

View File

@ -1947,9 +1947,9 @@ class ContainerEqMatcher {
GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
};
// Implements Contains(element_matcher) for the given argument type Container.
// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
template <typename Container>
class ContainsMatcherImpl : public MatcherInterface<Container> {
class QuantifierMatcherImpl : public MatcherInterface<Container> {
public:
typedef GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Container)) RawContainer;
typedef StlContainerView<RawContainer> View;
@ -1958,44 +1958,97 @@ class ContainsMatcherImpl : public MatcherInterface<Container> {
typedef typename StlContainer::value_type Element;
template <typename InnerMatcher>
explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
: inner_matcher_(
testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
*os << "contains at least one element that ";
inner_matcher_.DescribeTo(os);
}
// Describes what the negation of this matcher does.
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't contain any element that ";
inner_matcher_.DescribeTo(os);
}
virtual bool MatchAndExplain(Container container,
MatchResultListener* listener) const {
// Checks whether:
// * All elements in the container match, if all_elements_should_match.
// * Any element in the container matches, if !all_elements_should_match.
bool MatchAndExplainImpl(bool all_elements_should_match,
Container container,
MatchResultListener* listener) const {
StlContainerReference stl_container = View::ConstReference(container);
size_t i = 0;
for (typename StlContainer::const_iterator it = stl_container.begin();
it != stl_container.end(); ++it, ++i) {
StringMatchResultListener inner_listener;
if (inner_matcher_.MatchAndExplain(*it, &inner_listener)) {
*listener << "whose element #" << i << " matches";
const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
if (matches != all_elements_should_match) {
*listener << "whose element #" << i
<< (matches ? " matches" : " doesn't match");
PrintIfNotEmpty(inner_listener.str(), listener->stream());
return true;
return !all_elements_should_match;
}
}
return false;
return all_elements_should_match;
}
protected:
const Matcher<const Element&> inner_matcher_;
GTEST_DISALLOW_ASSIGN_(QuantifierMatcherImpl);
};
// Implements Contains(element_matcher) for the given argument type Container.
// Symmetric to EachMatcherImpl.
template <typename Container>
class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
public:
template <typename InnerMatcher>
explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
: QuantifierMatcherImpl<Container>(inner_matcher) {}
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
*os << "contains at least one element that ";
this->inner_matcher_.DescribeTo(os);
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't contain any element that ";
this->inner_matcher_.DescribeTo(os);
}
virtual bool MatchAndExplain(Container container,
MatchResultListener* listener) const {
return this->MatchAndExplainImpl(false, container, listener);
}
private:
const Matcher<const Element&> inner_matcher_;
GTEST_DISALLOW_ASSIGN_(ContainsMatcherImpl);
};
// Implements Each(element_matcher) for the given argument type Container.
// Symmetric to ContainsMatcherImpl.
template <typename Container>
class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
public:
template <typename InnerMatcher>
explicit EachMatcherImpl(InnerMatcher inner_matcher)
: QuantifierMatcherImpl<Container>(inner_matcher) {}
// Describes what this matcher does.
virtual void DescribeTo(::std::ostream* os) const {
*os << "only contains elements that ";
this->inner_matcher_.DescribeTo(os);
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "contains some element that ";
this->inner_matcher_.DescribeNegationTo(os);
}
virtual bool MatchAndExplain(Container container,
MatchResultListener* listener) const {
return this->MatchAndExplainImpl(true, container, listener);
}
private:
GTEST_DISALLOW_ASSIGN_(EachMatcherImpl);
};
// Implements polymorphic Contains(element_matcher).
template <typename M>
class ContainsMatcher {
@ -2013,6 +2066,23 @@ class ContainsMatcher {
GTEST_DISALLOW_ASSIGN_(ContainsMatcher);
};
// Implements polymorphic Each(element_matcher).
template <typename M>
class EachMatcher {
public:
explicit EachMatcher(M m) : inner_matcher_(m) {}
template <typename Container>
operator Matcher<Container>() const {
return MakeMatcher(new EachMatcherImpl<Container>(inner_matcher_));
}
private:
const M inner_matcher_;
GTEST_DISALLOW_ASSIGN_(EachMatcher);
};
// Implements Key(inner_matcher) for the given argument pair type.
// Key(inner_matcher) matches an std::pair whose 'first' field matches
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
@ -2855,6 +2925,38 @@ inline internal::ContainsMatcher<M> Contains(M matcher) {
return internal::ContainsMatcher<M>(matcher);
}
// Matches an STL-style container or a native array that contains only
// elements matching the given value or matcher.
//
// Each(m) is semantically equivalent to Not(Contains(Not(m))). Only
// the messages are different.
//
// Examples:
// ::std::set<int> page_ids;
// // Each(m) matches an empty container, regardless of what m is.
// EXPECT_THAT(page_ids, Each(Eq(1)));
// EXPECT_THAT(page_ids, Each(Eq(77)));
//
// page_ids.insert(3);
// EXPECT_THAT(page_ids, Each(Gt(0)));
// EXPECT_THAT(page_ids, Not(Each(Gt(4))));
// page_ids.insert(1);
// EXPECT_THAT(page_ids, Not(Each(Lt(2))));
//
// ::std::map<int, size_t> page_lengths;
// page_lengths[1] = 100;
// page_lengths[2] = 200;
// page_lengths[3] = 300;
// EXPECT_THAT(page_lengths, Not(Each(Pair(1, 100))));
// EXPECT_THAT(page_lengths, Each(Key(Le(3))));
//
// const char* user_ids[] = { "joe", "mike", "tom" };
// EXPECT_THAT(user_ids, Not(Each(Eq(::std::string("tom")))));
template <typename M>
inline internal::EachMatcher<M> Each(M matcher) {
return internal::EachMatcher<M>(matcher);
}
// Key(inner_matcher) matches an std::pair whose 'first' field matches
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
// std::map that contains at least one element whose key is >= 5.

View File

@ -1,57 +0,0 @@
# A Makefile for fusing Google Mock and building a sample test against it.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make check - makes everything and runs the built sample test.
# make clean - removes all files generated by make.
# Points to the root of fused Google Mock, relative to where this file is.
FUSED_GMOCK_DIR = output
# Paths to the fused gmock files.
FUSED_GTEST_H = $(FUSED_GMOCK_DIR)/gtest/gtest.h
FUSED_GMOCK_H = $(FUSED_GMOCK_DIR)/gmock/gmock.h
FUSED_GMOCK_GTEST_ALL_CC = $(FUSED_GMOCK_DIR)/gmock-gtest-all.cc
# Where to find the gmock_test.cc.
GMOCK_TEST_CC = ../../test/gmock_test.cc
# Where to find gmock_main.cc.
GMOCK_MAIN_CC = ../../src/gmock_main.cc
# Flags passed to the preprocessor.
CPPFLAGS += -I$(FUSED_GMOCK_DIR)
# Flags passed to the C++ compiler.
CXXFLAGS += -g
all : gmock_test
check : all
./gmock_test
clean :
rm -rf $(FUSED_GMOCK_DIR) gmock_test *.o
$(FUSED_GTEST_H) :
../fuse_gmock_files.py $(FUSED_GMOCK_DIR)
$(FUSED_GMOCK_H) :
../fuse_gmock_files.py $(FUSED_GMOCK_DIR)
$(FUSED_GMOCK_GTEST_ALL_CC) :
../fuse_gmock_files.py $(FUSED_GMOCK_DIR)
gmock-gtest-all.o : $(FUSED_GTEST_H) $(FUSED_GMOCK_H) $(FUSED_GMOCK_GTEST_ALL_CC)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FUSED_GMOCK_GTEST_ALL_CC)
gmock_main.o : $(FUSED_GTEST_H) $(FUSED_GMOCK_H) $(GMOCK_MAIN_CC)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GMOCK_MAIN_CC)
gmock_test.o : $(FUSED_GTEST_H) $(FUSED_GMOCK_H) $(GMOCK_TEST_CC)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GMOCK_TEST_CC)
gmock_test : gmock_test.o gmock-gtest-all.o gmock_main.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@

View File

@ -65,8 +65,10 @@ using std::make_pair;
using std::map;
using std::multimap;
using std::pair;
using std::set;
using std::stringstream;
using std::tr1::make_tuple;
using std::vector;
using testing::A;
using testing::AllArgs;
using testing::AllOf;
@ -363,20 +365,20 @@ TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
// Tests that MakePolymorphicMatcher() can construct a polymorphic
// matcher from its implementation using the old API.
const int bar = 1;
const int g_bar = 1;
class ReferencesBarOrIsZeroImpl {
public:
template <typename T>
bool MatchAndExplain(const T& x,
MatchResultListener* /* listener */) const {
const void* p = &x;
return p == &bar || x == 0;
return p == &g_bar || x == 0;
}
void DescribeTo(::std::ostream* os) const { *os << "bar or zero"; }
void DescribeTo(::std::ostream* os) const { *os << "g_bar or zero"; }
void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't reference bar and is not zero";
*os << "doesn't reference g_bar and is not zero";
}
};
@ -391,15 +393,15 @@ TEST(MakePolymorphicMatcherTest, ConstructsMatcherUsingOldAPI) {
Matcher<const int&> m1 = ReferencesBarOrIsZero();
EXPECT_TRUE(m1.Matches(0));
// Verifies that the identity of a by-reference argument is preserved.
EXPECT_TRUE(m1.Matches(bar));
EXPECT_TRUE(m1.Matches(g_bar));
EXPECT_FALSE(m1.Matches(1));
EXPECT_EQ("bar or zero", Describe(m1));
EXPECT_EQ("g_bar or zero", Describe(m1));
// Using a polymorphic matcher to match a value type.
Matcher<double> m2 = ReferencesBarOrIsZero();
EXPECT_TRUE(m2.Matches(0.0));
EXPECT_FALSE(m2.Matches(0.1));
EXPECT_EQ("bar or zero", Describe(m2));
EXPECT_EQ("g_bar or zero", Describe(m2));
}
// Tests implementing a polymorphic matcher using MatchAndExplain().
@ -3984,5 +3986,91 @@ TEST(MatcherTupleTest, ExplainsMatchFailure) {
// explanation.
}
// Tests Each().
TEST(EachTest, ExplainsMatchResultCorrectly) {
set<int> a; // empty
Matcher<set<int> > m = Each(2);
EXPECT_EQ("", Explain(m, a));
Matcher<const int(&)[1]> n = Each(1);
const int b[1] = { 1 };
EXPECT_EQ("", Explain(n, b));
n = Each(3);
EXPECT_EQ("whose element #0 doesn't match", Explain(n, b));
a.insert(1);
a.insert(2);
a.insert(3);
m = Each(GreaterThan(0));
EXPECT_EQ("", Explain(m, a));
m = Each(GreaterThan(10));
EXPECT_EQ("whose element #0 doesn't match, which is 9 less than 10",
Explain(m, a));
}
TEST(EachTest, DescribesItselfCorrectly) {
Matcher<vector<int> > m = Each(1);
EXPECT_EQ("only contains elements that is equal to 1", Describe(m));
Matcher<vector<int> > m2 = Not(m);
EXPECT_EQ("contains some element that isn't equal to 1", Describe(m2));
}
TEST(EachTest, MatchesVectorWhenAllElementsMatch) {
vector<int> some_vector;
EXPECT_THAT(some_vector, Each(1));
some_vector.push_back(3);
EXPECT_THAT(some_vector, Not(Each(1)));
EXPECT_THAT(some_vector, Each(3));
some_vector.push_back(1);
some_vector.push_back(2);
EXPECT_THAT(some_vector, Not(Each(3)));
EXPECT_THAT(some_vector, Each(Lt(3.5)));
vector<string> another_vector;
another_vector.push_back("fee");
EXPECT_THAT(another_vector, Each(string("fee")));
another_vector.push_back("fie");
another_vector.push_back("foe");
another_vector.push_back("fum");
EXPECT_THAT(another_vector, Not(Each(string("fee"))));
}
TEST(EachTest, MatchesMapWhenAllElementsMatch) {
map<const char*, int> my_map;
const char* bar = "a string";
my_map[bar] = 2;
EXPECT_THAT(my_map, Each(make_pair(bar, 2)));
map<string, int> another_map;
EXPECT_THAT(another_map, Each(make_pair(string("fee"), 1)));
another_map["fee"] = 1;
EXPECT_THAT(another_map, Each(make_pair(string("fee"), 1)));
another_map["fie"] = 2;
another_map["foe"] = 3;
another_map["fum"] = 4;
EXPECT_THAT(another_map, Not(Each(make_pair(string("fee"), 1))));
EXPECT_THAT(another_map, Not(Each(make_pair(string("fum"), 1))));
EXPECT_THAT(another_map, Each(Pair(_, Gt(0))));
}
TEST(EachTest, AcceptsMatcher) {
const int a[] = { 1, 2, 3 };
EXPECT_THAT(a, Each(Gt(0)));
EXPECT_THAT(a, Not(Each(Gt(1))));
}
TEST(EachTest, WorksForNativeArrayAsTuple) {
const int a[] = { 1, 2 };
const int* const pointer = a;
EXPECT_THAT(make_tuple(pointer, 2), Each(Gt(0)));
EXPECT_THAT(make_tuple(pointer, 2), Not(Each(Gt(1))));
}
} // namespace gmock_matchers_test
} // namespace testing