mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 03:43:28 +01:00
parent
3035120dc7
commit
495d2458e0
@ -10,10 +10,33 @@
|
||||
|
||||
#include "catch_matchers.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Catch {
|
||||
namespace Matchers {
|
||||
|
||||
namespace Vector {
|
||||
namespace Detail {
|
||||
template <typename InputIterator, typename T>
|
||||
size_t count(InputIterator first, InputIterator last, T const& item) {
|
||||
size_t cnt = 0;
|
||||
for (; first != last; ++first) {
|
||||
if (*first == item) {
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
template <typename InputIterator, typename T>
|
||||
bool contains(InputIterator first, InputIterator last, T const& item) {
|
||||
for (; first != last; ++first) {
|
||||
if (*first == item) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
|
||||
@ -89,6 +112,46 @@ namespace Matchers {
|
||||
std::vector<T> const& m_comparator;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
|
||||
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
|
||||
bool match(std::vector<T> const& vec) const override {
|
||||
// Note: This is a reimplementation of std::is_permutation,
|
||||
// because I don't want to include <algorithm> inside the common path
|
||||
if (m_target.size() != vec.size()) {
|
||||
return false;
|
||||
}
|
||||
auto lfirst = m_target.begin(), llast = m_target.end();
|
||||
auto rfirst = vec.begin(), rlast = vec.end();
|
||||
// Cut common prefix to optimize checking of permuted parts
|
||||
while (lfirst != llast && *lfirst != *rfirst) {
|
||||
++lfirst; ++rfirst;
|
||||
}
|
||||
if (lfirst == llast) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto mid = lfirst; mid != llast; ++mid) {
|
||||
// Skip already counted items
|
||||
if (Detail::contains(lfirst, mid, *mid)) {
|
||||
continue;
|
||||
}
|
||||
size_t num_vec = Detail::count(rfirst, rlast, *mid);
|
||||
if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string describe() const override {
|
||||
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
|
||||
}
|
||||
private:
|
||||
std::vector<T> const& m_target;
|
||||
};
|
||||
|
||||
} // namespace Vector
|
||||
|
||||
// The following functions create the actual matcher objects.
|
||||
@ -109,6 +172,11 @@ namespace Matchers {
|
||||
return Vector::EqualsMatcher<T>( comparator );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
|
||||
return Vector::UnorderedEqualsMatcher<T>(target);
|
||||
}
|
||||
|
||||
} // namespace Matchers
|
||||
} // namespace Catch
|
||||
|
||||
|
@ -828,6 +828,10 @@ Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) && VectorContains
|
||||
Matchers.tests.cpp:<line number>: passed: v, Equals(v) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: empty, Equals(empty) for: { } Equals: { }
|
||||
Matchers.tests.cpp:<line number>: passed: v, Equals(v2) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals(v) for: { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: empty, UnorderedEquals(empty) for: { } UnorderedEquals: { }
|
||||
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: failed: v, VectorContains(-1) for: { 1, 2, 3 } Contains: -1
|
||||
Matchers.tests.cpp:<line number>: failed: empty, VectorContains(1) for: { } Contains: 1
|
||||
Matchers.tests.cpp:<line number>: failed: empty, Contains(v) for: { } Contains: { 1, 2, 3 }
|
||||
@ -836,6 +840,10 @@ Matchers.tests.cpp:<line number>: failed: v, Equals(v2) for: { 1, 2, 3 } Equals:
|
||||
Matchers.tests.cpp:<line number>: failed: v2, Equals(v) for: { 1, 2 } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: failed: empty, Equals(v) for: { } Equals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: failed: v, Equals(empty) for: { 1, 2, 3 } Equals: { }
|
||||
Matchers.tests.cpp:<line number>: failed: v, UnorderedEquals(empty) for: { 1, 2, 3 } UnorderedEquals: { }
|
||||
Matchers.tests.cpp:<line number>: failed: empty, UnorderedEquals(v) for: { } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: failed: permuted, UnorderedEquals(v) for: { 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
Matchers.tests.cpp:<line number>: failed: permuted, UnorderedEquals(v) for: { 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows(), std::domain_error
|
||||
Exception.tests.cpp:<line number>: passed: thisDoesntThrow()
|
||||
Exception.tests.cpp:<line number>: passed: thisThrows()
|
||||
@ -1023,5 +1031,5 @@ Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
|
||||
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Misc.tests.cpp:<line number>: passed:
|
||||
Failed 50 test cases, failed 106 assertions.
|
||||
Failed 50 test cases, failed 110 assertions.
|
||||
|
||||
|
@ -809,6 +809,33 @@ Matchers.tests.cpp:<line number>: FAILED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers that fail
|
||||
UnorderedEquals
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( v, UnorderedEquals(empty) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } UnorderedEquals: { }
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( empty, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When unchecked exceptions are thrown directly they are always failures
|
||||
-------------------------------------------------------------------------------
|
||||
@ -1054,5 +1081,5 @@ with expansion:
|
||||
|
||||
===============================================================================
|
||||
test cases: 191 | 139 passed | 48 failed | 4 failed as expected
|
||||
assertions: 963 | 839 passed | 103 failed | 21 failed as expected
|
||||
assertions: 971 | 843 passed | 107 failed | 21 failed as expected
|
||||
|
||||
|
@ -6480,6 +6480,37 @@ PASSED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { 1, 2, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers
|
||||
UnorderedEquals
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK_THAT( v, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
CHECK_THAT( empty, UnorderedEquals(empty) )
|
||||
with expansion:
|
||||
{ } UnorderedEquals: { }
|
||||
|
||||
Matchers.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE_THAT( permuted, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>:
|
||||
PASSED:
|
||||
REQUIRE_THAT( permuted, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers that fail
|
||||
Contains (element)
|
||||
@ -6541,6 +6572,33 @@ Matchers.tests.cpp:<line number>: FAILED:
|
||||
with expansion:
|
||||
{ 1, 2, 3 } Equals: { }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Vector matchers that fail
|
||||
UnorderedEquals
|
||||
-------------------------------------------------------------------------------
|
||||
Matchers.tests.cpp:<line number>
|
||||
...............................................................................
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( v, UnorderedEquals(empty) )
|
||||
with expansion:
|
||||
{ 1, 2, 3 } UnorderedEquals: { }
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( empty, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
Matchers.tests.cpp:<line number>: FAILED:
|
||||
CHECK_THAT( permuted, UnorderedEquals(v) )
|
||||
with expansion:
|
||||
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
When checked exceptions are thrown they can be expected or unexpected
|
||||
-------------------------------------------------------------------------------
|
||||
@ -8057,5 +8115,5 @@ PASSED:
|
||||
|
||||
===============================================================================
|
||||
test cases: 191 | 137 passed | 50 failed | 4 failed as expected
|
||||
assertions: 962 | 835 passed | 106 failed | 21 failed as expected
|
||||
assertions: 970 | 839 passed | 110 failed | 21 failed as expected
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuitesloose text artifact
|
||||
>
|
||||
<testsuite name="<exe-name>" errors="15" failures="92" tests="963" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testsuite name="<exe-name>" errors="15" failures="96" tests="971" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
|
||||
@ -608,6 +608,7 @@ Exception.tests.cpp:<line number>
|
||||
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (vector)" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (element), composed" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Vector matchers/Equals" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Vector matchers/UnorderedEquals" time="{duration}"/>
|
||||
<testcase classname="<exe-name>.global" name="Vector matchers that fail/Contains (element)" time="{duration}">
|
||||
<failure message="{ 1, 2, 3 } Contains: -1" type="CHECK_THAT">
|
||||
Matchers.tests.cpp:<line number>
|
||||
@ -635,6 +636,20 @@ Matchers.tests.cpp:<line number>
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{ 1, 2, 3 } Equals: { }" type="CHECK_THAT">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase classname="<exe-name>.global" name="Vector matchers that fail/UnorderedEquals" time="{duration}">
|
||||
<failure message="{ 1, 2, 3 } UnorderedEquals: { }" type="CHECK_THAT">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{ } UnorderedEquals: { 1, 2, 3 }" type="CHECK_THAT">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{ 1, 3 } UnorderedEquals: { 1, 2, 3 }" type="CHECK_THAT">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
<failure message="{ 3, 1 } UnorderedEquals: { 1, 2, 3 }" type="CHECK_THAT">
|
||||
Matchers.tests.cpp:<line number>
|
||||
</failure>
|
||||
</testcase>
|
||||
|
@ -7377,6 +7377,41 @@ Message from section two
|
||||
</Expression>
|
||||
<OverallResults successes="3" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="UnorderedEquals" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
v, UnorderedEquals(v)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
empty, UnorderedEquals(empty)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ } UnorderedEquals: { }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
permuted, UnorderedEquals(v)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
permuted, UnorderedEquals(v)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="4" failures="0" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<TestCase name="Vector matchers that fail" tags="[.][failing][matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
@ -7453,6 +7488,41 @@ Message from section two
|
||||
</Expression>
|
||||
<OverallResults successes="0" failures="4" expectedFailures="0"/>
|
||||
</Section>
|
||||
<Section name="UnorderedEquals" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
v, UnorderedEquals(empty)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 2, 3 } UnorderedEquals: { }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
empty, UnorderedEquals(v)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ } UnorderedEquals: { 1, 2, 3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
permuted, UnorderedEquals(v)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 1, 3 } UnorderedEquals: { 1, 2, 3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||
<Original>
|
||||
permuted, UnorderedEquals(v)
|
||||
</Original>
|
||||
<Expanded>
|
||||
{ 3, 1 } UnorderedEquals: { 1, 2, 3 }
|
||||
</Expanded>
|
||||
</Expression>
|
||||
<OverallResults successes="0" failures="4" expectedFailures="0"/>
|
||||
</Section>
|
||||
<OverallResult success="false"/>
|
||||
</TestCase>
|
||||
<TestCase name="When checked exceptions are thrown they can be expected or unexpected" tags="[!throws]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||
@ -8968,7 +9038,7 @@ loose text artifact
|
||||
</Section>
|
||||
<OverallResult success="true"/>
|
||||
</TestCase>
|
||||
<OverallResults successes="835" failures="107" expectedFailures="21"/>
|
||||
<OverallResults successes="839" failures="111" expectedFailures="21"/>
|
||||
</Group>
|
||||
<OverallResults successes="835" failures="106" expectedFailures="21"/>
|
||||
<OverallResults successes="839" failures="110" expectedFailures="21"/>
|
||||
</Catch>
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
@ -216,6 +217,17 @@ namespace { namespace MatchersTests {
|
||||
v2.push_back(3);
|
||||
CHECK_THAT(v, Equals(v2));
|
||||
}
|
||||
SECTION("UnorderedEquals") {
|
||||
CHECK_THAT(v, UnorderedEquals(v));
|
||||
CHECK_THAT(empty, UnorderedEquals(empty));
|
||||
|
||||
auto permuted = v;
|
||||
std::next_permutation(begin(permuted), end(permuted));
|
||||
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||
|
||||
std::reverse(begin(permuted), end(permuted));
|
||||
REQUIRE_THAT(permuted, UnorderedEquals(v));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Vector matchers that fail", "[matchers][vector][.][failing]") {
|
||||
@ -247,6 +259,18 @@ namespace { namespace MatchersTests {
|
||||
CHECK_THAT(empty, Equals(v));
|
||||
CHECK_THAT(v, Equals(empty));
|
||||
}
|
||||
SECTION("UnorderedEquals") {
|
||||
CHECK_THAT(v, UnorderedEquals(empty));
|
||||
CHECK_THAT(empty, UnorderedEquals(v));
|
||||
|
||||
auto permuted = v;
|
||||
std::next_permutation(begin(permuted), end(permuted));
|
||||
permuted.pop_back();
|
||||
CHECK_THAT(permuted, UnorderedEquals(v));
|
||||
|
||||
std::reverse(begin(permuted), end(permuted));
|
||||
CHECK_THAT(permuted, UnorderedEquals(v));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
|
||||
|
Loading…
Reference in New Issue
Block a user