Add parseUInt utility function

There is an increasing number of places where Catch2 wants to parse
strings into numbers, but being stuck in C++14 world, we do not
have good stdlib facilities to do this (`strtoul` and `stoul`
are both bad).
This commit is contained in:
Martin Hořeňovský 2022-10-20 15:06:26 +02:00
parent 38d926090a
commit d7341b5dc1
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
25 changed files with 550 additions and 14 deletions

View File

@ -81,6 +81,7 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_istream.hpp ${SOURCES_DIR}/internal/catch_istream.hpp
${SOURCES_DIR}/internal/catch_unique_name.hpp ${SOURCES_DIR}/internal/catch_unique_name.hpp
${SOURCES_DIR}/internal/catch_sharding.hpp ${SOURCES_DIR}/internal/catch_sharding.hpp
${SOURCES_DIR}/internal/catch_parse_numbers.hpp
${SOURCES_DIR}/generators/catch_generator_exception.hpp ${SOURCES_DIR}/generators/catch_generator_exception.hpp
${SOURCES_DIR}/generators/catch_generators.hpp ${SOURCES_DIR}/generators/catch_generators.hpp
${SOURCES_DIR}/generators/catch_generators_adapters.hpp ${SOURCES_DIR}/generators/catch_generators_adapters.hpp
@ -184,6 +185,7 @@ set(IMPL_SOURCES
${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp
${SOURCES_DIR}/internal/catch_floating_point_helpers.cpp ${SOURCES_DIR}/internal/catch_floating_point_helpers.cpp
${SOURCES_DIR}/internal/catch_istream.cpp ${SOURCES_DIR}/internal/catch_istream.cpp
${SOURCES_DIR}/internal/catch_parse_numbers.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.cpp
${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_reporter.cpp
${SOURCES_DIR}/internal/catch_list.cpp ${SOURCES_DIR}/internal/catch_list.cpp

View File

@ -78,6 +78,7 @@
#include <catch2/internal/catch_noncopyable.hpp> #include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/internal/catch_optional.hpp> #include <catch2/internal/catch_optional.hpp>
#include <catch2/internal/catch_output_redirect.hpp> #include <catch2/internal/catch_output_redirect.hpp>
#include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_platform.hpp> #include <catch2/internal/catch_platform.hpp>
#include <catch2/internal/catch_polyfills.hpp> #include <catch2/internal/catch_polyfills.hpp>
#include <catch2/internal/catch_preprocessor.hpp> #include <catch2/internal/catch_preprocessor.hpp>

View File

@ -0,0 +1,49 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <limits>
namespace Catch {
Optional<unsigned int> parseUInt(std::string const& input, int base) {
auto trimmed = trim( input );
// std::stoull is annoying and accepts numbers starting with '-',
// it just negates them into unsigned int
if ( trimmed.empty() || trimmed[0] == '-' ) {
return {};
}
CATCH_TRY {
size_t pos = 0;
const auto ret = std::stoull( trimmed, &pos, base );
// We did not consume the whole input, so there is an issue
// This can be bunch of different stuff, like multiple numbers
// in the input, or invalid digits/characters and so on. Either
// way, we do not want to return the partially parsed result.
if ( pos != trimmed.size() ) {
return {};
}
// Too large
if ( ret > std::numeric_limits<unsigned int>::max() ) {
return {};
}
return static_cast<unsigned int>(ret);
} CATCH_CATCH_ANON( std::exception const& ) {
// There was a larger issue with the input, e.g. the parsed
// number would be too large to fit within ull.
return {};
}
}
} // namespace Catch

View File

@ -0,0 +1,26 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
#define CATCH_PARSE_NUMBERS_HPP_INCLUDED
#include <catch2/internal/catch_optional.hpp>
#include <string>
namespace Catch {
/**
* Parses unsigned int from the input, using provided base
*
* Effectively a wrapper around std::stoul but with better error checking
* e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
*/
Optional<unsigned int> parseUInt(std::string const& input, int base = 10);
}
#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED

View File

@ -100,6 +100,7 @@ internal_headers = [
'internal/catch_noncopyable.hpp', 'internal/catch_noncopyable.hpp',
'internal/catch_optional.hpp', 'internal/catch_optional.hpp',
'internal/catch_output_redirect.hpp', 'internal/catch_output_redirect.hpp',
'internal/catch_parse_numbers.hpp',
'internal/catch_platform.hpp', 'internal/catch_platform.hpp',
'internal/catch_polyfills.hpp', 'internal/catch_polyfills.hpp',
'internal/catch_preprocessor.hpp', 'internal/catch_preprocessor.hpp',
@ -207,6 +208,7 @@ internal_sources = files(
'internal/catch_list.cpp', 'internal/catch_list.cpp',
'internal/catch_message_info.cpp', 'internal/catch_message_info.cpp',
'internal/catch_output_redirect.cpp', 'internal/catch_output_redirect.cpp',
'internal/catch_parse_numbers.cpp',
'internal/catch_polyfills.cpp', 'internal/catch_polyfills.cpp',
'internal/catch_random_number_generator.cpp', 'internal/catch_random_number_generator.cpp',
'internal/catch_random_seed_generation.cpp', 'internal/catch_random_seed_generation.cpp',

View File

@ -85,6 +85,7 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/IntrospectiveTests/FloatingPoint.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/FloatingPoint.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Parse.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/RandomNumberGeneration.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/RandomNumberGeneration.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Reporters.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/Reporters.tests.cpp

View File

@ -189,6 +189,7 @@ Nor would this
: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 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 Parse uints
:test-result: PASS Parsed tags are matched case insensitive :test-result: PASS Parsed tags are matched case insensitive
:test-result: PASS Parsing sharding-related cli flags :test-result: PASS Parsing sharding-related cli flags
:test-result: PASS Parsing tags with non-alphabetical characters is pass-through :test-result: PASS Parsing tags with non-alphabetical characters is pass-through

View File

@ -187,6 +187,7 @@
: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 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 Parse uints
:test-result: PASS Parsed tags are matched case insensitive :test-result: PASS Parsed tags are matched case insensitive
:test-result: PASS Parsing sharding-related cli flags :test-result: PASS Parsing sharding-related cli flags
:test-result: PASS Parsing tags with non-alphabetical characters is pass-through :test-result: PASS Parsing tags with non-alphabetical characters is pass-through

View File

@ -1270,6 +1270,17 @@ CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("hidden an
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true CmdLine.tests.cpp:<line number>: passed: spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true
Parse.tests.cpp:<line number>: passed: parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "!!KJHF*#" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "-1" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "4294967296" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "42949672964294967296429496729642949672964294967296" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "2 4" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "0x<hex digits>", 10 )) for: !{?}
TestSpecParser.tests.cpp:<line number>: passed: spec.hasFilters() for: true TestSpecParser.tests.cpp:<line number>: passed: spec.hasFilters() for: true
TestSpecParser.tests.cpp:<line number>: passed: spec.getInvalidSpecs().empty() for: true TestSpecParser.tests.cpp:<line number>: passed: spec.getInvalidSpecs().empty() for: true
TestSpecParser.tests.cpp:<line number>: passed: spec.matches( testCase ) for: true TestSpecParser.tests.cpp:<line number>: passed: spec.matches( testCase ) for: true

View File

@ -1268,6 +1268,17 @@ CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("hidden an
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false CmdLine.tests.cpp:<line number>: passed: !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true CmdLine.tests.cpp:<line number>: passed: spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true
Parse.tests.cpp:<line number>: passed: parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "!!KJHF*#" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "-1" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "4294967296" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "42949672964294967296429496729642949672964294967296" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "2 4" )) for: !{?}
Parse.tests.cpp:<line number>: passed: !(parseUInt( "0x<hex digits>", 10 )) for: !{?}
TestSpecParser.tests.cpp:<line number>: passed: spec.hasFilters() for: true TestSpecParser.tests.cpp:<line number>: passed: spec.hasFilters() for: true
TestSpecParser.tests.cpp:<line number>: passed: spec.getInvalidSpecs().empty() for: true TestSpecParser.tests.cpp:<line number>: passed: spec.getInvalidSpecs().empty() for: true
TestSpecParser.tests.cpp:<line number>: passed: spec.matches( testCase ) for: true TestSpecParser.tests.cpp:<line number>: passed: spec.matches( testCase ) for: true

View File

@ -1394,6 +1394,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 394 | 318 passed | 69 failed | 7 failed as expected test cases: 395 | 319 passed | 69 failed | 7 failed as expected
assertions: 2284 | 2129 passed | 128 failed | 27 failed as expected assertions: 2295 | 2140 passed | 128 failed | 27 failed as expected

View File

@ -9055,6 +9055,75 @@ CmdLine.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
Parse uints
proper inputs
-------------------------------------------------------------------------------
Parse.tests.cpp:<line number>
...............................................................................
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0" ) == Optional<unsigned int>{ 0 } )
with expansion:
{?} == {?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "100" ) == Optional<unsigned int>{ 100 } )
with expansion:
{?} == {?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } )
with expansion:
{?} == {?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } )
with expansion:
{?} == {?}
-------------------------------------------------------------------------------
Parse uints
Bad inputs
-------------------------------------------------------------------------------
Parse.tests.cpp:<line number>
...............................................................................
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "!!KJHF*#" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "-1" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "4294967296" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "42949672964294967296429496729642949672964294967296" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "2 4" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "0x<hex digits>", 10 ) )
with expansion:
!{?}
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Parsed tags are matched case insensitive Parsed tags are matched case insensitive
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -18450,6 +18519,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 394 | 304 passed | 83 failed | 7 failed as expected test cases: 395 | 305 passed | 83 failed | 7 failed as expected
assertions: 2299 | 2129 passed | 143 failed | 27 failed as expected assertions: 2310 | 2140 passed | 143 failed | 27 failed as expected

View File

@ -9053,6 +9053,75 @@ CmdLine.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
Parse uints
proper inputs
-------------------------------------------------------------------------------
Parse.tests.cpp:<line number>
...............................................................................
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0" ) == Optional<unsigned int>{ 0 } )
with expansion:
{?} == {?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "100" ) == Optional<unsigned int>{ 100 } )
with expansion:
{?} == {?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } )
with expansion:
{?} == {?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE( parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } )
with expansion:
{?} == {?}
-------------------------------------------------------------------------------
Parse uints
Bad inputs
-------------------------------------------------------------------------------
Parse.tests.cpp:<line number>
...............................................................................
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "!!KJHF*#" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "-1" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "4294967296" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "42949672964294967296429496729642949672964294967296" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "2 4" ) )
with expansion:
!{?}
Parse.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( parseUInt( "0x<hex digits>", 10 ) )
with expansion:
!{?}
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Parsed tags are matched case insensitive Parsed tags are matched case insensitive
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -18442,6 +18511,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 394 | 304 passed | 83 failed | 7 failed as expected test cases: 395 | 305 passed | 83 failed | 7 failed as expected
assertions: 2299 | 2129 passed | 143 failed | 27 failed as expected assertions: 2310 | 2140 passed | 143 failed | 27 failed as expected

View File

@ -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="126" tests="2299" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="126" tests="2310" 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] *"/>
@ -1083,6 +1083,8 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test name" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test name" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags are split apart when parsing" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags are split apart when parsing" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags also properly handle exclusion" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags also properly handle exclusion" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse uints/proper inputs" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse uints/Bad inputs" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parsed tags are matched case insensitive" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parsed tags are matched case insensitive" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/shard-count" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/shard-count" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/Negative shard count reports error" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/Negative shard count reports error" time="{duration}" status="run"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuites> <testsuites>
<testsuite name="<exe-name>" errors="17" failures="126" tests="2299" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="126" tests="2310" 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] *"/>
@ -1082,6 +1082,8 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test name" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/Leading and trailing spaces in test name" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags are split apart when parsing" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags are split apart when parsing" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags also properly handle exclusion" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parse test names and tags/Shortened hide tags also properly handle exclusion" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse uints/proper inputs" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parse uints/Bad inputs" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parsed tags are matched case insensitive" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parsed tags are matched case insensitive" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/shard-count" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/shard-count" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/Negative shard count reports error" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Parsing sharding-related cli flags/Negative shard count reports error" time="{duration}" status="run"/>

View File

@ -157,6 +157,10 @@
<testCase name="warmup" duration="{duration}"/> <testCase name="warmup" duration="{duration}"/>
<testCase name="weighted_average_quantile" duration="{duration}"/> <testCase name="weighted_average_quantile" duration="{duration}"/>
</file> </file>
<file path="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp">
<testCase name="Parse uints/proper inputs" duration="{duration}"/>
<testCase name="Parse uints/Bad inputs" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp"> <file path="tests/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp">
<testCase name="#1938 - GENERATE after a section/A" duration="{duration}"/> <testCase name="#1938 - GENERATE after a section/A" duration="{duration}"/>
<testCase name="#1938 - GENERATE after a section/B" duration="{duration}"/> <testCase name="#1938 - GENERATE after a section/B" duration="{duration}"/>

View File

@ -156,6 +156,10 @@
<testCase name="warmup" duration="{duration}"/> <testCase name="warmup" duration="{duration}"/>
<testCase name="weighted_average_quantile" duration="{duration}"/> <testCase name="weighted_average_quantile" duration="{duration}"/>
</file> </file>
<file path="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp">
<testCase name="Parse uints/proper inputs" duration="{duration}"/>
<testCase name="Parse uints/Bad inputs" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp"> <file path="tests/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp">
<testCase name="#1938 - GENERATE after a section/A" duration="{duration}"/> <testCase name="#1938 - GENERATE after a section/A" duration="{duration}"/>
<testCase name="#1938 - GENERATE after a section/B" duration="{duration}"/> <testCase name="#1938 - GENERATE after a section/B" duration="{duration}"/>

View File

@ -2383,6 +2383,28 @@ ok {test-number} - !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !fal
ok {test-number} - !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false ok {test-number} - !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false
# Parse test names and tags # Parse test names and tags
ok {test-number} - spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true ok {test-number} - spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true
# Parse uints
ok {test-number} - parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?}
# Parse uints
ok {test-number} - parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?}
# Parse uints
ok {test-number} - parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?}
# Parse uints
ok {test-number} - parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?}
# Parse uints
ok {test-number} - !(parseUInt( "" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "!!KJHF*#" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "-1" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "4294967296" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "42949672964294967296429496729642949672964294967296" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "2 4" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "0x<hex digits>", 10 )) for: !{?}
# Parsed tags are matched case insensitive # Parsed tags are matched case insensitive
ok {test-number} - spec.hasFilters() for: true ok {test-number} - spec.hasFilters() for: true
# Parsed tags are matched case insensitive # Parsed tags are matched case insensitive
@ -4601,5 +4623,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..2299 1..2310

View File

@ -2381,6 +2381,28 @@ ok {test-number} - !(spec.matches(*fakeTestCase("only foo", "[foo]"))) for: !fal
ok {test-number} - !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false ok {test-number} - !(spec.matches(*fakeTestCase("only hidden", "[.]"))) for: !false
# Parse test names and tags # Parse test names and tags
ok {test-number} - spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true ok {test-number} - spec.matches(*fakeTestCase("neither foo nor hidden", "[bar]")) for: true
# Parse uints
ok {test-number} - parseUInt( "0" ) == Optional<unsigned int>{ 0 } for: {?} == {?}
# Parse uints
ok {test-number} - parseUInt( "100" ) == Optional<unsigned int>{ 100 } for: {?} == {?}
# Parse uints
ok {test-number} - parseUInt( "4294967295" ) == Optional<unsigned int>{ 4294967295 } for: {?} == {?}
# Parse uints
ok {test-number} - parseUInt( "0x<hex digits>", 16 ) == Optional<unsigned int>{ 255 } for: {?} == {?}
# Parse uints
ok {test-number} - !(parseUInt( "" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "!!KJHF*#" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "-1" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "4294967296" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "42949672964294967296429496729642949672964294967296" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "2 4" )) for: !{?}
# Parse uints
ok {test-number} - !(parseUInt( "0x<hex digits>", 10 )) for: !{?}
# Parsed tags are matched case insensitive # Parsed tags are matched case insensitive
ok {test-number} - spec.hasFilters() for: true ok {test-number} - spec.hasFilters() for: true
# Parsed tags are matched case insensitive # Parsed tags are matched case insensitive
@ -4593,5 +4615,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..2299 1..2310

View File

@ -483,6 +483,8 @@ Message.tests.cpp:<line number>|nexplicit failure with message:|n "Message from
##teamcity[testFinished name='Overloaded comma or address-of operators are not used' duration="{duration}"] ##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='Parse uints']
##teamcity[testFinished name='Parse uints' duration="{duration}"]
##teamcity[testStarted name='Parsed tags are matched case insensitive'] ##teamcity[testStarted name='Parsed tags are matched case insensitive']
##teamcity[testFinished name='Parsed tags are matched case insensitive' duration="{duration}"] ##teamcity[testFinished name='Parsed tags are matched case insensitive' duration="{duration}"]
##teamcity[testStarted name='Parsing sharding-related cli flags'] ##teamcity[testStarted name='Parsing sharding-related cli flags']

View File

@ -483,6 +483,8 @@ Message.tests.cpp:<line number>|nexplicit failure with message:|n "Message from
##teamcity[testFinished name='Overloaded comma or address-of operators are not used' duration="{duration}"] ##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='Parse uints']
##teamcity[testFinished name='Parse uints' duration="{duration}"]
##teamcity[testStarted name='Parsed tags are matched case insensitive'] ##teamcity[testStarted name='Parsed tags are matched case insensitive']
##teamcity[testFinished name='Parsed tags are matched case insensitive' duration="{duration}"] ##teamcity[testFinished name='Parsed tags are matched case insensitive' duration="{duration}"]
##teamcity[testStarted name='Parsing sharding-related cli flags'] ##teamcity[testStarted name='Parsing sharding-related cli flags']

View File

@ -11005,6 +11005,103 @@ C
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Parse uints" tags="[parse-numbers]" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Section name="proper inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "0" ) == Optional&lt;unsigned int>{ 0 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "100" ) == Optional&lt;unsigned int>{ 100 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "4294967295" ) == Optional&lt;unsigned int>{ 4294967295 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "0x<hex digits>", 16 ) == Optional&lt;unsigned int>{ 255 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Bad inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "!!KJHF*#" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "-1" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "4294967296" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "42949672964294967296429496729642949672964294967296" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "2 4" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "0x<hex digits>", 10 ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<OverallResults successes="7" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Parsed tags are matched case insensitive" tags="[test-spec][test-spec-parser]" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" > <TestCase name="Parsed tags are matched case insensitive" tags="[test-spec][test-spec-parser]" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" >
<Original> <Original>
@ -21702,6 +21799,6 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="2129" failures="143" expectedFailures="27"/> <OverallResults successes="2140" failures="143" expectedFailures="27"/>
<OverallResultsCases successes="304" failures="83" expectedFailures="7"/> <OverallResultsCases successes="305" failures="83" expectedFailures="7"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -11005,6 +11005,103 @@ C
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Parse uints" tags="[parse-numbers]" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Section name="proper inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "0" ) == Optional&lt;unsigned int>{ 0 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "100" ) == Optional&lt;unsigned int>{ 100 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "4294967295" ) == Optional&lt;unsigned int>{ 4294967295 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
parseUInt( "0x<hex digits>", 16 ) == Optional&lt;unsigned int>{ 255 }
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Bad inputs" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "!!KJHF*#" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "-1" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "4294967296" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "42949672964294967296429496729642949672964294967296" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "2 4" ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp" >
<Original>
!(parseUInt( "0x<hex digits>", 10 ))
</Original>
<Expanded>
!{?}
</Expanded>
</Expression>
<OverallResults successes="7" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Parsed tags are matched case insensitive" tags="[test-spec][test-spec-parser]" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" > <TestCase name="Parsed tags are matched case insensitive" tags="[test-spec][test-spec-parser]" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/TestSpecParser.tests.cpp" >
<Original> <Original>
@ -21701,6 +21798,6 @@ There is no extra whitespace here
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="2129" failures="143" expectedFailures="27"/> <OverallResults successes="2140" failures="143" expectedFailures="27"/>
<OverallResultsCases successes="304" failures="83" expectedFailures="7"/> <OverallResultsCases successes="305" failures="83" expectedFailures="7"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -0,0 +1,38 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_parse_numbers.hpp>
TEST_CASE("Parse uints", "[parse-numbers]") {
using Catch::parseUInt;
using Catch::Optional;
SECTION("proper inputs") {
REQUIRE( parseUInt( "0" ) == Optional<unsigned int>{ 0 } );
REQUIRE( parseUInt( "100" ) == Optional<unsigned int>{ 100 } );
REQUIRE( parseUInt( "4294967295" ) ==
Optional<unsigned int>{ 4294967295 } );
REQUIRE( parseUInt( "0xFF", 16 ) == Optional<unsigned int>{ 255 } );
}
SECTION( "Bad inputs" ) {
// empty
REQUIRE_FALSE( parseUInt( "" ) );
// random noise
REQUIRE_FALSE( parseUInt( "!!KJHF*#" ) );
// negative
REQUIRE_FALSE( parseUInt( "-1" ) );
// too large
REQUIRE_FALSE( parseUInt( "4294967296" ) );
REQUIRE_FALSE( parseUInt( "42949672964294967296429496729642949672964294967296" ) );
REQUIRE_FALSE( parseUInt( "2 4" ) );
// hex with base 10
REQUIRE_FALSE( parseUInt( "0xFF", 10 ) );
}
}

View File

@ -16,6 +16,7 @@ self_test_sources = files(
'SelfTest/IntrospectiveTests/FloatingPoint.tests.cpp', 'SelfTest/IntrospectiveTests/FloatingPoint.tests.cpp',
'SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp', 'SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp',
'SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp', 'SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp',
'SelfTest/IntrospectiveTests/Parse.tests.cpp',
'SelfTest/IntrospectiveTests/PartTracker.tests.cpp', 'SelfTest/IntrospectiveTests/PartTracker.tests.cpp',
'SelfTest/IntrospectiveTests/RandomNumberGeneration.tests.cpp', 'SelfTest/IntrospectiveTests/RandomNumberGeneration.tests.cpp',
'SelfTest/IntrospectiveTests/Reporters.tests.cpp', 'SelfTest/IntrospectiveTests/Reporters.tests.cpp',