From 17fe5eaa5c0c28e7a6a197420f0f16b085a8fa9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 1 Aug 2025 23:00:30 +0200 Subject: [PATCH] Fix StringMaker for time_point with non-default duration Fixes #2685 --- src/catch2/catch_tostring.hpp | 8 +++++--- .../SelfTest/Baselines/automake.sw.approved.txt | 1 + .../Baselines/automake.sw.multi.approved.txt | 1 + .../SelfTest/Baselines/compact.sw.approved.txt | 7 +++++-- .../Baselines/compact.sw.multi.approved.txt | 7 +++++-- .../SelfTest/Baselines/console.std.approved.txt | 4 ++-- .../SelfTest/Baselines/console.sw.approved.txt | 17 +++++++++++++++-- .../Baselines/console.sw.multi.approved.txt | 17 +++++++++++++++-- tests/SelfTest/Baselines/junit.sw.approved.txt | 3 ++- .../Baselines/junit.sw.multi.approved.txt | 3 ++- .../Baselines/sonarqube.sw.approved.txt | 1 + .../Baselines/sonarqube.sw.multi.approved.txt | 1 + tests/SelfTest/Baselines/tap.sw.approved.txt | 4 +++- .../Baselines/tap.sw.multi.approved.txt | 4 +++- .../SelfTest/Baselines/teamcity.sw.approved.txt | 2 ++ .../Baselines/teamcity.sw.multi.approved.txt | 2 ++ tests/SelfTest/Baselines/xml.sw.approved.txt | 17 +++++++++++++++-- .../Baselines/xml.sw.multi.approved.txt | 17 +++++++++++++++-- .../UsageTests/ToStringChrono.tests.cpp | 6 ++++++ 19 files changed, 101 insertions(+), 21 deletions(-) diff --git a/src/catch2/catch_tostring.hpp b/src/catch2/catch_tostring.hpp index 70741663..ab91c618 100644 --- a/src/catch2/catch_tostring.hpp +++ b/src/catch2/catch_tostring.hpp @@ -626,17 +626,19 @@ struct ratio_string { template struct StringMaker> { static std::string convert(std::chrono::time_point const& time_point) { - auto converted = std::chrono::system_clock::to_time_t(time_point); + const auto systemish = std::chrono::time_point_cast< + std::chrono::system_clock::duration>( time_point ); + const auto as_time_t = std::chrono::system_clock::to_time_t( systemish ); #ifdef _MSC_VER std::tm timeInfo = {}; - const auto err = gmtime_s(&timeInfo, &converted); + const auto err = gmtime_s( &timeInfo, &as_time_t ); if ( err ) { return "gmtime from provided timepoint has failed. This " "happens e.g. with pre-1970 dates using Microsoft libc"; } #else - std::tm* timeInfo = std::gmtime(&converted); + std::tm* timeInfo = std::gmtime( &as_time_t ); #endif auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index f04cd867..084a3d26 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -412,6 +412,7 @@ b1! :test-result: PASS stringify( vectors ) :test-result: PASS stringify( vectors ) :test-result: PASS strlen3 +:test-result: PASS system_clock timepoint with non-default duration :test-result: PASS tables :test-result: PASS tags with dots in later positions are not parsed as hidden :test-result: SKIP tests can be skipped dynamically at runtime diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index 7da3c913..1c6b7d99 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -401,6 +401,7 @@ :test-result: PASS stringify( vectors ) :test-result: PASS stringify( vectors ) :test-result: PASS strlen3 +:test-result: PASS system_clock timepoint with non-default duration :test-result: PASS tables :test-result: PASS tags with dots in later positions are not parsed as hidden :test-result: SKIP tests can be skipped dynamically at runtime diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index fbf249c1..fe5ee317 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -2766,6 +2766,9 @@ Generators.tests.cpp:: passed: data.str.size() == data.len for: 3 = Generators.tests.cpp:: passed: data.str.size() == data.len for: 3 == 3 Generators.tests.cpp:: passed: data.str.size() == data.len for: 5 == 5 Generators.tests.cpp:: passed: data.str.size() == data.len for: 4 == 4 +ToStringChrono.tests.cpp:: passed: tp1 == tp2 for: {iso8601-timestamp} +== +{iso8601-timestamp} Generators.tests.cpp:: passed: strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 5 == 5 Generators.tests.cpp:: passed: strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 6 == 6 Generators.tests.cpp:: passed: strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 5 == 5 @@ -2871,7 +2874,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected +test cases: 433 | 315 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2291 | 2093 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index f0e75afa..4c8d923b 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -2755,6 +2755,9 @@ Generators.tests.cpp:: passed: data.str.size() == data.len for: 3 = Generators.tests.cpp:: passed: data.str.size() == data.len for: 3 == 3 Generators.tests.cpp:: passed: data.str.size() == data.len for: 5 == 5 Generators.tests.cpp:: passed: data.str.size() == data.len for: 4 == 4 +ToStringChrono.tests.cpp:: passed: tp1 == tp2 for: {iso8601-timestamp} +== +{iso8601-timestamp} Generators.tests.cpp:: passed: strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 5 == 5 Generators.tests.cpp:: passed: strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 6 == 6 Generators.tests.cpp:: passed: strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 5 == 5 @@ -2860,7 +2863,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected +test cases: 433 | 315 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2291 | 2093 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 92d58aaa..fc820cc5 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1719,6 +1719,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 432 | 332 passed | 76 failed | 7 skipped | 17 failed as expected -assertions: 2269 | 2092 passed | 136 failed | 41 failed as expected +test cases: 433 | 333 passed | 76 failed | 7 skipped | 17 failed as expected +assertions: 2270 | 2093 passed | 136 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 0bc35756..8e129486 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -18409,6 +18409,19 @@ Generators.tests.cpp:: PASSED: with expansion: 4 == 4 +------------------------------------------------------------------------------- +system_clock timepoint with non-default duration +------------------------------------------------------------------------------- +ToStringChrono.tests.cpp: +............................................................................... + +ToStringChrono.tests.cpp:: PASSED: + CHECK( tp1 == tp2 ) +with expansion: + {iso8601-timestamp} + == + {iso8601-timestamp} + ------------------------------------------------------------------------------- tables ------------------------------------------------------------------------------- @@ -19200,6 +19213,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected +test cases: 433 | 315 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2291 | 2093 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 6d853f1b..908b7a66 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -18398,6 +18398,19 @@ Generators.tests.cpp:: PASSED: with expansion: 4 == 4 +------------------------------------------------------------------------------- +system_clock timepoint with non-default duration +------------------------------------------------------------------------------- +ToStringChrono.tests.cpp: +............................................................................... + +ToStringChrono.tests.cpp:: PASSED: + CHECK( tp1 == tp2 ) +with expansion: + {iso8601-timestamp} + == + {iso8601-timestamp} + ------------------------------------------------------------------------------- tables ------------------------------------------------------------------------------- @@ -19189,6 +19202,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 432 | 314 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2290 | 2092 passed | 157 failed | 41 failed as expected +test cases: 433 | 315 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2291 | 2093 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index 181c0809..f9dba650 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -2333,6 +2333,7 @@ at Message.tests.cpp: + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index 8d90d575..e064e606 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -2332,6 +2332,7 @@ at Message.tests.cpp: + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index fcc57d42..066ec161 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -2298,6 +2298,7 @@ at Skip.tests.cpp: + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index 9afa17f1..3358f32b 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -2297,6 +2297,7 @@ at Skip.tests.cpp: + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index bd797da8..51d649a0 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -4411,6 +4411,8 @@ ok {test-number} - data.str.size() == data.len for: 3 == 3 ok {test-number} - data.str.size() == data.len for: 5 == 5 # strlen3 ok {test-number} - data.str.size() == data.len for: 4 == 4 +# system_clock timepoint with non-default duration +ok {test-number} - tp1 == tp2 for: {iso8601-timestamp} == {iso8601-timestamp} # tables ok {test-number} - strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 5 == 5 # tables @@ -4601,5 +4603,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2302 +1..2303 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 9f2ec42c..cd08187b 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -4400,6 +4400,8 @@ ok {test-number} - data.str.size() == data.len for: 3 == 3 ok {test-number} - data.str.size() == data.len for: 5 == 5 # strlen3 ok {test-number} - data.str.size() == data.len for: 4 == 4 +# system_clock timepoint with non-default duration +ok {test-number} - tp1 == tp2 for: {iso8601-timestamp} == {iso8601-timestamp} # tables ok {test-number} - strlen(std::get<0>(data)) == static_cast(std::get<1>(data)) for: 5 == 5 # tables @@ -4590,5 +4592,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2302 +1..2303 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 39bceb12..e65e0719 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -999,6 +999,8 @@ loose text artifact ##teamcity[testFinished name='stringify( vectors )' duration="{duration}"] ##teamcity[testStarted name='strlen3'] ##teamcity[testFinished name='strlen3' duration="{duration}"] +##teamcity[testStarted name='system_clock timepoint with non-default duration'] +##teamcity[testFinished name='system_clock timepoint with non-default duration' duration="{duration}"] ##teamcity[testStarted name='tables'] ##teamcity[testFinished name='tables' duration="{duration}"] ##teamcity[testStarted name='tags with dots in later positions are not parsed as hidden'] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index e9b5fee9..41aab3c2 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -998,6 +998,8 @@ ##teamcity[testFinished name='stringify( vectors )' duration="{duration}"] ##teamcity[testStarted name='strlen3'] ##teamcity[testFinished name='strlen3' duration="{duration}"] +##teamcity[testStarted name='system_clock timepoint with non-default duration'] +##teamcity[testFinished name='system_clock timepoint with non-default duration' duration="{duration}"] ##teamcity[testStarted name='tables'] ##teamcity[testFinished name='tables' duration="{duration}"] ##teamcity[testStarted name='tags with dots in later positions are not parsed as hidden'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index 44cd5fc3..d4a0ce02 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -21324,6 +21324,19 @@ Approx( -1.95996398454005449 ) + + + + tp1 == tp2 + + + {iso8601-timestamp} +== +{iso8601-timestamp} + + + + @@ -22201,6 +22214,6 @@ Approx( -1.95996398454005449 ) - - + + diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index 6e4a78b7..72c8ff9f 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -21323,6 +21323,19 @@ Approx( -1.95996398454005449 ) + + + + tp1 == tp2 + + + {iso8601-timestamp} +== +{iso8601-timestamp} + + + + @@ -22200,6 +22213,6 @@ Approx( -1.95996398454005449 ) - - + + diff --git a/tests/SelfTest/UsageTests/ToStringChrono.tests.cpp b/tests/SelfTest/UsageTests/ToStringChrono.tests.cpp index 744b899b..931b4b22 100644 --- a/tests/SelfTest/UsageTests/ToStringChrono.tests.cpp +++ b/tests/SelfTest/UsageTests/ToStringChrono.tests.cpp @@ -49,3 +49,9 @@ TEST_CASE("Stringifying std::chrono::time_point", "[toString][chrono][!no auto later2 = now2 + std::chrono::minutes(2); REQUIRE(now2 != later2); } + +TEST_CASE( "system_clock timepoint with non-default duration", "[toString][chrono]" ) { + std::chrono::time_point + tp1, tp2; + CHECK( tp1 == tp2 ); +}