mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 13:26:10 +01:00
Add support for multiply calling lambda parsers in Clara
Previously a lambda parser in Clara could only be invoked once, even if it internally was ok with being invoked multiple times. With this change, a lambda parser can mark itself as `accept_many`, in which case it will be invoked multiple times if the appropriate flag was supplied multiple times by the user.
This commit is contained in:
parent
f17725a186
commit
12d14a3c63
@ -29,14 +29,17 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <catch2/internal/catch_noncopyable.hpp>
|
|
||||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||||
|
#include <catch2/internal/catch_noncopyable.hpp>
|
||||||
|
#include <catch2/internal/catch_void_type.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@ -53,7 +56,25 @@ namespace Catch {
|
|||||||
ShortCircuitSame
|
ShortCircuitSame
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct accept_many_t {};
|
||||||
|
constexpr accept_many_t accept_many {};
|
||||||
|
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
|
struct fake_arg {
|
||||||
|
template <typename T>
|
||||||
|
operator T();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F, typename = void>
|
||||||
|
struct is_unary_function : std::false_type {};
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
struct is_unary_function<
|
||||||
|
F,
|
||||||
|
Catch::Detail::void_t<decltype(
|
||||||
|
std::declval<F>()( fake_arg() ) )
|
||||||
|
>
|
||||||
|
> : std::true_type {};
|
||||||
|
|
||||||
// Traits for extracting arg and return type of lambdas (for single
|
// Traits for extracting arg and return type of lambdas (for single
|
||||||
// argument lambdas)
|
// argument lambdas)
|
||||||
@ -393,6 +414,11 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename L> struct BoundManyLambda : BoundLambda<L> {
|
||||||
|
explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {}
|
||||||
|
bool isContainer() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
|
template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
|
||||||
L m_lambda;
|
L m_lambda;
|
||||||
|
|
||||||
@ -447,12 +473,23 @@ namespace Catch {
|
|||||||
m_ref( ref ) {}
|
m_ref( ref ) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename LambdaT>
|
||||||
|
ParserRefImpl( accept_many_t,
|
||||||
|
LambdaT const& ref,
|
||||||
|
std::string const& hint ):
|
||||||
|
m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
|
||||||
|
m_hint( hint ) {}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename = typename std::enable_if_t<
|
||||||
|
!Detail::is_unary_function<T>::value>>
|
||||||
ParserRefImpl( T& ref, std::string const& hint ):
|
ParserRefImpl( T& ref, std::string const& hint ):
|
||||||
m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
|
||||||
m_hint( hint ) {}
|
m_hint( hint ) {}
|
||||||
|
|
||||||
template <typename LambdaT>
|
template <typename LambdaT,
|
||||||
|
typename = typename std::enable_if_t<
|
||||||
|
Detail::is_unary_function<LambdaT>::value>>
|
||||||
ParserRefImpl( LambdaT const& ref, std::string const& hint ):
|
ParserRefImpl( LambdaT const& ref, std::string const& hint ):
|
||||||
m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
|
m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
|
||||||
m_hint( hint ) {}
|
m_hint( hint ) {}
|
||||||
@ -513,13 +550,21 @@ namespace Catch {
|
|||||||
|
|
||||||
explicit Opt(bool& ref);
|
explicit Opt(bool& ref);
|
||||||
|
|
||||||
template <typename LambdaT>
|
template <typename LambdaT,
|
||||||
Opt(LambdaT const& ref, std::string const& hint) :
|
typename = typename std::enable_if_t<
|
||||||
ParserRefImpl(ref, hint) {}
|
Detail::is_unary_function<LambdaT>::value>>
|
||||||
|
Opt( LambdaT const& ref, std::string const& hint ):
|
||||||
|
ParserRefImpl( ref, hint ) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename LambdaT>
|
||||||
Opt(T& ref, std::string const& hint) :
|
Opt( accept_many_t, LambdaT const& ref, std::string const& hint ):
|
||||||
ParserRefImpl(ref, hint) {}
|
ParserRefImpl( accept_many, ref, hint ) {}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename = typename std::enable_if_t<
|
||||||
|
!Detail::is_unary_function<T>::value>>
|
||||||
|
Opt( T& ref, std::string const& hint ):
|
||||||
|
ParserRefImpl( ref, hint ) {}
|
||||||
|
|
||||||
auto operator[](std::string const& optName) -> Opt& {
|
auto operator[](std::string const& optName) -> Opt& {
|
||||||
m_optNames.push_back(optName);
|
m_optNames.push_back(optName);
|
||||||
|
@ -102,6 +102,7 @@ Nor would this
|
|||||||
: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 Clara::Arg supports single-arg parse the way Opt does
|
:test-result: PASS Clara::Arg supports single-arg parse the way Opt does
|
||||||
|
:test-result: PASS Clara::Opt supports accept-many lambdas
|
||||||
:test-result: PASS Combining MatchAllOfGeneric does not nest
|
:test-result: PASS Combining MatchAllOfGeneric does not nest
|
||||||
:test-result: PASS Combining MatchAnyOfGeneric does not nest
|
:test-result: PASS Combining MatchAnyOfGeneric does not nest
|
||||||
:test-result: PASS Combining MatchNotOfGeneric does not nest
|
:test-result: PASS Combining MatchNotOfGeneric does not nest
|
||||||
@ -297,6 +298,7 @@ Message from section two
|
|||||||
:test-result: FAIL first tag
|
:test-result: FAIL first tag
|
||||||
loose text artifact
|
loose text artifact
|
||||||
:test-result: FAIL has printf
|
:test-result: FAIL has printf
|
||||||
|
:test-result: PASS is_unary_function
|
||||||
:test-result: FAIL just failure
|
:test-result: FAIL just failure
|
||||||
:test-result: FAIL just failure after unscoped info
|
:test-result: FAIL just failure after unscoped info
|
||||||
:test-result: FAIL just info
|
:test-result: FAIL just info
|
||||||
|
@ -350,6 +350,9 @@ 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
|
||||||
Clara.tests.cpp:<line number>: passed: name.empty() for: true
|
Clara.tests.cpp:<line number>: passed: name.empty() for: true
|
||||||
Clara.tests.cpp:<line number>: passed: name == "foo" for: "foo" == "foo"
|
Clara.tests.cpp:<line number>: passed: name == "foo" for: "foo" == "foo"
|
||||||
|
Clara.tests.cpp:<line number>: passed: !(parse_result) for: !{?}
|
||||||
|
Clara.tests.cpp:<line number>: passed: parse_result for: {?}
|
||||||
|
Clara.tests.cpp:<line number>: passed: res == std::vector<std::string>{ "aaa", "bbb" } for: { "aaa", "bbb" } == { "aaa", "bbb" }
|
||||||
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype( ( MatcherA() && MatcherB() ) && MatcherC() ), Catch::Matchers::Detail:: MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value'
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype( ( MatcherA() && MatcherB() ) && MatcherC() ), Catch::Matchers::Detail:: 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: 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() ) ), Catch::Matchers::Detail:: MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value'
|
Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype( MatcherA() && ( MatcherB() && MatcherC() ) ), Catch::Matchers::Detail:: MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value'
|
||||||
@ -2111,6 +2114,18 @@ Misc.tests.cpp:<line number>: passed:
|
|||||||
Misc.tests.cpp:<line number>: passed:
|
Misc.tests.cpp:<line number>: passed:
|
||||||
Misc.tests.cpp:<line number>: passed:
|
Misc.tests.cpp:<line number>: passed:
|
||||||
loose text artifact
|
loose text artifact
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary3)>::value'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary4)>::value'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary5)>::value'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary6)>::value'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(binary1)>::value)'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(binary2)>::value)'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(nullary1)>::value)'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(nullary2)>::value)'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: '!(Catch::Clara::Detail::is_unary_function<int>::value)'
|
||||||
|
Clara.tests.cpp:<line number>: passed: with 1 message: '!(Catch::Clara::Detail::is_unary_function<std::string const&>::value)'
|
||||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Previous info should not be seen'
|
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Previous info should not be seen'
|
||||||
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'previous unscoped info SHOULD not be seen'
|
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'previous unscoped info SHOULD not be seen'
|
||||||
Misc.tests.cpp:<line number>: passed: l == std::numeric_limits<long long>::max() for: 9223372036854775807 (0x<hex digits>)
|
Misc.tests.cpp:<line number>: passed: l == std::numeric_limits<long long>::max() for: 9223372036854775807 (0x<hex digits>)
|
||||||
|
@ -1426,6 +1426,6 @@ due to unexpected exception with message:
|
|||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 374 | 297 passed | 70 failed | 7 failed as expected
|
test cases: 376 | 299 passed | 70 failed | 7 failed as expected
|
||||||
assertions: 2127 | 1971 passed | 129 failed | 27 failed as expected
|
assertions: 2142 | 1986 passed | 129 failed | 27 failed as expected
|
||||||
|
|
||||||
|
@ -2908,6 +2908,35 @@ Clara.tests.cpp:<line number>: PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
"foo" == "foo"
|
"foo" == "foo"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Clara::Opt supports accept-many lambdas
|
||||||
|
Parsing fails on multiple options without accept_many
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Clara.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
CHECK_FALSE( parse_result )
|
||||||
|
with expansion:
|
||||||
|
!{?}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Clara::Opt supports accept-many lambdas
|
||||||
|
Parsing succeeds on multiple options with accept_many
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Clara.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
CHECK( parse_result )
|
||||||
|
with expansion:
|
||||||
|
{?}
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
CHECK( res == std::vector<std::string>{ "aaa", "bbb" } )
|
||||||
|
with expansion:
|
||||||
|
{ "aaa", "bbb" } == { "aaa", "bbb" }
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Combining MatchAllOfGeneric does not nest
|
Combining MatchAllOfGeneric does not nest
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -14962,6 +14991,60 @@ Tricky.tests.cpp:<line number>
|
|||||||
|
|
||||||
No assertions in test case 'has printf'
|
No assertions in test case 'has printf'
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
is_unary_function
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Clara.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
Catch::Clara::Detail::is_unary_function<decltype(unary3)>::value
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
Catch::Clara::Detail::is_unary_function<decltype(unary4)>::value
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
Catch::Clara::Detail::is_unary_function<decltype(unary5)>::value
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
Catch::Clara::Detail::is_unary_function<decltype(unary6)>::value
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
!(Catch::Clara::Detail::is_unary_function<decltype(binary1)>::value)
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
!(Catch::Clara::Detail::is_unary_function<decltype(binary2)>::value)
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
!(Catch::Clara::Detail::is_unary_function<decltype(nullary1)>::value)
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
!(Catch::Clara::Detail::is_unary_function<decltype(nullary2)>::value)
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
!(Catch::Clara::Detail::is_unary_function<int>::value)
|
||||||
|
|
||||||
|
Clara.tests.cpp:<line number>: PASSED:
|
||||||
|
with message:
|
||||||
|
!(Catch::Clara::Detail::is_unary_function<std::string const&>::value)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
just failure
|
just failure
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -17144,6 +17227,6 @@ Misc.tests.cpp:<line number>
|
|||||||
Misc.tests.cpp:<line number>: PASSED:
|
Misc.tests.cpp:<line number>: PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 374 | 281 passed | 86 failed | 7 failed as expected
|
test cases: 376 | 283 passed | 86 failed | 7 failed as expected
|
||||||
assertions: 2144 | 1971 passed | 146 failed | 27 failed as expected
|
assertions: 2159 | 1986 passed | 146 failed | 27 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="129" tests="2144" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="17" failures="129" tests="2159" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="random-seed" value="1"/>
|
<property name="random-seed" value="1"/>
|
||||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
|
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/>
|
||||||
@ -382,6 +382,8 @@ Exception.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="Character pretty printing/General chars" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="Character pretty printing/General chars" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="Clara::Arg supports single-arg parse the way Opt does" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="Clara::Arg supports single-arg parse the way Opt does" time="{duration}" status="run"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Clara::Opt supports accept-many lambdas/Parsing fails on multiple options without accept_many" time="{duration}" status="run"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Clara::Opt supports accept-many lambdas/Parsing succeeds on multiple options with accept_many" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="Combining MatchAllOfGeneric does not nest" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="Combining MatchAllOfGeneric does not nest" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="Combining MatchAnyOfGeneric does not nest" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="Combining MatchAnyOfGeneric does not nest" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="Combining MatchNotOfGeneric does not nest" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="Combining MatchNotOfGeneric does not nest" time="{duration}" status="run"/>
|
||||||
@ -1601,6 +1603,7 @@ Misc.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="even more nested SECTION tests/c/d (leaf)" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="even more nested SECTION tests/c/d (leaf)" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="even more nested SECTION tests/c/e (leaf)" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="even more nested SECTION tests/c/e (leaf)" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="even more nested SECTION tests/f (leaf)" time="{duration}" status="run"/>
|
<testcase classname="<exe-name>.global" name="even more nested SECTION tests/f (leaf)" time="{duration}" status="run"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="is_unary_function" time="{duration}" status="run"/>
|
||||||
<testcase classname="<exe-name>.global" name="just failure" time="{duration}" status="run">
|
<testcase classname="<exe-name>.global" name="just failure" time="{duration}" status="run">
|
||||||
<failure type="FAIL">
|
<failure type="FAIL">
|
||||||
FAILED:
|
FAILED:
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
>
|
>
|
||||||
<file path="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp">
|
<file path="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp">
|
||||||
<testCase name="Clara::Arg supports single-arg parse the way Opt does" duration="{duration}"/>
|
<testCase name="Clara::Arg supports single-arg parse the way Opt does" duration="{duration}"/>
|
||||||
|
<testCase name="Clara::Opt supports accept-many lambdas/Parsing fails on multiple options without accept_many" duration="{duration}"/>
|
||||||
|
<testCase name="Clara::Opt supports accept-many lambdas/Parsing succeeds on multiple options with accept_many" duration="{duration}"/>
|
||||||
|
<testCase name="is_unary_function" duration="{duration}"/>
|
||||||
</file>
|
</file>
|
||||||
<file path="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp">
|
<file path="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp">
|
||||||
<testCase name="#1905 -- test spec parser properly clears internal state between compound tests" duration="{duration}"/>
|
<testCase name="#1905 -- test spec parser properly clears internal state between compound tests" duration="{duration}"/>
|
||||||
|
@ -698,6 +698,12 @@ ok {test-number} - c == i for: 5 == 5
|
|||||||
ok {test-number} - name.empty() for: true
|
ok {test-number} - name.empty() for: true
|
||||||
# Clara::Arg supports single-arg parse the way Opt does
|
# Clara::Arg supports single-arg parse the way Opt does
|
||||||
ok {test-number} - name == "foo" for: "foo" == "foo"
|
ok {test-number} - name == "foo" for: "foo" == "foo"
|
||||||
|
# Clara::Opt supports accept-many lambdas
|
||||||
|
ok {test-number} - !(parse_result) for: !{?}
|
||||||
|
# Clara::Opt supports accept-many lambdas
|
||||||
|
ok {test-number} - parse_result for: {?}
|
||||||
|
# Clara::Opt supports accept-many lambdas
|
||||||
|
ok {test-number} - res == std::vector<std::string>{ "aaa", "bbb" } for: { "aaa", "bbb" } == { "aaa", "bbb" }
|
||||||
# Combining MatchAllOfGeneric does not nest
|
# Combining MatchAllOfGeneric does not nest
|
||||||
ok {test-number} - with 1 message: 'std::is_same< decltype( ( MatcherA() && MatcherB() ) && MatcherC() ), Catch::Matchers::Detail:: MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value'
|
ok {test-number} - with 1 message: 'std::is_same< decltype( ( MatcherA() && MatcherB() ) && MatcherC() ), Catch::Matchers::Detail:: MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value'
|
||||||
# Combining MatchAllOfGeneric does not nest
|
# Combining MatchAllOfGeneric does not nest
|
||||||
@ -3786,6 +3792,30 @@ ok {test-number} -
|
|||||||
# even more nested SECTION tests
|
# even more nested SECTION tests
|
||||||
ok {test-number} -
|
ok {test-number} -
|
||||||
loose text artifact
|
loose text artifact
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary3)>::value'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary4)>::value'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary5)>::value'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary6)>::value'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(binary1)>::value)'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(binary2)>::value)'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(nullary1)>::value)'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: '!(Catch::Clara::Detail::is_unary_function<decltype(nullary2)>::value)'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: '!(Catch::Clara::Detail::is_unary_function<int>::value)'
|
||||||
|
# is_unary_function
|
||||||
|
ok {test-number} - with 1 message: '!(Catch::Clara::Detail::is_unary_function<std::string const&>::value)'
|
||||||
# just failure
|
# just failure
|
||||||
not ok {test-number} - explicitly with 1 message: 'Previous info should not be seen'
|
not ok {test-number} - explicitly with 1 message: 'Previous info should not be seen'
|
||||||
# just failure after unscoped info
|
# just failure after unscoped info
|
||||||
@ -4290,5 +4320,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..2144
|
1..2159
|
||||||
|
|
||||||
|
@ -237,6 +237,8 @@ Exception.tests.cpp:<line number>|nunexpected exception with message:|n "unexpe
|
|||||||
##teamcity[testFinished name='Character pretty printing' duration="{duration}"]
|
##teamcity[testFinished name='Character pretty printing' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Clara::Arg supports single-arg parse the way Opt does']
|
##teamcity[testStarted name='Clara::Arg supports single-arg parse the way Opt does']
|
||||||
##teamcity[testFinished name='Clara::Arg supports single-arg parse the way Opt does' duration="{duration}"]
|
##teamcity[testFinished name='Clara::Arg supports single-arg parse the way Opt does' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='Clara::Opt supports accept-many lambdas']
|
||||||
|
##teamcity[testFinished name='Clara::Opt supports accept-many lambdas' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Combining MatchAllOfGeneric does not nest']
|
##teamcity[testStarted name='Combining MatchAllOfGeneric does not nest']
|
||||||
##teamcity[testFinished name='Combining MatchAllOfGeneric does not nest' duration="{duration}"]
|
##teamcity[testFinished name='Combining MatchAllOfGeneric does not nest' duration="{duration}"]
|
||||||
##teamcity[testStarted name='Combining MatchAnyOfGeneric does not nest']
|
##teamcity[testStarted name='Combining MatchAnyOfGeneric does not nest']
|
||||||
@ -723,6 +725,8 @@ Misc.tests.cpp:<line number>|nexpression failed|n REQUIRE( testCheckedIf( false
|
|||||||
##teamcity[testStarted name='has printf']
|
##teamcity[testStarted name='has printf']
|
||||||
loose text artifact
|
loose text artifact
|
||||||
##teamcity[testFinished name='has printf' duration="{duration}"]
|
##teamcity[testFinished name='has printf' duration="{duration}"]
|
||||||
|
##teamcity[testStarted name='is_unary_function']
|
||||||
|
##teamcity[testFinished name='is_unary_function' duration="{duration}"]
|
||||||
##teamcity[testStarted name='just failure']
|
##teamcity[testStarted name='just failure']
|
||||||
Message.tests.cpp:<line number>|nexplicit failure with message:|n "Previous info should not be seen"']
|
Message.tests.cpp:<line number>|nexplicit failure with message:|n "Previous info should not be seen"']
|
||||||
##teamcity[testFinished name='just failure' duration="{duration}"]
|
##teamcity[testFinished name='just failure' duration="{duration}"]
|
||||||
|
@ -3156,6 +3156,39 @@ Nor would this
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="Clara::Opt supports accept-many lambdas" tags="[clara][opt]" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<Section name="Parsing fails on multiple options without accept_many" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<Expression success="true" type="CHECK_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
!(parse_result)
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
!{?}
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="1" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<Section name="Parsing succeeds on multiple options with accept_many" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
parse_result
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{?}
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="CHECK" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
res == std::vector<std::string>{ "aaa", "bbb" }
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{ "aaa", "bbb" } == { "aaa", "bbb" }
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResults successes="2" failures="0" expectedFailures="0"/>
|
||||||
|
</Section>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="Combining MatchAllOfGeneric does not nest" tags="[matchers][templated]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
<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" >
|
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
@ -17633,6 +17666,9 @@ There is no extra whitespace here
|
|||||||
loose text artifact
|
loose text artifact
|
||||||
<OverallResult success="false"/>
|
<OverallResult success="false"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="is_unary_function" tags="[clara][compilation]" filename="tests/<exe-name>/IntrospectiveTests/Clara.tests.cpp" >
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="just failure" tags="[.][fail][isolated info][messages]" filename="tests/<exe-name>/UsageTests/Message.tests.cpp" >
|
<TestCase name="just failure" tags="[.][fail][isolated info][messages]" filename="tests/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||||
<Failure filename="tests/<exe-name>/UsageTests/Message.tests.cpp" >
|
<Failure filename="tests/<exe-name>/UsageTests/Message.tests.cpp" >
|
||||||
Previous info should not be seen
|
Previous info should not be seen
|
||||||
@ -20147,6 +20183,6 @@ loose text artifact
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="1971" failures="146" expectedFailures="27"/>
|
<OverallResults successes="1986" failures="146" expectedFailures="27"/>
|
||||||
<OverallResultsCases successes="281" failures="86" expectedFailures="7"/>
|
<OverallResultsCases successes="283" failures="86" expectedFailures="7"/>
|
||||||
</Catch2TestRun>
|
</Catch2TestRun>
|
||||||
|
@ -4,19 +4,70 @@
|
|||||||
// https://www.boost.org/LICENSE_1_0.txt)
|
// https://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
// SPDX-License-Identifier: BSL-1.0
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
#include <catch2/internal/catch_clara.hpp>
|
#include <catch2/internal/catch_clara.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
TEST_CASE("is_unary_function", "[clara][compilation]") {
|
||||||
|
auto unary1 = [](int) {};
|
||||||
|
auto unary2 = [](std::string const&) {};
|
||||||
|
auto const unary3 = [](std::string const&) {};
|
||||||
|
auto unary4 = [](int) { return 42; };
|
||||||
|
void unary5(char);
|
||||||
|
double unary6(long);
|
||||||
|
|
||||||
|
double binary1(long, int);
|
||||||
|
auto binary2 = [](int, char) {};
|
||||||
|
auto nullary1 = []() {};
|
||||||
|
auto nullary2 = []() {return 42;};
|
||||||
|
|
||||||
|
STATIC_REQUIRE(Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value);
|
||||||
|
STATIC_REQUIRE(Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value);
|
||||||
|
STATIC_REQUIRE(Catch::Clara::Detail::is_unary_function<decltype(unary3)>::value);
|
||||||
|
STATIC_REQUIRE(Catch::Clara::Detail::is_unary_function<decltype(unary4)>::value);
|
||||||
|
STATIC_REQUIRE(Catch::Clara::Detail::is_unary_function<decltype(unary5)>::value);
|
||||||
|
STATIC_REQUIRE(Catch::Clara::Detail::is_unary_function<decltype(unary6)>::value);
|
||||||
|
|
||||||
|
STATIC_REQUIRE_FALSE(Catch::Clara::Detail::is_unary_function<decltype(binary1)>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(Catch::Clara::Detail::is_unary_function<decltype(binary2)>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(Catch::Clara::Detail::is_unary_function<decltype(nullary1)>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(Catch::Clara::Detail::is_unary_function<decltype(nullary2)>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(Catch::Clara::Detail::is_unary_function<int>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(Catch::Clara::Detail::is_unary_function<std::string const&>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Clara::Arg supports single-arg parse the way Opt does", "[clara][arg][compilation]") {
|
TEST_CASE("Clara::Arg supports single-arg parse the way Opt does", "[clara][arg][compilation]") {
|
||||||
std::string name;
|
std::string name;
|
||||||
auto p = Catch::Clara::Arg(name, "just one arg");
|
auto p = Catch::Clara::Arg(name, "just one arg");
|
||||||
|
|
||||||
CHECK(name.empty());
|
CHECK(name.empty());
|
||||||
|
|
||||||
p.parse( Catch::Clara::Args{ "UnitTest", "foo" } );
|
p.parse( Catch::Clara::Args{ "UnitTest", "foo" } );
|
||||||
REQUIRE(name == "foo");
|
REQUIRE(name == "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Clara::Opt supports accept-many lambdas", "[clara][opt]") {
|
||||||
|
std::string name;
|
||||||
|
using namespace Catch::Clara;
|
||||||
|
std::vector<std::string> res;
|
||||||
|
const auto push_to_res = [&](std::string const& s) {
|
||||||
|
res.push_back(s);
|
||||||
|
return ParserResult::ok();
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("Parsing fails on multiple options without accept_many") {
|
||||||
|
auto p = Parser() | Opt(push_to_res, "value")["-o"];
|
||||||
|
auto parse_result = p.parse( Args{ "UnitTest", "-o", "aaa", "-o", "bbb" } );
|
||||||
|
CHECK_FALSE(parse_result);
|
||||||
|
}
|
||||||
|
SECTION("Parsing succeeds on multiple options with accept_many") {
|
||||||
|
auto p = Parser() | Opt(accept_many, push_to_res, "value")["-o"];
|
||||||
|
auto parse_result = p.parse( Args{ "UnitTest", "-o", "aaa", "-o", "bbb" } );
|
||||||
|
CHECK(parse_result);
|
||||||
|
CHECK(res == std::vector<std::string>{ "aaa", "bbb" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user