// Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Google Mock - a framework for writing C++ mock classes. // // This file tests the built-in matchers generated by a script. #include #include #include #include #include #include #include namespace { using std::list; using std::stringstream; using std::vector; using testing::_; using testing::ElementsAre; using testing::ElementsAreArray; using testing::Eq; using testing::Ge; using testing::Gt; using testing::MakeMatcher; using testing::Matcher; using testing::MatcherInterface; using testing::Ne; using testing::Not; using testing::Pointee; using testing::Ref; using testing::StrEq; using testing::internal::string; // Returns the description of the given matcher. template string Describe(const Matcher& m) { stringstream ss; m.DescribeTo(&ss); return ss.str(); } // Returns the description of the negation of the given matcher. template string DescribeNegation(const Matcher& m) { stringstream ss; m.DescribeNegationTo(&ss); return ss.str(); } // Returns the reason why x matches, or doesn't match, m. template string Explain(const MatcherType& m, const Value& x) { stringstream ss; m.ExplainMatchResultTo(x, &ss); return ss.str(); } // For testing ExplainMatchResultTo(). class GreaterThanMatcher : public MatcherInterface { public: explicit GreaterThanMatcher(int rhs) : rhs_(rhs) {} virtual bool Matches(int lhs) const { return lhs > rhs_; } virtual void DescribeTo(::std::ostream* os) const { *os << "is greater than " << rhs_; } virtual void ExplainMatchResultTo(int lhs, ::std::ostream* os) const { const int diff = lhs - rhs_; if (diff > 0) { *os << "is " << diff << " more than " << rhs_; } else if (diff == 0) { *os << "is the same as " << rhs_; } else { *os << "is " << -diff << " less than " << rhs_; } } private: const int rhs_; }; Matcher GreaterThan(int n) { return MakeMatcher(new GreaterThanMatcher(n)); } // Tests for ElementsAre(). // Evaluates to the number of elements in 'array'. #define GMOCK_ARRAY_SIZE_(array) (sizeof(array)/sizeof(array[0])) TEST(ElementsAreTest, CanDescribeExpectingNoElement) { Matcher&> m = ElementsAre(); EXPECT_EQ("is empty", Describe(m)); } TEST(ElementsAreTest, CanDescribeExpectingOneElement) { Matcher > m = ElementsAre(Gt(5)); EXPECT_EQ("has 1 element that is greater than 5", Describe(m)); } TEST(ElementsAreTest, CanDescribeExpectingManyElements) { Matcher > m = ElementsAre(StrEq("one"), "two"); EXPECT_EQ("has 2 elements where\n" "element 0 is equal to \"one\",\n" "element 1 is equal to \"two\"", Describe(m)); } TEST(ElementsAreTest, CanDescribeNegationOfExpectingNoElement) { Matcher > m = ElementsAre(); EXPECT_EQ("is not empty", DescribeNegation(m)); } TEST(ElementsAreTest, CanDescribeNegationOfExpectingOneElment) { Matcher& > m = ElementsAre(Gt(5)); EXPECT_EQ("does not have 1 element, or\n" "element 0 is not greater than 5", DescribeNegation(m)); } TEST(ElementsAreTest, CanDescribeNegationOfExpectingManyElements) { Matcher& > m = ElementsAre("one", "two"); EXPECT_EQ("does not have 2 elements, or\n" "element 0 is not equal to \"one\", or\n" "element 1 is not equal to \"two\"", DescribeNegation(m)); } TEST(ElementsAreTest, DoesNotExplainTrivialMatch) { Matcher& > m = ElementsAre(1, Ne(2)); list test_list; test_list.push_back(1); test_list.push_back(3); EXPECT_EQ("", Explain(m, test_list)); // No need to explain anything. } TEST(ElementsAreTest, ExplainsNonTrivialMatch) { Matcher& > m = ElementsAre(GreaterThan(1), 0, GreaterThan(2)); const int a[] = { 10, 0, 100 }; vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_EQ("element 0 is 9 more than 1,\n" "element 2 is 98 more than 2", Explain(m, test_vector)); } TEST(ElementsAreTest, CanExplainMismatchWrongSize) { Matcher& > m = ElementsAre(1, 3); list test_list; // No need to explain when the container is empty. EXPECT_EQ("", Explain(m, test_list)); test_list.push_back(1); EXPECT_EQ("has 1 element", Explain(m, test_list)); } TEST(ElementsAreTest, CanExplainMismatchRightSize) { Matcher& > m = ElementsAre(1, GreaterThan(5)); vector v; v.push_back(2); v.push_back(1); EXPECT_EQ("element 0 doesn't match", Explain(m, v)); v[0] = 1; EXPECT_EQ("element 1 doesn't match (is 4 less than 5)", Explain(m, v)); } TEST(ElementsAreTest, MatchesOneElementVector) { vector test_vector; test_vector.push_back("test string"); EXPECT_THAT(test_vector, ElementsAre(StrEq("test string"))); } TEST(ElementsAreTest, MatchesOneElementList) { list test_list; test_list.push_back("test string"); EXPECT_THAT(test_list, ElementsAre("test string")); } TEST(ElementsAreTest, MatchesThreeElementVector) { vector test_vector; test_vector.push_back("one"); test_vector.push_back("two"); test_vector.push_back("three"); EXPECT_THAT(test_vector, ElementsAre("one", StrEq("two"), _)); } TEST(ElementsAreTest, MatchesOneElementEqMatcher) { vector test_vector; test_vector.push_back(4); EXPECT_THAT(test_vector, ElementsAre(Eq(4))); } TEST(ElementsAreTest, MatchesOneElementAnyMatcher) { vector test_vector; test_vector.push_back(4); EXPECT_THAT(test_vector, ElementsAre(_)); } TEST(ElementsAreTest, MatchesOneElementValue) { vector test_vector; test_vector.push_back(4); EXPECT_THAT(test_vector, ElementsAre(4)); } TEST(ElementsAreTest, MatchesThreeElementsMixedMatchers) { vector test_vector; test_vector.push_back(1); test_vector.push_back(2); test_vector.push_back(3); EXPECT_THAT(test_vector, ElementsAre(1, Eq(2), _)); } TEST(ElementsAreTest, MatchesTenElementVector) { const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, // The element list can contain values and/or matchers // of different types. ElementsAre(0, Ge(0), _, 3, 4, Ne(2), Eq(6), 7, 8, _)); } TEST(ElementsAreTest, DoesNotMatchWrongSize) { vector test_vector; test_vector.push_back("test string"); test_vector.push_back("test string"); Matcher > m = ElementsAre(StrEq("test string")); EXPECT_FALSE(m.Matches(test_vector)); } TEST(ElementsAreTest, DoesNotMatchWrongValue) { vector test_vector; test_vector.push_back("other string"); Matcher > m = ElementsAre(StrEq("test string")); EXPECT_FALSE(m.Matches(test_vector)); } TEST(ElementsAreTest, DoesNotMatchWrongOrder) { vector test_vector; test_vector.push_back("one"); test_vector.push_back("three"); test_vector.push_back("two"); Matcher > m = ElementsAre( StrEq("one"), StrEq("two"), StrEq("three")); EXPECT_FALSE(m.Matches(test_vector)); } TEST(ElementsAreTest, WorksForNestedContainer) { const char* strings[] = { "Hi", "world" }; vector > nested; for (int i = 0; i < GMOCK_ARRAY_SIZE_(strings); i++) { nested.push_back(list(strings[i], strings[i] + strlen(strings[i]))); } EXPECT_THAT(nested, ElementsAre(ElementsAre('H', Ne('e')), ElementsAre('w', 'o', _, _, 'd'))); EXPECT_THAT(nested, Not(ElementsAre(ElementsAre('H', 'e'), ElementsAre('w', 'o', _, _, 'd')))); } TEST(ElementsAreTest, WorksWithByRefElementMatchers) { int a[] = { 0, 1, 2 }; vector v(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_THAT(v, ElementsAre(Ref(v[0]), Ref(v[1]), Ref(v[2]))); EXPECT_THAT(v, Not(ElementsAre(Ref(v[0]), Ref(v[1]), Ref(a[2])))); } TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) { int a[] = { 0, 1, 2 }; vector v(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_THAT(&v, Pointee(ElementsAre(0, 1, _))); EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3)))); } // Tests for ElementsAreArray(). Since ElementsAreArray() shares most // of the implementation with ElementsAre(), we don't test it as // thoroughly here. TEST(ElementsAreArrayTest, CanBeCreatedWithValueArray) { const int a[] = { 1, 2, 3 }; vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(a)); test_vector[2] = 0; EXPECT_THAT(test_vector, Not(ElementsAreArray(a))); } TEST(ElementsAreArrayTest, CanBeCreatedWithArraySize) { const char* a[] = { "one", "two", "three" }; vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(a, GMOCK_ARRAY_SIZE_(a))); const char** p = a; test_vector[0] = "1"; EXPECT_THAT(test_vector, Not(ElementsAreArray(p, GMOCK_ARRAY_SIZE_(a)))); } TEST(ElementsAreArrayTest, CanBeCreatedWithoutArraySize) { const char* a[] = { "one", "two", "three" }; vector test_vector(a, a + GMOCK_ARRAY_SIZE_(a)); EXPECT_THAT(test_vector, ElementsAreArray(a)); test_vector[0] = "1"; EXPECT_THAT(test_vector, Not(ElementsAreArray(a))); } TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) { const Matcher kMatcherArray[] = { StrEq("one"), StrEq("two"), StrEq("three") }; vector test_vector; test_vector.push_back("one"); test_vector.push_back("two"); test_vector.push_back("three"); EXPECT_THAT(test_vector, ElementsAreArray(kMatcherArray)); test_vector.push_back("three"); EXPECT_THAT(test_vector, Not(ElementsAreArray(kMatcherArray))); } } // namespace