mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +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:
		| @@ -29,14 +29,17 @@ | ||||
| #    endif | ||||
| #endif | ||||
|  | ||||
| #include <catch2/internal/catch_noncopyable.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 <cctype> | ||||
| #include <memory> | ||||
| #include <ostream> | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch { | ||||
| @@ -53,7 +56,25 @@ namespace Catch { | ||||
|             ShortCircuitSame | ||||
|         }; | ||||
|  | ||||
|         struct accept_many_t {}; | ||||
|         constexpr accept_many_t accept_many {}; | ||||
|  | ||||
|         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 | ||||
|             // 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 { | ||||
|                 L m_lambda; | ||||
|  | ||||
| @@ -447,12 +473,23 @@ namespace Catch { | ||||
|                     m_ref( ref ) {} | ||||
|  | ||||
|             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 ): | ||||
|                     m_ref( std::make_shared<BoundValueRef<T>>( ref ) ), | ||||
|                     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 ): | ||||
|                     m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ), | ||||
|                     m_hint( hint ) {} | ||||
| @@ -513,11 +550,19 @@ namespace Catch { | ||||
|  | ||||
|             explicit Opt(bool& ref); | ||||
|  | ||||
|             template <typename LambdaT> | ||||
|             template <typename LambdaT, | ||||
|                       typename = typename std::enable_if_t< | ||||
|                           Detail::is_unary_function<LambdaT>::value>> | ||||
|             Opt( LambdaT const& ref, std::string const& hint ): | ||||
|                 ParserRefImpl( ref, hint ) {} | ||||
|  | ||||
|             template <typename T> | ||||
|             template <typename LambdaT> | ||||
|             Opt( accept_many_t, LambdaT const& ref, std::string const& 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 ) {} | ||||
|  | ||||
|   | ||||
| @@ -102,6 +102,7 @@ Nor would this | ||||
| :test-result: PASS Capture and info messages | ||||
| :test-result: PASS Character pretty printing | ||||
| :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 MatchAnyOfGeneric does not nest | ||||
| :test-result: PASS Combining MatchNotOfGeneric does not nest | ||||
| @@ -297,6 +298,7 @@ Message from section two | ||||
| :test-result: FAIL first tag | ||||
| loose text artifact | ||||
| :test-result: FAIL has printf | ||||
| :test-result: PASS is_unary_function | ||||
| :test-result: FAIL just failure | ||||
| :test-result: FAIL just failure after unscoped 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 | ||||
| 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: !(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: 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' | ||||
| @@ -2111,6 +2114,18 @@ Misc.tests.cpp:<line number>: passed: | ||||
| Misc.tests.cpp:<line number>: passed: | ||||
| Misc.tests.cpp:<line number>: passed: | ||||
| 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 unscoped info SHOULD not be seen' | ||||
| 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? | ||||
|  | ||||
| =============================================================================== | ||||
| test cases:  374 |  297 passed |  70 failed |  7 failed as expected | ||||
| assertions: 2127 | 1971 passed | 129 failed | 27 failed as expected | ||||
| test cases:  376 |  299 passed |  70 failed |  7 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: | ||||
|   "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 | ||||
| ------------------------------------------------------------------------------- | ||||
| @@ -14962,6 +14991,60 @@ Tricky.tests.cpp:<line number> | ||||
|  | ||||
| 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 | ||||
| ------------------------------------------------------------------------------- | ||||
| @@ -17144,6 +17227,6 @@ Misc.tests.cpp:<line number> | ||||
| Misc.tests.cpp:<line number>: PASSED: | ||||
|  | ||||
| =============================================================================== | ||||
| test cases:  374 |  281 passed |  86 failed |  7 failed as expected | ||||
| assertions: 2144 | 1971 passed | 146 failed | 27 failed as expected | ||||
| test cases:  376 |  283 passed |  86 failed |  7 failed as expected | ||||
| assertions: 2159 | 1986 passed | 146 failed | 27 failed as expected | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <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> | ||||
|       <property name="random-seed" value="1"/> | ||||
|       <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/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::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 MatchAnyOfGeneric 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/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="is_unary_function" time="{duration}" status="run"/> | ||||
|     <testcase classname="<exe-name>.global" name="just failure" time="{duration}" status="run"> | ||||
|       <failure type="FAIL"> | ||||
| FAILED: | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
| > | ||||
|   <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::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 path="tests/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp"> | ||||
|     <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 | ||||
| # Clara::Arg supports single-arg parse the way Opt does | ||||
| 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 | ||||
| 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 | ||||
| @@ -3786,6 +3792,30 @@ ok {test-number} - | ||||
| # even more nested SECTION tests | ||||
| ok {test-number} - | ||||
| 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 | ||||
| not ok {test-number} - explicitly with 1 message: 'Previous info should not be seen' | ||||
| # just failure after unscoped info | ||||
| @@ -4290,5 +4320,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 | ||||
| ok {test-number} - | ||||
| # xmlentitycheck | ||||
| 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[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[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[testFinished name='Combining MatchAllOfGeneric does not nest' duration="{duration}"] | ||||
| ##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'] | ||||
| loose text artifact | ||||
| ##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'] | ||||
| Message.tests.cpp:<line number>|nexplicit failure with message:|n  "Previous info should not be seen"'] | ||||
| ##teamcity[testFinished name='just failure' duration="{duration}"] | ||||
|   | ||||
| @@ -3156,6 +3156,39 @@ Nor would this | ||||
|     </Expression> | ||||
|     <OverallResult success="true"/> | ||||
|   </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" > | ||||
|     <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > | ||||
|       <Original> | ||||
| @@ -17633,6 +17666,9 @@ There is no extra whitespace here | ||||
| loose text artifact | ||||
|     <OverallResult success="false"/> | ||||
|   </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" > | ||||
|     <Failure filename="tests/<exe-name>/UsageTests/Message.tests.cpp" > | ||||
|       Previous info should not be seen | ||||
| @@ -20147,6 +20183,6 @@ loose text artifact | ||||
|     </Section> | ||||
|     <OverallResult success="true"/> | ||||
|   </TestCase> | ||||
|   <OverallResults successes="1971" failures="146" expectedFailures="27"/> | ||||
|   <OverallResultsCases successes="281" failures="86" expectedFailures="7"/> | ||||
|   <OverallResults successes="1986" failures="146" expectedFailures="27"/> | ||||
|   <OverallResultsCases successes="283" failures="86" expectedFailures="7"/> | ||||
| </Catch2TestRun> | ||||
|   | ||||
| @@ -11,6 +11,35 @@ | ||||
|  | ||||
| #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]") { | ||||
|     std::string name; | ||||
|     auto p = Catch::Clara::Arg(name, "just one arg"); | ||||
| @@ -20,3 +49,25 @@ TEST_CASE("Clara::Arg supports single-arg parse the way Opt does", "[clara][arg] | ||||
|     p.parse( Catch::Clara::Args{ "UnitTest", "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" }); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský