From 10dfca34ac6db38b5be6ed7865f645aab90eeadb Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 21 Feb 2017 16:05:04 +0000 Subject: [PATCH] Added first vector matchers (Contains and Equals) --- CMakeLists.txt | 1 + include/catch.hpp | 1 + include/internal/catch_matchers_vector.h | 101 +++++++++++ .../Baselines/console.std.approved.txt | 65 ++++++- .../Baselines/console.sw.approved.txt | 140 ++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 35 +++- .../SelfTest/Baselines/xml.sw.approved.txt | 164 +++++++++++++++++- projects/SelfTest/MatchersTests.cpp | 69 ++++++++ 8 files changed, 569 insertions(+), 7 deletions(-) create mode 100644 include/internal/catch_matchers_vector.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eddb983..605fce0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_matchers.hpp ${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_string.hpp + ${HEADER_DIR}/internal/catch_matchers_vector.h ${HEADER_DIR}/internal/catch_message.h ${HEADER_DIR}/internal/catch_message.hpp ${HEADER_DIR}/internal/catch_notimplemented_exception.h diff --git a/include/catch.hpp b/include/catch.hpp index 72084c37..997f3ccc 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -37,6 +37,7 @@ #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" #include "internal/catch_matchers_string.h" +#include "internal/catch_matchers_vector.h" #include "internal/catch_compiler_capabilities.h" #include "internal/catch_interfaces_tag_alias_registry.h" diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h new file mode 100644 index 00000000..6a48a4e0 --- /dev/null +++ b/include/internal/catch_matchers_vector.h @@ -0,0 +1,101 @@ +/* + * Created by Phil Nash on 21/02/2017. + * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED +#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED + +#include "catch_matchers.hpp" + +namespace Catch { +namespace Matchers { + + namespace Vector { + + template + struct ContainsElementMatcher : MatcherBase, T> { + + ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} + + bool match(std::vector const &v) const CATCH_OVERRIDE { + return std::find(v.begin(), v.end(), m_comparator) != v.end(); + } + + virtual std::string describe() const CATCH_OVERRIDE { + return "Contains: " + Catch::toString( m_comparator ); + } + + T const& m_comparator; + }; + + template + struct ContainsMatcher : MatcherBase, std::vector > { + + ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const CATCH_OVERRIDE { + // !TBD: see note in EqualsMatcher + if (m_comparator.size() > v.size()) + return false; + for (size_t i = 0; i < m_comparator.size(); ++i) + if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) + return false; + return true; + } + virtual std::string describe() const CATCH_OVERRIDE { + return "Contains: " + Catch::toString( m_comparator ); + } + + std::vector const& m_comparator; + }; + + template + struct EqualsMatcher : MatcherBase, std::vector > { + + EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const CATCH_OVERRIDE { + // !TBD: This currently works if all elements can be compared using != + // - a more general approach would be via a compare template that defaults + // to using !=. but could be specialised for, e.g. std::vector etc + // - then just call that directly + if (m_comparator.size() != v.size()) + return false; + for (size_t i = 0; i < v.size(); ++i) + if (m_comparator[i] != v[i]) + return false; + return true; + } + virtual std::string describe() const CATCH_OVERRIDE { + return "Equals: " + Catch::toString( m_comparator ); + } + std::vector const& m_comparator; + }; + + } // namespace Vector + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + + template + Vector::ContainsMatcher Contains( std::vector const& comparator ) { + return Vector::ContainsMatcher( comparator ); + } + + template + Vector::ContainsElementMatcher VectorContains( T const& comparator ) { + return Vector::ContainsElementMatcher( comparator ); + } + + template + Vector::EqualsMatcher Equals( std::vector const& comparator ) { + return Vector::EqualsMatcher( comparator ); + } + +} // namespace Matchers +} // namespace Catch + +#endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 9c5ea971..81dfd96c 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -602,6 +602,67 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: 3.14 +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (element) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, VectorContains( -1 ) ) +with expansion: + { 1, 2, 3 } Contains: -1 + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, VectorContains( 1 ) ) +with expansion: + { } Contains: 1 + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (vector) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Contains( v) ) +with expansion: + { } Contains: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2, 4 } + +------------------------------------------------------------------------------- +Vector matchers that fail + Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( v2 ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v2, Equals( v ) ) +with expansion: + { 1, 2 } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Equals( v ) ) +with expansion: + { } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( empty ) ) +with expansion: + { 1, 2, 3 } Equals: { } + ------------------------------------------------------------------------------- When unchecked exceptions are thrown directly they are always failures ------------------------------------------------------------------------------- @@ -829,6 +890,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 160 | 116 passed | 42 failed | 2 failed as expected -assertions: 931 | 835 passed | 78 failed | 18 failed as expected +test cases: 162 | 117 passed | 43 failed | 2 failed as expected +assertions: 948 | 844 passed | 86 failed | 18 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index eb58e3a0..13a187d0 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -7880,6 +7880,142 @@ PASSED: with message: no assertions +------------------------------------------------------------------------------- +Vector matchers + Contains (element) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, VectorContains( 1 ) ) +with expansion: + { 1, 2, 3 } Contains: 1 + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, VectorContains( 2 ) ) +with expansion: + { 1, 2, 3 } Contains: 2 + +------------------------------------------------------------------------------- +Vector matchers + Contains (vector) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2 } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2, 3 } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Contains( empty) ) +with expansion: + { 1, 2, 3 } Contains: { } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( empty, Contains( empty) ) +with expansion: + { } Contains: { } + +------------------------------------------------------------------------------- +Vector matchers + Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Equals( v ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( empty, Equals( empty ) ) +with expansion: + { } Equals: { } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Equals( v2 ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2, 3 } + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (element) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, VectorContains( -1 ) ) +with expansion: + { 1, 2, 3 } Contains: -1 + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, VectorContains( 1 ) ) +with expansion: + { } Contains: 1 + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (vector) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Contains( v) ) +with expansion: + { } Contains: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2, 4 } + +------------------------------------------------------------------------------- +Vector matchers that fail + Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( v2 ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v2, Equals( v ) ) +with expansion: + { 1, 2 } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Equals( v ) ) +with expansion: + { } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( empty ) ) +with expansion: + { 1, 2, 3 } Equals: { } + ------------------------------------------------------------------------------- When checked exceptions are thrown they can be expected or unexpected ------------------------------------------------------------------------------- @@ -9152,6 +9288,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 160 | 115 passed | 43 failed | 2 failed as expected -assertions: 933 | 835 passed | 80 failed | 18 failed as expected +test cases: 162 | 116 passed | 44 failed | 2 failed as expected +assertions: 950 | 844 passed | 88 failed | 18 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 6b9ab73b..23044dc6 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -499,6 +499,39 @@ ExceptionTests.cpp: + + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 32ecb062..f62de9e3 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -8421,6 +8421,166 @@ there" + +
+ + + v, VectorContains( 1 ) + + + { 1, 2, 3 } Contains: 1 + + + + + v, VectorContains( 2 ) + + + { 1, 2, 3 } Contains: 2 + + + +
+
+ + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2 } + + + + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2, 3 } + + + + + v, Contains( empty) + + + { 1, 2, 3 } Contains: { } + + + + + empty, Contains( empty) + + + { } Contains: { } + + + +
+
+ + + v, Equals( v ) + + + { 1, 2, 3 } Equals: { 1, 2, 3 } + + + + + empty, Equals( empty ) + + + { } Equals: { } + + + + + v, Equals( v2 ) + + + { 1, 2, 3 } Equals: { 1, 2, 3 } + + + +
+ +
+ +
+ + + v, VectorContains( -1 ) + + + { 1, 2, 3 } Contains: -1 + + + + + empty, VectorContains( 1 ) + + + { } Contains: 1 + + + +
+
+ + + empty, Contains( v) + + + { } Contains: { 1, 2, 3 } + + + + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2, 4 } + + + +
+
+ + + v, Equals( v2 ) + + + { 1, 2, 3 } Equals: { 1, 2 } + + + + + v2, Equals( v ) + + + { 1, 2 } Equals: { 1, 2, 3 } + + + + + empty, Equals( v ) + + + { } Equals: { 1, 2, 3 } + + + + + v, Equals( empty ) + + + { 1, 2, 3 } Equals: { } + + + +
+ +
@@ -9682,7 +9842,7 @@ spanner - + - + diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index 601c6608..7bcd3cf8 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -97,3 +97,72 @@ TEST_CASE("Matchers can be negated (Not) with the ! operator - failing", "[match { CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ); } + +TEST_CASE( "Vector matchers", "[matchers][vector]" ) { + std::vector v; + v.push_back( 1 ); + v.push_back( 2 ); + v.push_back( 3 ); + + std::vector v2; + v2.push_back( 1 ); + v2.push_back( 2 ); + + std::vector empty; + + SECTION( "Contains (element)" ) { + CHECK_THAT( v, VectorContains( 1 ) ); + CHECK_THAT( v, VectorContains( 2 ) ); + } + SECTION( "Contains (vector)" ) { + CHECK_THAT( v, Contains( v2 ) ); + v2.push_back( 3 ); // now exactly matches + CHECK_THAT( v, Contains( v2 ) ); + + CHECK_THAT( v, Contains( empty) ); + CHECK_THAT( empty, Contains( empty) ); + } + + SECTION( "Equals" ) { + + // Same vector + CHECK_THAT( v, Equals( v ) ); + + CHECK_THAT( empty, Equals( empty ) ); + + // Different vector with same elements + v2.push_back( 3 ); + CHECK_THAT( v, Equals( v2 ) ); + } +} + +TEST_CASE( "Vector matchers that fail", "[matchers][vector][.][failing]" ) { + std::vector v; + v.push_back( 1 ); + v.push_back( 2 ); + v.push_back( 3 ); + + std::vector v2; + v2.push_back( 1 ); + v2.push_back( 2 ); + + std::vector empty; + + SECTION( "Contains (element)" ) { + CHECK_THAT( v, VectorContains( -1 ) ); + CHECK_THAT( empty, VectorContains( 1 ) ); + } + SECTION( "Contains (vector)" ) { + CHECK_THAT( empty, Contains( v) ); + v2.push_back( 4 ); + CHECK_THAT( v, Contains( v2 ) ); + } + + SECTION( "Equals" ) { + + CHECK_THAT( v, Equals( v2 ) ); + CHECK_THAT( v2, Equals( v ) ); + CHECK_THAT( empty, Equals( v ) ); + CHECK_THAT( v, Equals( empty ) ); + } +}