diff --git a/src/catch2/catch_config.cpp b/src/catch2/catch_config.cpp index 92fcff20..20303c2a 100644 --- a/src/catch2/catch_config.cpp +++ b/src/catch2/catch_config.cpp @@ -72,7 +72,7 @@ namespace Catch { ShowDurations Config::showDurations() const { return m_data.showDurations; } double Config::minDuration() const { return m_data.minDuration; } TestRunOrder Config::runOrder() const { return m_data.runOrder; } - unsigned int Config::rngSeed() const { return m_data.rngSeed; } + unsigned int Config::rngSeed() const { return *m_data.rngSeed; } UseColour Config::useColour() const { return m_data.useColour; } bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } int Config::abortAfter() const { return m_data.abortAfter; } diff --git a/src/catch2/catch_config.hpp b/src/catch2/catch_config.hpp index 7daf61c7..65a50ed8 100644 --- a/src/catch2/catch_config.hpp +++ b/src/catch2/catch_config.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ namespace Catch { bool libIdentify = false; int abortAfter = -1; - unsigned int rngSeed = 0; + Optional rngSeed; bool benchmarkNoAnalysis = false; unsigned int benchmarkSamples = 100; diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index 66e9e482..913c7111 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -170,6 +171,10 @@ namespace Catch { if( m_startupExceptions ) return 1; + if (!m_configData.rngSeed) { + m_configData.rngSeed = static_cast(std::time(nullptr)); + } + auto result = m_cli.parse( Clara::Args( argc, argv ) ); if( !result ) { config(); @@ -187,6 +192,7 @@ namespace Catch { showHelp(); if( m_configData.libIdentify ) libIdentify(); + m_config.reset(); return 0; } @@ -256,6 +262,7 @@ namespace Catch { return 0; } + CATCH_TRY { config(); // Force config to be constructed diff --git a/src/catch2/internal/catch_commandline.cpp b/src/catch2/internal/catch_commandline.cpp index 103e7344..e5fdd692 100644 --- a/src/catch2/internal/catch_commandline.cpp +++ b/src/catch2/internal/catch_commandline.cpp @@ -7,6 +7,7 @@ // SPDX-License-Identifier: BSL-1.0 #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include +#include namespace Catch { @@ -71,10 +73,28 @@ namespace Catch { return ParserResult::ok( ParseResultType::Matched ); }; auto const setRngSeed = [&]( std::string const& seed ) { - if( seed != "time" ) - return Clara::Detail::convertInto( seed, config.rngSeed ); - config.rngSeed = static_cast( std::time(nullptr) ); - return ParserResult::ok( ParseResultType::Matched ); + if( seed == "time" ) { + config.rngSeed = static_cast(std::time(nullptr)); + return ParserResult::ok(ParseResultType::Matched); + } + + CATCH_TRY { + std::size_t parsedTo = 0; + unsigned long parsedSeed = std::stoul(seed, &parsedTo, 0); + if (parsedTo != seed.size()) { + return ParserResult::runtimeError("Could not parse '" + seed + "' as seed"); + } + + // TODO: Ideally we could parse unsigned int directly, + // but the stdlib doesn't provide helper for that + // type. After this is refactored to use fixed size + // type, we should check the parsed value is in range + // of the underlying type. + config.rngSeed = static_cast(parsedSeed); + return ParserResult::ok(ParseResultType::Matched); + } CATCH_CATCH_ANON(std::exception const&) { + return ParserResult::runtimeError("Could not parse '" + seed + "' as seed"); + } }; auto const setColourUsage = [&]( std::string const& useColour ) { auto mode = toLower( useColour );