mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-25 14:56:10 +01:00
Feature: generic matchers (#1843)
This commit extends the Matchers feature with the ability to have type-independent (e.g. templated) matchers. This is done by adding a new base type that Matchers can extend, `MatcherGenericBase`, and overloads of operators `!`, `&&` and `||` that handle matchers extending `MatcherGenericBase` in a special manner. These new matchers can also take their arguments as values and non-const references. Closes #1307 Closes #1553 Closes #1554 Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
This commit is contained in:
parent
db1a0465dc
commit
17c4b2d093
@ -77,6 +77,7 @@ set(INTERNAL_HEADERS
|
|||||||
${SOURCES_DIR}/catch_matchers_floating.h
|
${SOURCES_DIR}/catch_matchers_floating.h
|
||||||
${SOURCES_DIR}/catch_matchers_generic.hpp
|
${SOURCES_DIR}/catch_matchers_generic.hpp
|
||||||
${SOURCES_DIR}/catch_matchers_string.h
|
${SOURCES_DIR}/catch_matchers_string.h
|
||||||
|
${SOURCES_DIR}/catch_matchers_templates.hpp
|
||||||
${SOURCES_DIR}/catch_matchers_vector.h
|
${SOURCES_DIR}/catch_matchers_vector.h
|
||||||
${SOURCES_DIR}/catch_message.h
|
${SOURCES_DIR}/catch_message.h
|
||||||
${SOURCES_DIR}/catch_meta.hpp
|
${SOURCES_DIR}/catch_meta.hpp
|
||||||
@ -159,6 +160,7 @@ set(IMPL_SOURCES
|
|||||||
${SOURCES_DIR}/catch_matchers_floating.cpp
|
${SOURCES_DIR}/catch_matchers_floating.cpp
|
||||||
${SOURCES_DIR}/catch_matchers_generic.cpp
|
${SOURCES_DIR}/catch_matchers_generic.cpp
|
||||||
${SOURCES_DIR}/catch_matchers_string.cpp
|
${SOURCES_DIR}/catch_matchers_string.cpp
|
||||||
|
${SOURCES_DIR}/catch_matchers_templates.cpp
|
||||||
${SOURCES_DIR}/catch_message.cpp
|
${SOURCES_DIR}/catch_message.cpp
|
||||||
${SOURCES_DIR}/catch_output_redirect.cpp
|
${SOURCES_DIR}/catch_output_redirect.cpp
|
||||||
${SOURCES_DIR}/catch_registry_hub.cpp
|
${SOURCES_DIR}/catch_registry_hub.cpp
|
||||||
|
@ -17,7 +17,7 @@ namespace Catch {
|
|||||||
// the Equals matcher (so the header does not mention matchers)
|
// the Equals matcher (so the header does not mention matchers)
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) {
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) {
|
||||||
std::string exceptionMessage = Catch::translateActiveException();
|
std::string exceptionMessage = Catch::translateActiveException();
|
||||||
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
|
MatchExpr<std::string, StringMatcher const&> expr( std::move(exceptionMessage), matcher, matcherString );
|
||||||
handler.handleExpr( expr );
|
handler.handleExpr( expr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@ namespace Catch {
|
|||||||
|
|
||||||
template<typename ArgT, typename MatcherT>
|
template<typename ArgT, typename MatcherT>
|
||||||
class MatchExpr : public ITransientExpression {
|
class MatchExpr : public ITransientExpression {
|
||||||
ArgT const& m_arg;
|
ArgT && m_arg;
|
||||||
MatcherT m_matcher;
|
MatcherT m_matcher;
|
||||||
StringRef m_matcherString;
|
StringRef m_matcherString;
|
||||||
public:
|
public:
|
||||||
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
|
MatchExpr( ArgT && arg, MatcherT const& matcher, StringRef const& matcherString )
|
||||||
: ITransientExpression{ true, matcher.match( arg ) },
|
: ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose
|
||||||
m_arg( arg ),
|
m_arg( std::forward<ArgT>(arg) ),
|
||||||
m_matcher( matcher ),
|
m_matcher( matcher ),
|
||||||
m_matcherString( matcherString )
|
m_matcherString( matcherString )
|
||||||
{}
|
{}
|
||||||
@ -42,8 +42,8 @@ namespace Catch {
|
|||||||
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString );
|
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString );
|
||||||
|
|
||||||
template<typename ArgT, typename MatcherT>
|
template<typename ArgT, typename MatcherT>
|
||||||
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> {
|
auto makeMatchExpr( ArgT && arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> {
|
||||||
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
|
return MatchExpr<ArgT, MatcherT>( std::forward<ArgT>(arg), matcher, matcherString );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
32
src/catch2/catch_matchers_templates.cpp
Normal file
32
src/catch2/catch_matchers_templates.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <catch2/catch_matchers_templates.hpp>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
namespace Matchers {
|
||||||
|
namespace Impl {
|
||||||
|
MatcherGenericBase::~MatcherGenericBase() {}
|
||||||
|
|
||||||
|
std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end) {
|
||||||
|
std::string description;
|
||||||
|
std::size_t combined_size = 4;
|
||||||
|
for ( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
|
||||||
|
combined_size += desc->size();
|
||||||
|
}
|
||||||
|
combined_size += (descriptions_end - descriptions_begin - 1) * combine.size();
|
||||||
|
|
||||||
|
description.reserve(combined_size);
|
||||||
|
|
||||||
|
description += "( ";
|
||||||
|
bool first = true;
|
||||||
|
for( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
|
||||||
|
if( first )
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
description += combine;
|
||||||
|
description += *desc;
|
||||||
|
}
|
||||||
|
description += " )";
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Matchers
|
||||||
|
} // namespace Catch
|
262
src/catch2/catch_matchers_templates.hpp
Normal file
262
src/catch2/catch_matchers_templates.hpp
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
#ifndef TWOBLUECUBES_CATCH_MATCHERS_TEMPLATES_HPP_INCLUDED
|
||||||
|
#define TWOBLUECUBES_CATCH_MATCHERS_TEMPLATES_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <catch2/catch_common.h>
|
||||||
|
#include <catch2/catch_matchers.h>
|
||||||
|
#include <catch2/catch_stringref.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
namespace Matchers {
|
||||||
|
namespace Impl {
|
||||||
|
|
||||||
|
template<typename... MatcherTs> struct MatchAllOfGeneric;
|
||||||
|
template<typename... MatcherTs> struct MatchAnyOfGeneric;
|
||||||
|
template<typename MatcherT> struct MatchNotOfGeneric;
|
||||||
|
|
||||||
|
struct MatcherGenericBase : MatcherUntypedBase {
|
||||||
|
virtual ~MatcherGenericBase();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t N, std::size_t M>
|
||||||
|
std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
|
||||||
|
std::array<void const*, N + M> arr{};
|
||||||
|
std::copy_n(lhs.begin(), N, arr.begin());
|
||||||
|
std::copy_n(rhs.begin(), M, arr.begin() + N);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
|
||||||
|
std::array<void const*, N+1> arr{};
|
||||||
|
std::copy_n(lhs.begin(), N, arr.begin());
|
||||||
|
arr[N] = rhs;
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
|
||||||
|
std::array<void const*, N+1> arr{lhs};
|
||||||
|
std::copy_n(rhs.begin(), N, arr.begin() + 1);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CATCH_CPP17_OR_GREATER
|
||||||
|
|
||||||
|
using std::conjunction;
|
||||||
|
|
||||||
|
#else // CATCH_CPP17_OR_GREATER
|
||||||
|
|
||||||
|
template<typename... Cond>
|
||||||
|
struct conjunction : std::true_type {};
|
||||||
|
|
||||||
|
template<typename Cond, typename... Rest>
|
||||||
|
struct conjunction<Cond, Rest...> : std::integral_constant<bool, Cond::value && conjunction<Rest...>::value> {};
|
||||||
|
|
||||||
|
#endif // CATCH_CPP17_OR_GREATER
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using is_generic_matcher = std::is_base_of<
|
||||||
|
Catch::Matchers::Impl::MatcherGenericBase,
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type
|
||||||
|
>;
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
using are_generic_matchers = conjunction<is_generic_matcher<Ts>...>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using is_matcher = std::is_base_of<
|
||||||
|
Catch::Matchers::Impl::MatcherUntypedBase,
|
||||||
|
typename std::remove_cv<typename std::remove_reference<T>::type>::type
|
||||||
|
>;
|
||||||
|
|
||||||
|
|
||||||
|
template<std::size_t N, typename Arg>
|
||||||
|
bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
|
||||||
|
bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
|
||||||
|
return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<std::size_t N, typename Arg>
|
||||||
|
bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
|
||||||
|
bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
|
||||||
|
return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end);
|
||||||
|
|
||||||
|
template<typename... MatcherTs, std::size_t... Idx>
|
||||||
|
std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) {
|
||||||
|
std::array<std::string, sizeof...(MatcherTs)> descriptions {{
|
||||||
|
static_cast<MatcherTs const*>(matchers[Idx])->toString()...
|
||||||
|
}};
|
||||||
|
|
||||||
|
return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename... MatcherTs>
|
||||||
|
struct MatchAllOfGeneric : MatcherGenericBase {
|
||||||
|
MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{std::addressof(matchers)...} {}
|
||||||
|
explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
|
||||||
|
|
||||||
|
template<typename Arg>
|
||||||
|
bool match(Arg&& arg) const {
|
||||||
|
return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<void const*, sizeof...(MatcherTs)> m_matchers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename... MatcherTs>
|
||||||
|
struct MatchAnyOfGeneric : MatcherGenericBase {
|
||||||
|
MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{std::addressof(matchers)...} {}
|
||||||
|
explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
|
||||||
|
|
||||||
|
template<typename Arg>
|
||||||
|
bool match(Arg&& arg) const {
|
||||||
|
return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<void const*, sizeof...(MatcherTs)> m_matchers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename MatcherT>
|
||||||
|
struct MatchNotOfGeneric : MatcherGenericBase {
|
||||||
|
explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
|
||||||
|
|
||||||
|
template<typename Arg>
|
||||||
|
bool match(Arg&& arg) const {
|
||||||
|
return !m_matcher.match(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "not " + m_matcher.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
MatcherT const& m_matcher;
|
||||||
|
};
|
||||||
|
|
||||||
|
// compose only generic matchers
|
||||||
|
template<typename MatcherLHS, typename MatcherRHS>
|
||||||
|
typename std::enable_if<are_generic_matchers<MatcherLHS, MatcherRHS>::value, MatchAllOfGeneric<MatcherLHS, MatcherRHS>>::type
|
||||||
|
operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
|
||||||
|
return {lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatcherLHS, typename MatcherRHS>
|
||||||
|
typename std::enable_if<are_generic_matchers<MatcherLHS, MatcherRHS>::value, MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>::type
|
||||||
|
operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
|
||||||
|
return {lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatcherT>
|
||||||
|
typename std::enable_if<is_generic_matcher<MatcherT>::value, MatchNotOfGeneric<MatcherT>>::type
|
||||||
|
operator ! (MatcherT const& matcher) {
|
||||||
|
return MatchNotOfGeneric<MatcherT>{matcher};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// compose mixed generic and non-generic matchers
|
||||||
|
template<typename MatcherLHS, typename ArgRHS>
|
||||||
|
typename std::enable_if<is_generic_matcher<MatcherLHS>::value, MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>::type
|
||||||
|
operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
|
||||||
|
return {lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ArgLHS, typename MatcherRHS>
|
||||||
|
typename std::enable_if<is_generic_matcher<MatcherRHS>::value, MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>::type
|
||||||
|
operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
|
||||||
|
return {lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatcherLHS, typename ArgRHS>
|
||||||
|
typename std::enable_if<is_generic_matcher<MatcherLHS>::value, MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>::type
|
||||||
|
operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
|
||||||
|
return {lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ArgLHS, typename MatcherRHS>
|
||||||
|
typename std::enable_if<is_generic_matcher<MatcherRHS>::value, MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>::type
|
||||||
|
operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
|
||||||
|
return {lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// avoid deep nesting of matcher templates
|
||||||
|
template<typename... MatchersLHS, typename... MatchersRHS>
|
||||||
|
MatchAllOfGeneric<MatchersLHS..., MatchersRHS...>
|
||||||
|
operator && (MatchAllOfGeneric<MatchersLHS...> && lhs, MatchAllOfGeneric<MatchersRHS...> && rhs) {
|
||||||
|
return MatchAllOfGeneric<MatchersLHS..., MatchersRHS...>{array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... MatchersLHS, typename MatcherRHS>
|
||||||
|
typename std::enable_if<is_matcher<MatcherRHS>::value, MatchAllOfGeneric<MatchersLHS..., MatcherRHS>>::type
|
||||||
|
operator && (MatchAllOfGeneric<MatchersLHS...> && lhs, MatcherRHS const& rhs) {
|
||||||
|
return MatchAllOfGeneric<MatchersLHS..., MatcherRHS>{array_cat(std::move(lhs.m_matchers), static_cast<void const*>(&rhs))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatcherLHS, typename... MatchersRHS>
|
||||||
|
typename std::enable_if<is_matcher<MatcherLHS>::value, MatchAllOfGeneric<MatcherLHS, MatchersRHS...>>::type
|
||||||
|
operator && (MatcherLHS const& lhs, MatchAllOfGeneric<MatchersRHS...> && rhs) {
|
||||||
|
return MatchAllOfGeneric<MatcherLHS, MatchersRHS...>{array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... MatchersLHS, typename... MatchersRHS>
|
||||||
|
MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...>
|
||||||
|
operator || (MatchAnyOfGeneric<MatchersLHS...> && lhs, MatchAnyOfGeneric<MatchersRHS...> && rhs) {
|
||||||
|
return MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...>{array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... MatchersLHS, typename MatcherRHS>
|
||||||
|
typename std::enable_if<is_matcher<MatcherRHS>::value, MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>>::type
|
||||||
|
operator || (MatchAnyOfGeneric<MatchersLHS...> && lhs, MatcherRHS const& rhs) {
|
||||||
|
return MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>{array_cat(std::move(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatcherLHS, typename... MatchersRHS>
|
||||||
|
typename std::enable_if<is_matcher<MatcherLHS>::value, MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>>::type
|
||||||
|
operator || (MatcherLHS const& lhs, MatchAnyOfGeneric<MatchersRHS...> && rhs) {
|
||||||
|
return MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>{array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MatcherT>
|
||||||
|
MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
|
||||||
|
return matcher.m_matcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Impl
|
||||||
|
|
||||||
|
} // namespace Matchers
|
||||||
|
|
||||||
|
using namespace Matchers;
|
||||||
|
using Matchers::Impl::MatcherGenericBase;
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#endif //TWOBLUECUBES_CATCH_MATCHERS_TEMPLATES_HPP_INCLUDED
|
@ -85,6 +85,13 @@ Nor would this
|
|||||||
:test-result: PASS CAPTURE parses string and character constants
|
:test-result: PASS CAPTURE parses string and character constants
|
||||||
:test-result: PASS Capture and info messages
|
:test-result: PASS Capture and info messages
|
||||||
:test-result: PASS Character pretty printing
|
:test-result: PASS Character pretty printing
|
||||||
|
:test-result: PASS Combining MatchAllOfGeneric does not nest
|
||||||
|
:test-result: PASS Combining MatchAnyOfGeneric does not nest
|
||||||
|
:test-result: PASS Combining MatchNotOfGeneric does not nest
|
||||||
|
:test-result: PASS Combining concrete matchers does not use templated matchers
|
||||||
|
:test-result: PASS Combining only templated matchers
|
||||||
|
:test-result: PASS Combining templated and concrete matchers
|
||||||
|
:test-result: PASS Combining templated matchers
|
||||||
:test-result: PASS Commas in various macros are allowed
|
:test-result: PASS Commas in various macros are allowed
|
||||||
:test-result: PASS Comparing function pointers
|
:test-result: PASS Comparing function pointers
|
||||||
:test-result: PASS Comparison ops
|
:test-result: PASS Comparison ops
|
||||||
@ -147,6 +154,7 @@ Nor would this
|
|||||||
:test-result: PASS Ordering comparison checks that should succeed
|
:test-result: PASS Ordering comparison checks that should succeed
|
||||||
:test-result: PASS Our PCG implementation provides expected results for known seeds
|
:test-result: PASS Our PCG implementation provides expected results for known seeds
|
||||||
:test-result: FAIL Output from all sections is reported
|
:test-result: FAIL Output from all sections is reported
|
||||||
|
:test-result: PASS Overloaded comma or address-of operators are not used
|
||||||
:test-result: PASS Parse test names and tags
|
:test-result: PASS Parse test names and tags
|
||||||
:test-result: PASS Pointers can be compared to null
|
:test-result: PASS Pointers can be compared to null
|
||||||
:test-result: PASS Precision of floating point stringification can be set
|
:test-result: PASS Precision of floating point stringification can be set
|
||||||
|
@ -263,6 +263,37 @@ ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2
|
|||||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
|
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
|
||||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
|
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
|
||||||
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5
|
ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!MatcherA()), MatcherA const& >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, !!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 0, !!!MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!!!MatcherA()), MatcherA const & >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, !!!!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), Catch::Matchers::Impl::MatchAnyOf<std::string> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric<MatcherB>> >::value'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || !MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: vec, Predicate<std::vector<int>>([](auto const& vec) { return std::all_of(vec.begin(), vec.end(), [](int elem) { return elem % 2 == 1; }); }, "All elements are odd") && !EqualsRange(a) for: { 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5, 3, 1 } )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar") for: "foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and ends with: "bar" )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar") for: "foobar" ( starts with: "foo" and not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and ends with: "bar" )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar") for: "foobar" ( Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar") for: "foobar" ( not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar")) for: "foobar" ( Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } or ( starts with: "foo" and ends with: "bar" ) )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr) for: "foobar" ( ( starts with: "foo" and ends with: "bar" ) or Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } )
|
||||||
|
Matchers.tests.cpp:<line number>: passed: container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c) for: { 1, 2, 3 } ( Equals: { 1, 2, 3 } or Equals: { 0, 1, 2 } or Equals: { 4, 5, 6 } )
|
||||||
Tricky.tests.cpp:<line number>: passed: std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
|
Tricky.tests.cpp:<line number>: passed: std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
|
||||||
Tricky.tests.cpp:<line number>: passed: std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
|
Tricky.tests.cpp:<line number>: passed: std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
|
||||||
Tricky.tests.cpp:<line number>: passed: std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3}
|
Tricky.tests.cpp:<line number>: passed: std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3}
|
||||||
@ -883,6 +914,10 @@ RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits>
|
|||||||
4261393167 (0x<hex digits>)
|
4261393167 (0x<hex digits>)
|
||||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section one'
|
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section one'
|
||||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section two'
|
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section two'
|
||||||
|
Matchers.tests.cpp:<line number>: passed: (EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed
|
||||||
|
Matchers.tests.cpp:<line number>: passed: &EvilMatcher(), EvilAddressOfOperatorUsed
|
||||||
|
Matchers.tests.cpp:<line number>: passed: EvilMatcher() || EvilMatcher() && !EvilMatcher()
|
||||||
|
Matchers.tests.cpp:<line number>: passed: (EvilMatcher() && EvilMatcher()) || !EvilMatcher()
|
||||||
CmdLine.tests.cpp:<line number>: passed: spec.hasFilters() == false for: false == false
|
CmdLine.tests.cpp:<line number>: passed: spec.hasFilters() == false for: false == false
|
||||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( *tcA ) == false for: false == false
|
CmdLine.tests.cpp:<line number>: passed: spec.matches( *tcA ) == false for: false == false
|
||||||
CmdLine.tests.cpp:<line number>: passed: spec.matches( *tcB ) == false for: false == false
|
CmdLine.tests.cpp:<line number>: passed: spec.matches( *tcB ) == false for: false == false
|
||||||
|
@ -1380,6 +1380,6 @@ due to unexpected exception with message:
|
|||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 320 | 246 passed | 70 failed | 4 failed as expected
|
test cases: 328 | 254 passed | 70 failed | 4 failed as expected
|
||||||
assertions: 1792 | 1640 passed | 131 failed | 21 failed as expected
|
assertions: 1827 | 1675 passed | 131 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -2116,6 +2116,217 @@ ToStringGeneral.tests.cpp:<line number>: PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
5 == 5
|
5 == 5
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining MatchAllOfGeneric does not nest
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::
|
||||||
|
Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() && MatcherB() && MatcherC() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T)
|
||||||
|
1 )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()),
|
||||||
|
Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC,
|
||||||
|
MatcherD> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T)
|
||||||
|
1 and equals: true )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining MatchAnyOfGeneric does not nest
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::
|
||||||
|
Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() || MatcherB() || MatcherC() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1
|
||||||
|
)
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()),
|
||||||
|
Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC,
|
||||||
|
MatcherD> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1
|
||||||
|
or equals: true )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining MatchNotOfGeneric does not nest
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric
|
||||||
|
<MatcherA> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 0, !MatcherA() )
|
||||||
|
with expansion:
|
||||||
|
0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(!!MatcherA()), MatcherA const& >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, !!MatcherA() )
|
||||||
|
with expansion:
|
||||||
|
1 equals: (int) 1 or (float) 1.0f
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Impl::
|
||||||
|
MatchNotOfGeneric<MatcherA> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 0, !!!MatcherA() )
|
||||||
|
with expansion:
|
||||||
|
0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(!!!!MatcherA()), MatcherA const & >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, !!!!MatcherA() )
|
||||||
|
with expansion:
|
||||||
|
1 equals: (int) 1 or (float) 1.0f
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining concrete matchers does not use templated matchers
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith
|
||||||
|
("bar") && !EndsWith("foo"))), Catch::Matchers::Impl::MatchAnyOf<std::string>
|
||||||
|
>::value
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining only templated matchers
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Impl::
|
||||||
|
MatchAnyOfGeneric<MatcherA, MatcherB> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() || MatcherB() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Impl::
|
||||||
|
MatchAllOfGeneric<MatcherA, MatcherB> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() && MatcherB() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Impl::
|
||||||
|
MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric
|
||||||
|
<MatcherB>> >::value
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( 1, MatcherA() || !MatcherB() )
|
||||||
|
with expansion:
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining templated and concrete matchers
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( vec, Predicate<std::vector<int>>([](auto const& vec) { return std::all_of(vec.begin(), vec.end(), [](int elem) { return elem % 2 == 1; }); }, "All elements are odd") && !EqualsRange(a) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5,
|
||||||
|
3, 1 } )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar") )
|
||||||
|
with expansion:
|
||||||
|
"foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' }
|
||||||
|
and ends with: "bar" )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar") )
|
||||||
|
with expansion:
|
||||||
|
"foobar" ( starts with: "foo" and not Equals: { 'o', 'o', 'f', 'b', 'a', 'r'
|
||||||
|
} and ends with: "bar" )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar") )
|
||||||
|
with expansion:
|
||||||
|
"foobar" ( Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and starts with: "foo"
|
||||||
|
and ends with: "bar" )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar") )
|
||||||
|
with expansion:
|
||||||
|
"foobar" ( not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and starts with:
|
||||||
|
"foo" and ends with: "bar" )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar")) )
|
||||||
|
with expansion:
|
||||||
|
"foobar" ( Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } or ( starts with: "foo"
|
||||||
|
and ends with: "bar" ) )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr) )
|
||||||
|
with expansion:
|
||||||
|
"foobar" ( ( starts with: "foo" and ends with: "bar" ) or Equals: { 'o', 'o',
|
||||||
|
'f', 'b', 'a', 'r' } )
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Combining templated matchers
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THAT( container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c) )
|
||||||
|
with expansion:
|
||||||
|
{ 1, 2, 3 } ( Equals: { 1, 2, 3 } or Equals: { 0, 1, 2 } or Equals: { 4, 5, 6
|
||||||
|
} )
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Commas in various macros are allowed
|
Commas in various macros are allowed
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -6414,6 +6625,24 @@ Message.tests.cpp:<line number>: FAILED:
|
|||||||
explicitly with message:
|
explicitly with message:
|
||||||
Message from section two
|
Message from section two
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Overloaded comma or address-of operators are not used
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Matchers.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THROWS_AS( (EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_THROWS_AS( &EvilMatcher(), EvilAddressOfOperatorUsed )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_NOTHROW( EvilMatcher() || EvilMatcher() && !EvilMatcher() )
|
||||||
|
|
||||||
|
Matchers.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE_NOTHROW( (EvilMatcher() && EvilMatcher()) || !EvilMatcher() )
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Parse test names and tags
|
Parse test names and tags
|
||||||
Empty test spec should have no filters
|
Empty test spec should have no filters
|
||||||
@ -14053,6 +14282,6 @@ Misc.tests.cpp:<line number>
|
|||||||
Misc.tests.cpp:<line number>: PASSED:
|
Misc.tests.cpp:<line number>: PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 320 | 230 passed | 86 failed | 4 failed as expected
|
test cases: 328 | 238 passed | 86 failed | 4 failed as expected
|
||||||
assertions: 1809 | 1640 passed | 148 failed | 21 failed as expected
|
assertions: 1844 | 1675 passed | 148 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesloose text artifact
|
<testsuitesloose text artifact
|
||||||
>
|
>
|
||||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1810" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="17" failures="132" tests="1845" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
|
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
|
||||||
<property name="random-seed" value="1"/>
|
<property name="random-seed" value="1"/>
|
||||||
@ -350,6 +350,13 @@ Exception.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Character pretty printing/Specifically escaped" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Character pretty printing/Specifically escaped" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Character pretty printing/General chars" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Character pretty printing/General chars" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining MatchAllOfGeneric does not nest" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining MatchAnyOfGeneric does not nest" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining MatchNotOfGeneric does not nest" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining concrete matchers does not use templated matchers" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining only templated matchers" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining templated and concrete matchers" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Combining templated matchers" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Commas in various macros are allowed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Commas in various macros are allowed" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Comparing function pointers" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Comparing function pointers" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Comparison ops" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Comparison ops" time="{duration}"/>
|
||||||
@ -950,6 +957,7 @@ Message from section two
|
|||||||
Message.tests.cpp:<line number>
|
Message.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="Overloaded comma or address-of operators are not used" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Empty test spec should have no filters" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Parse test names and tags/Empty test spec should have no filters" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Test spec from empty string should have no filters" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Parse test names and tags/Test spec from empty string should have no filters" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Parse test names and tags/Test spec from just a comma should have no filters" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="Parse test names and tags/Test spec from just a comma should have no filters" time="{duration}"/>
|
||||||
|
@ -915,6 +915,13 @@ Exception.tests.cpp:<line number>
|
|||||||
<file path="tests/<exe-name>/UsageTests/Matchers.tests.cpp">
|
<file path="tests/<exe-name>/UsageTests/Matchers.tests.cpp">
|
||||||
<testCase name="Arbitrary predicate matcher/Function pointer" duration="{duration}"/>
|
<testCase name="Arbitrary predicate matcher/Function pointer" duration="{duration}"/>
|
||||||
<testCase name="Arbitrary predicate matcher/Lambdas + different type" duration="{duration}"/>
|
<testCase name="Arbitrary predicate matcher/Lambdas + different type" duration="{duration}"/>
|
||||||
|
<testCase name="Combining MatchAllOfGeneric does not nest" duration="{duration}"/>
|
||||||
|
<testCase name="Combining MatchAnyOfGeneric does not nest" duration="{duration}"/>
|
||||||
|
<testCase name="Combining MatchNotOfGeneric does not nest" duration="{duration}"/>
|
||||||
|
<testCase name="Combining concrete matchers does not use templated matchers" duration="{duration}"/>
|
||||||
|
<testCase name="Combining only templated matchers" duration="{duration}"/>
|
||||||
|
<testCase name="Combining templated and concrete matchers" duration="{duration}"/>
|
||||||
|
<testCase name="Combining templated matchers" duration="{duration}"/>
|
||||||
<testCase name="Contains string matcher" duration="{duration}">
|
<testCase name="Contains string matcher" duration="{duration}">
|
||||||
<failure message="CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No))">
|
<failure message="CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No))">
|
||||||
FAILED:
|
FAILED:
|
||||||
@ -1042,6 +1049,7 @@ with expansion:
|
|||||||
Matchers.tests.cpp:<line number>
|
Matchers.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testCase>
|
</testCase>
|
||||||
|
<testCase name="Overloaded comma or address-of operators are not used" duration="{duration}"/>
|
||||||
<testCase name="Predicate matcher can accept const char*" duration="{duration}"/>
|
<testCase name="Predicate matcher can accept const char*" duration="{duration}"/>
|
||||||
<testCase name="Regex string matcher" duration="{duration}">
|
<testCase name="Regex string matcher" duration="{duration}">
|
||||||
<failure message="CHECK_THAT(testStringForMatching(), Matches("this STRING contains 'abc' as a substring"))">
|
<failure message="CHECK_THAT(testStringForMatching(), Matches("this STRING contains 'abc' as a substring"))">
|
||||||
|
@ -524,6 +524,68 @@ ok {test-number} - c == i for: 3 == 3
|
|||||||
ok {test-number} - c == i for: 4 == 4
|
ok {test-number} - c == i for: 4 == 4
|
||||||
# Character pretty printing
|
# Character pretty printing
|
||||||
ok {test-number} - c == i for: 5 == 5
|
ok {test-number} - c == i for: 5 == 5
|
||||||
|
# Combining MatchAllOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||||
|
# Combining MatchAllOfGeneric does not nest
|
||||||
|
ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||||
|
# Combining MatchAllOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||||
|
# Combining MatchAllOfGeneric does not nest
|
||||||
|
ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||||
|
# Combining MatchAnyOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value'
|
||||||
|
# Combining MatchAnyOfGeneric does not nest
|
||||||
|
ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||||
|
# Combining MatchAnyOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value'
|
||||||
|
# Combining MatchAnyOfGeneric does not nest
|
||||||
|
ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value'
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(!!MatcherA()), MatcherA const& >::value'
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - 1, !!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value'
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - 0, !!!MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(!!!!MatcherA()), MatcherA const & >::value'
|
||||||
|
# Combining MatchNotOfGeneric does not nest
|
||||||
|
ok {test-number} - 1, !!!!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f
|
||||||
|
# Combining concrete matchers does not use templated matchers
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), Catch::Matchers::Impl::MatchAnyOf<std::string> >::value'
|
||||||
|
# Combining only templated matchers
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB> >::value'
|
||||||
|
# Combining only templated matchers
|
||||||
|
ok {test-number} - 1, MatcherA() || MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 )
|
||||||
|
# Combining only templated matchers
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB> >::value'
|
||||||
|
# Combining only templated matchers
|
||||||
|
ok {test-number} - 1, MatcherA() && MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 )
|
||||||
|
# Combining only templated matchers
|
||||||
|
ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric<MatcherB>> >::value'
|
||||||
|
# Combining only templated matchers
|
||||||
|
ok {test-number} - 1, MatcherA() || !MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - vec, Predicate<std::vector<int>>([](auto const& vec) { return std::all_of(vec.begin(), vec.end(), [](int elem) { return elem % 2 == 1; }); }, "All elements are odd") && !EqualsRange(a) for: { 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5, 3, 1 } )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar") for: "foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and ends with: "bar" )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar") for: "foobar" ( starts with: "foo" and not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and ends with: "bar" )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar") for: "foobar" ( Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar") for: "foobar" ( not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar")) for: "foobar" ( Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } or ( starts with: "foo" and ends with: "bar" ) )
|
||||||
|
# Combining templated and concrete matchers
|
||||||
|
ok {test-number} - str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr) for: "foobar" ( ( starts with: "foo" and ends with: "bar" ) or Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } )
|
||||||
|
# Combining templated matchers
|
||||||
|
ok {test-number} - container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c) for: { 1, 2, 3 } ( Equals: { 1, 2, 3 } or Equals: { 0, 1, 2 } or Equals: { 4, 5, 6 } )
|
||||||
# Commas in various macros are allowed
|
# Commas in various macros are allowed
|
||||||
ok {test-number} - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
|
ok {test-number} - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}}
|
||||||
# Commas in various macros are allowed
|
# Commas in various macros are allowed
|
||||||
@ -1688,6 +1750,14 @@ ok {test-number} - rng() == 0x<hex digits> for: 4261393167 (0x<hex digits>) == 4
|
|||||||
not ok {test-number} - explicitly with 1 message: 'Message from section one'
|
not ok {test-number} - explicitly with 1 message: 'Message from section one'
|
||||||
# Output from all sections is reported
|
# Output from all sections is reported
|
||||||
not ok {test-number} - explicitly with 1 message: 'Message from section two'
|
not ok {test-number} - explicitly with 1 message: 'Message from section two'
|
||||||
|
# Overloaded comma or address-of operators are not used
|
||||||
|
ok {test-number} - (EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed
|
||||||
|
# Overloaded comma or address-of operators are not used
|
||||||
|
ok {test-number} - &EvilMatcher(), EvilAddressOfOperatorUsed
|
||||||
|
# Overloaded comma or address-of operators are not used
|
||||||
|
ok {test-number} - EvilMatcher() || EvilMatcher() && !EvilMatcher()
|
||||||
|
# Overloaded comma or address-of operators are not used
|
||||||
|
ok {test-number} - (EvilMatcher() && EvilMatcher()) || !EvilMatcher()
|
||||||
# Parse test names and tags
|
# Parse test names and tags
|
||||||
ok {test-number} - spec.hasFilters() == false for: false == false
|
ok {test-number} - spec.hasFilters() == false for: false == false
|
||||||
# Parse test names and tags
|
# Parse test names and tags
|
||||||
@ -3610,5 +3680,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
|
|||||||
ok {test-number} -
|
ok {test-number} -
|
||||||
# xmlentitycheck
|
# xmlentitycheck
|
||||||
ok {test-number} -
|
ok {test-number} -
|
||||||
1..1801
|
1..1836
|
||||||
|
|
||||||
|
@ -203,6 +203,20 @@ Exception.tests.cpp:<line number>|nunexpected exception with message:|n "unexpe
|
|||||||
##teamcity[testFinished name='Capture and info messages' duration="{duration}"]
|
##teamcity[testFinished name='Capture and info messages' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Character pretty printing']
|
##teamcity[testStarted name='Character pretty printing']
|
||||||
##teamcity[testFinished name='Character pretty printing' duration="{duration}"]
|
##teamcity[testFinished name='Character pretty printing' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining MatchAllOfGeneric does not nest']
|
||||||
|
##teamcity[testFinished name='Combining MatchAllOfGeneric does not nest' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining MatchAnyOfGeneric does not nest']
|
||||||
|
##teamcity[testFinished name='Combining MatchAnyOfGeneric does not nest' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining MatchNotOfGeneric does not nest']
|
||||||
|
##teamcity[testFinished name='Combining MatchNotOfGeneric does not nest' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining concrete matchers does not use templated matchers']
|
||||||
|
##teamcity[testFinished name='Combining concrete matchers does not use templated matchers' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining only templated matchers']
|
||||||
|
##teamcity[testFinished name='Combining only templated matchers' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining templated and concrete matchers']
|
||||||
|
##teamcity[testFinished name='Combining templated and concrete matchers' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Combining templated matchers']
|
||||||
|
##teamcity[testFinished name='Combining templated matchers' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Commas in various macros are allowed']
|
##teamcity[testStarted name='Commas in various macros are allowed']
|
||||||
##teamcity[testFinished name='Commas in various macros are allowed' duration="{duration}"]
|
##teamcity[testFinished name='Commas in various macros are allowed' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Comparing function pointers']
|
##teamcity[testStarted name='Comparing function pointers']
|
||||||
@ -395,6 +409,8 @@ Condition.tests.cpp:<line number>|nexpression failed|n CHECK( data.str_hello <=
|
|||||||
Message.tests.cpp:<line number>|nexplicit failure with message:|n "Message from section one"']
|
Message.tests.cpp:<line number>|nexplicit failure with message:|n "Message from section one"']
|
||||||
Message.tests.cpp:<line number>|nexplicit failure with message:|n "Message from section two"']
|
Message.tests.cpp:<line number>|nexplicit failure with message:|n "Message from section two"']
|
||||||
##teamcity[testFinished name='Output from all sections is reported' duration="{duration}"]
|
##teamcity[testFinished name='Output from all sections is reported' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Overloaded comma or address-of operators are not used']
|
||||||
|
##teamcity[testFinished name='Overloaded comma or address-of operators are not used' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Parse test names and tags']
|
##teamcity[testStarted name='Parse test names and tags']
|
||||||
##teamcity[testFinished name='Parse test names and tags' duration="{duration}"]
|
##teamcity[testFinished name='Parse test names and tags' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Pointers can be compared to null']
|
##teamcity[testStarted name='Pointers can be compared to null']
|
||||||
|
@ -2417,6 +2417,179 @@ Nor would this
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="Combining MatchAllOfGeneric does not nest" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() && MatcherB() && MatcherC()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() && MatcherB() && MatcherC() && MatcherD()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Combining MatchAnyOfGeneric does not nest" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() || MatcherB() || MatcherC()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() || MatcherB() || MatcherC() || MatcherD()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Combining MatchNotOfGeneric does not nest" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
0, !MatcherA()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, !!MatcherA()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 equals: (int) 1 or (float) 1.0f
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
0, !!!MatcherA()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
0 not equals: (int) 1 or (float) 1.0f
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, !!!!MatcherA()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 equals: (int) 1 or (float) 1.0f
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Combining concrete matchers does not use templated matchers" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Combining only templated matchers" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() || MatcherB()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() && MatcherB()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
1, MatcherA() || !MatcherB()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Combining templated and concrete matchers" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
vec, Predicate<std::vector<int>>([](auto const& vec) { return std::all_of(vec.begin(), vec.end(), [](int elem) { return elem % 2 == 1; }); }, "All elements are odd") && !EqualsRange(a)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5, 3, 1 } )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar")
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and ends with: "bar" )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar")
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"foobar" ( starts with: "foo" and not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and ends with: "bar" )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar")
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"foobar" ( Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar")
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"foobar" ( not Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } and starts with: "foo" and ends with: "bar" )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar"))
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"foobar" ( Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } or ( starts with: "foo" and ends with: "bar" ) )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
"foobar" ( ( starts with: "foo" and ends with: "bar" ) or Equals: { 'o', 'o', 'f', 'b', 'a', 'r' } )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Combining templated matchers" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ 1, 2, 3 } ( Equals: { 1, 2, 3 } or Equals: { 0, 1, 2 } or Equals: { 4, 5, 6 } )
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="Commas in various macros are allowed" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<TestCase name="Commas in various macros are allowed" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
<Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/UsageTests/Tricky.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
@ -8025,6 +8198,41 @@ Nor would this
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="false"/>
|
<OverallResult success="false"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="Overloaded comma or address-of operators are not used" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE_THROWS_AS" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
(EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
(EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_THROWS_AS" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
&EvilMatcher(), EvilAddressOfOperatorUsed
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
&EvilMatcher(), EvilAddressOfOperatorUsed
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_NOTHROW" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
EvilMatcher() || EvilMatcher() && !EvilMatcher()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
EvilMatcher() || EvilMatcher() && !EvilMatcher()
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE_NOTHROW" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
(EvilMatcher() && EvilMatcher()) || !EvilMatcher()
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
(EvilMatcher() && EvilMatcher()) || !EvilMatcher()
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="Parse test names and tags" tags="[command-line][test-spec]" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
|
<TestCase name="Parse test names and tags" tags="[command-line][test-spec]" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
|
||||||
<Section name="Empty test spec should have no filters" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
|
<Section name="Empty test spec should have no filters" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
|
||||||
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
|
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
|
||||||
@ -16909,7 +17117,7 @@ loose text artifact
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="1640" failures="149" expectedFailures="21"/>
|
<OverallResults successes="1675" failures="149" expectedFailures="21"/>
|
||||||
</Group>
|
</Group>
|
||||||
<OverallResults successes="1640" failures="148" expectedFailures="21"/>
|
<OverallResults successes="1675" failures="148" expectedFailures="21"/>
|
||||||
</Catch>
|
</Catch>
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
#include <catch2/catch_matchers_generic.hpp>
|
#include <catch2/catch_matchers_generic.hpp>
|
||||||
#include <catch2/catch_matchers_string.h>
|
#include <catch2/catch_matchers_string.h>
|
||||||
#include <catch2/catch_matchers_vector.h>
|
#include <catch2/catch_matchers_vector.h>
|
||||||
|
#include <catch2/catch_matchers_templates.hpp>
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <list>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
@ -554,6 +556,302 @@ namespace { namespace MatchersTests {
|
|||||||
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
|
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Range>
|
||||||
|
struct EqualsRangeMatcher : Catch::MatcherGenericBase {
|
||||||
|
|
||||||
|
EqualsRangeMatcher(Range const& range) : range{ range } {}
|
||||||
|
|
||||||
|
template<typename OtherRange>
|
||||||
|
bool match(OtherRange const& other) const {
|
||||||
|
using std::begin;
|
||||||
|
using std::end;
|
||||||
|
|
||||||
|
return std::equal(begin(range), end(range), begin(other), end(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "Equals: " + Catch::rangeToString(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Range const& range;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Range>
|
||||||
|
auto EqualsRange(const Range& range) -> EqualsRangeMatcher<Range> {
|
||||||
|
return EqualsRangeMatcher<Range>{range};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Combining templated matchers", "[matchers][templated]") {
|
||||||
|
std::array<int, 3> container{{ 1,2,3 }};
|
||||||
|
|
||||||
|
std::array<int, 3> a{{ 1,2,3 }};
|
||||||
|
std::vector<int> b{ 0,1,2 };
|
||||||
|
std::list<int> c{ 4,5,6 };
|
||||||
|
|
||||||
|
REQUIRE_THAT(container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Combining templated and concrete matchers", "[matchers][templated]") {
|
||||||
|
using namespace Catch::Matchers;
|
||||||
|
std::vector<int> vec{ 1, 3, 5 };
|
||||||
|
|
||||||
|
std::array<int, 3> a{{ 5, 3, 1 }};
|
||||||
|
|
||||||
|
REQUIRE_THAT(vec,
|
||||||
|
Predicate<std::vector<int>>([](auto const& vec) {
|
||||||
|
return std::all_of(vec.begin(), vec.end(), [](int elem) {
|
||||||
|
return elem % 2 == 1;
|
||||||
|
});
|
||||||
|
}, "All elements are odd") &&
|
||||||
|
!EqualsRange(a));
|
||||||
|
|
||||||
|
const std::string str = "foobar";
|
||||||
|
const std::array<char, 6> arr{{ 'f', 'o', 'o', 'b', 'a', 'r' }};
|
||||||
|
const std::array<char, 6> bad_arr{{ 'o', 'o', 'f', 'b', 'a', 'r' }};
|
||||||
|
|
||||||
|
using Catch::Matchers::StartsWith;
|
||||||
|
using Catch::Matchers::EndsWith;
|
||||||
|
|
||||||
|
REQUIRE_THAT(str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar"));
|
||||||
|
REQUIRE_THAT(str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar"));
|
||||||
|
|
||||||
|
REQUIRE_THAT(str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar"));
|
||||||
|
REQUIRE_THAT(str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar"));
|
||||||
|
|
||||||
|
REQUIRE_THAT(str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar")));
|
||||||
|
REQUIRE_THAT(str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Combining concrete matchers does not use templated matchers", "[matchers][templated]") {
|
||||||
|
using Catch::Matchers::StartsWith;
|
||||||
|
using Catch::Matchers::EndsWith;
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))),
|
||||||
|
Catch::Matchers::Impl::MatchAnyOf<std::string>
|
||||||
|
>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MatcherA : Catch::MatcherGenericBase {
|
||||||
|
std::string describe() const override { return "equals: (int) 1 or (float) 1.0f"; }
|
||||||
|
bool match(int i) const { return i == 1; }
|
||||||
|
bool match(float f) const { return f == 1.0f; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MatcherB : Catch::MatcherGenericBase {
|
||||||
|
std::string describe() const override { return "equals: (long long) 1"; }
|
||||||
|
bool match(long long l) const { return l == 1ll; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MatcherC : Catch::MatcherGenericBase {
|
||||||
|
std::string describe() const override { return "equals: (T) 1"; }
|
||||||
|
template<typename T>
|
||||||
|
bool match(T t) const { return t == T{1}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MatcherD : Catch::MatcherGenericBase {
|
||||||
|
std::string describe() const override { return "equals: true"; }
|
||||||
|
bool match(bool b) const { return b == true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("Combining only templated matchers", "[matchers][templated]") {
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() || MatcherB()),
|
||||||
|
Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() || MatcherB());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() && MatcherB()),
|
||||||
|
Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() && MatcherB());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() || !MatcherB()),
|
||||||
|
Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric<MatcherB>>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() || !MatcherB());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Combining MatchAnyOfGeneric does not nest", "[matchers][templated]") {
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() || MatcherB() || MatcherC()),
|
||||||
|
Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()),
|
||||||
|
Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC() || MatcherD());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Combining MatchAllOfGeneric does not nest", "[matchers][templated]") {
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() && MatcherB() && MatcherC()),
|
||||||
|
Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()),
|
||||||
|
Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC() && MatcherD());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Combining MatchNotOfGeneric does not nest", "[matchers][templated]") {
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(!MatcherA()),
|
||||||
|
Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(0, !MatcherA());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(!!MatcherA()),
|
||||||
|
MatcherA const&
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, !!MatcherA());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(!!!MatcherA()),
|
||||||
|
Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA>
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(0, !!!MatcherA());
|
||||||
|
|
||||||
|
STATIC_REQUIRE(std::is_same<
|
||||||
|
decltype(!!!!MatcherA()),
|
||||||
|
MatcherA const &
|
||||||
|
>::value);
|
||||||
|
|
||||||
|
REQUIRE_THAT(1, !!!!MatcherA());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EvilAddressOfOperatorUsed : std::exception {
|
||||||
|
EvilAddressOfOperatorUsed() {}
|
||||||
|
const char* what() const noexcept override {
|
||||||
|
return "overloaded address-of operator of matcher was used instead of std::addressof";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EvilCommaOperatorUsed : std::exception {
|
||||||
|
EvilCommaOperatorUsed() {}
|
||||||
|
const char* what() const noexcept override {
|
||||||
|
return "overloaded comma operator of matcher was used";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EvilMatcher : Catch::MatcherGenericBase {
|
||||||
|
std::string describe() const override {
|
||||||
|
return "equals: 45";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match(int i) const {
|
||||||
|
return i == 45;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvilMatcher const* operator& () const {
|
||||||
|
throw EvilAddressOfOperatorUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
int operator,(EvilMatcher const&) const {
|
||||||
|
throw EvilCommaOperatorUsed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("Overloaded comma or address-of operators are not used", "[matchers][templated]") {
|
||||||
|
REQUIRE_THROWS_AS((EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed);
|
||||||
|
REQUIRE_THROWS_AS(&EvilMatcher(), EvilAddressOfOperatorUsed);
|
||||||
|
REQUIRE_NOTHROW(EvilMatcher() || EvilMatcher() && !EvilMatcher());
|
||||||
|
REQUIRE_NOTHROW((EvilMatcher() && EvilMatcher()) || !EvilMatcher());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImmovableMatcher : Catch::MatcherGenericBase {
|
||||||
|
ImmovableMatcher() = default;
|
||||||
|
ImmovableMatcher(ImmovableMatcher const&) = delete;
|
||||||
|
ImmovableMatcher(ImmovableMatcher &&) = delete;
|
||||||
|
ImmovableMatcher& operator=(ImmovableMatcher const&) = delete;
|
||||||
|
ImmovableMatcher& operator=(ImmovableMatcher &&) = delete;
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "always false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool match(T&&) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MatcherWasMovedOrCopied : std::exception {
|
||||||
|
MatcherWasMovedOrCopied() {}
|
||||||
|
const char* what() const noexcept override {
|
||||||
|
return "attempted to copy or move a matcher";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThrowOnCopyOrMoveMatcher : Catch::MatcherGenericBase {
|
||||||
|
ThrowOnCopyOrMoveMatcher() = default;
|
||||||
|
[[noreturn]]
|
||||||
|
ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher const&) {
|
||||||
|
throw MatcherWasMovedOrCopied();
|
||||||
|
}
|
||||||
|
[[noreturn]]
|
||||||
|
ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher &&) {
|
||||||
|
throw MatcherWasMovedOrCopied();
|
||||||
|
}
|
||||||
|
ThrowOnCopyOrMoveMatcher& operator=(ThrowOnCopyOrMoveMatcher const&) {
|
||||||
|
throw MatcherWasMovedOrCopied();
|
||||||
|
}
|
||||||
|
ThrowOnCopyOrMoveMatcher& operator=(ThrowOnCopyOrMoveMatcher &&) {
|
||||||
|
throw MatcherWasMovedOrCopied();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string describe() const override {
|
||||||
|
return "always false";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool match(T&&) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("Matchers are not moved or copied", "[matchers][templated][approvals]") {
|
||||||
|
REQUIRE_NOTHROW((ThrowOnCopyOrMoveMatcher() && ThrowOnCopyOrMoveMatcher()) || !ThrowOnCopyOrMoveMatcher());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Immovable matchers can be used", "[matchers][templated][approvals]") {
|
||||||
|
REQUIRE_THAT(123, (ImmovableMatcher() && ImmovableMatcher()) || !ImmovableMatcher());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReferencingMatcher : Catch::MatcherGenericBase {
|
||||||
|
std::string describe() const override {
|
||||||
|
return "takes reference";
|
||||||
|
}
|
||||||
|
bool match(int& i) const {
|
||||||
|
return i == 22;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("Matchers can take references", "[matchers][templated][approvals]") {
|
||||||
|
REQUIRE_THAT(22, ReferencingMatcher{});
|
||||||
|
}
|
||||||
|
|
||||||
} } // namespace MatchersTests
|
} } // namespace MatchersTests
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
|
Loading…
Reference in New Issue
Block a user