From c267251e709c52cda421e9490c5cbaf62914fa52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 23 Jul 2026 14:26:17 +0200 Subject: [PATCH] Better support for infs and NaNs in JSON writer As the types and values sent into the writer are determined by Catch2, I do not expect to actually need this support, but it is better to have it and not be surprised in the future. --- src/catch2/internal/catch_jsonwriter.cpp | 22 ++++++ src/catch2/internal/catch_jsonwriter.hpp | 8 ++ .../Baselines/automake.sw.approved.txt | 2 + .../Baselines/automake.sw.multi.approved.txt | 2 + .../Baselines/compact.sw.approved.txt | 10 ++- .../Baselines/compact.sw.multi.approved.txt | 10 ++- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 76 ++++++++++++++++++- .../Baselines/console.sw.multi.approved.txt | 76 ++++++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 10 ++- .../Baselines/junit.sw.multi.approved.txt | 10 ++- .../Baselines/sonarqube.sw.approved.txt | 8 ++ .../Baselines/sonarqube.sw.multi.approved.txt | 8 ++ tests/SelfTest/Baselines/tap.sw.approved.txt | 14 +++- .../Baselines/tap.sw.multi.approved.txt | 14 +++- .../Baselines/teamcity.sw.approved.txt | 4 + .../Baselines/teamcity.sw.multi.approved.txt | 4 + tests/SelfTest/Baselines/xml.sw.approved.txt | 76 ++++++++++++++++++- .../Baselines/xml.sw.multi.approved.txt | 76 ++++++++++++++++++- .../IntrospectiveTests/Json.tests.cpp | 25 ++++++ 20 files changed, 441 insertions(+), 18 deletions(-) diff --git a/src/catch2/internal/catch_jsonwriter.cpp b/src/catch2/internal/catch_jsonwriter.cpp index 6a994f11..d5122dbc 100644 --- a/src/catch2/internal/catch_jsonwriter.cpp +++ b/src/catch2/internal/catch_jsonwriter.cpp @@ -7,8 +7,10 @@ // SPDX-License-Identifier: BSL-1.0 #include #include +#include #include +#include #include namespace Catch { @@ -145,10 +147,30 @@ namespace Catch { writeImpl( value, true ); } + void JsonValueWriter::write( float value ) && { + writeFloatingPoint( value ); + } + + void JsonValueWriter::write( double value ) && { + writeFloatingPoint( value ); + } + void JsonValueWriter::write( bool value ) && { writeImpl( value ? "true"_sr : "false"_sr, false ); } + template + void JsonValueWriter::writeFloatingPoint( T value ) { + if ( Catch::isnan( value ) ) { + writeImpl( "NaN"_sr, false ); + } else if ( std::isinf( value ) ) { + writeImpl( value < 0 ? "-Infinity"_sr : "Infinity"_sr, false ); + } else { + m_sstream << value; + writeImpl( m_sstream.str(), false ); + } + } + void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) { if ( quote ) { m_os << '"'; } size_t current_start = 0; diff --git a/src/catch2/internal/catch_jsonwriter.hpp b/src/catch2/internal/catch_jsonwriter.hpp index 8b3d2bc1..c07d7d75 100644 --- a/src/catch2/internal/catch_jsonwriter.hpp +++ b/src/catch2/internal/catch_jsonwriter.hpp @@ -39,11 +39,19 @@ namespace Catch { writeImpl( value, !std::is_arithmetic::value ); } void write( StringRef value ) &&; + void write( float value ) &&; + void write( double value ) &&; void write( bool value ) &&; private: void writeImpl( StringRef value, bool quote ); + // Helper to deal with non-finite floating point values, which + // are not standard JSON, but we use JS/Python/etc. approach of + // emitting `NaN`, `Infinity`, `-Infinity` as number(like). + template + void writeFloatingPoint( T value ); + // Without this SFINAE, this overload is a better match // for `std::string`, `char const*`, `char const[N]` args. // While it would still work, it would cause code bloat diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index b0028998..a25bc52a 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -190,6 +190,8 @@ Nor would this :test-result: PASS Inequality checks that should succeed :test-result: PASS JsonWriter :test-result: PASS JsonWriter escapes characters in strings properly +:test-result: PASS JsonWriter serializes non-finite FP using Python spelling - double +:test-result: PASS JsonWriter serializes non-finite FP using Python spelling - float :test-result: PASS JsonWriter serializes numbers independently of the global locale :test-result: PASS Lambdas in assertions :test-result: PASS Less-than inequalities with different epsilons diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index 9602395a..3f846b7b 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -188,6 +188,8 @@ :test-result: PASS Inequality checks that should succeed :test-result: PASS JsonWriter :test-result: PASS JsonWriter escapes characters in strings properly +:test-result: PASS JsonWriter serializes non-finite FP using Python spelling - double +:test-result: PASS JsonWriter serializes non-finite FP using Python spelling - float :test-result: PASS JsonWriter serializes numbers independently of the global locale :test-result: PASS Lambdas in assertions :test-result: PASS Less-than inequalities with different epsilons diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index d669bce4..7989d276 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -1248,6 +1248,12 @@ Json.tests.cpp:: passed: sstream.str() == "\"\\n\"" for: ""\n"" == Json.tests.cpp:: passed: sstream.str() == "\"\\r\"" for: ""\r"" == ""\r"" Json.tests.cpp:: passed: sstream.str() == "\"\\t\"" for: ""\t"" == ""\t"" Json.tests.cpp:: passed: sstream.str() == "\"\\\\/\\t\\r\\n\"" for: ""\\/\t\r\n"" == ""\\/\t\r\n"" +Json.tests.cpp:: passed: sstream.str() == "NaN" for: "NaN" == "NaN" +Json.tests.cpp:: passed: sstream.str() == "Infinity" for: "Infinity" == "Infinity" +Json.tests.cpp:: passed: sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" +Json.tests.cpp:: passed: sstream.str() == "NaN" for: "NaN" == "NaN" +Json.tests.cpp:: passed: sstream.str() == "Infinity" for: "Infinity" == "Infinity" +Json.tests.cpp:: passed: sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" Json.tests.cpp:: passed: sstream.str(), ContainsSubstring( "\"double\": 1.5," ) && ContainsSubstring( "\"int\": 1234567," ) && ContainsSubstring( "\"bool-1\": true," ) && ContainsSubstring( "\"bool-2\": false," ) && ContainsSubstring( "\"array\": [\n 2.5,\n 1234567\n ]\n}" ) for: "{ "double": 1.5, "int": 1234567, @@ -3014,7 +3020,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: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected +test cases: 454 | 334 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2423 | 2222 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 712b1259..ffe7a2f6 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -1246,6 +1246,12 @@ Json.tests.cpp:: passed: sstream.str() == "\"\\n\"" for: ""\n"" == Json.tests.cpp:: passed: sstream.str() == "\"\\r\"" for: ""\r"" == ""\r"" Json.tests.cpp:: passed: sstream.str() == "\"\\t\"" for: ""\t"" == ""\t"" Json.tests.cpp:: passed: sstream.str() == "\"\\\\/\\t\\r\\n\"" for: ""\\/\t\r\n"" == ""\\/\t\r\n"" +Json.tests.cpp:: passed: sstream.str() == "NaN" for: "NaN" == "NaN" +Json.tests.cpp:: passed: sstream.str() == "Infinity" for: "Infinity" == "Infinity" +Json.tests.cpp:: passed: sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" +Json.tests.cpp:: passed: sstream.str() == "NaN" for: "NaN" == "NaN" +Json.tests.cpp:: passed: sstream.str() == "Infinity" for: "Infinity" == "Infinity" +Json.tests.cpp:: passed: sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" Json.tests.cpp:: passed: sstream.str(), ContainsSubstring( "\"double\": 1.5," ) && ContainsSubstring( "\"int\": 1234567," ) && ContainsSubstring( "\"bool-1\": true," ) && ContainsSubstring( "\"bool-2\": false," ) && ContainsSubstring( "\"array\": [\n 2.5,\n 1234567\n ]\n}" ) for: "{ "double": 1.5, "int": 1234567, @@ -3003,7 +3009,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: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected +test cases: 454 | 334 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2423 | 2222 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index a833734a..344c5b03 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1743,6 +1743,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 452 | 350 passed | 76 failed | 7 skipped | 19 failed as expected -assertions: 2395 | 2216 passed | 136 failed | 43 failed as expected +test cases: 454 | 352 passed | 76 failed | 7 skipped | 19 failed as expected +assertions: 2401 | 2222 passed | 136 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 2de0a3a5..0729823f 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -8219,6 +8219,78 @@ Json.tests.cpp:: PASSED: with expansion: ""\\/\t\r\n"" == ""\\/\t\r\n"" +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - double + NaN +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "NaN" ) +with expansion: + "NaN" == "NaN" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - double + Pos nf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "Infinity" ) +with expansion: + "Infinity" == "Infinity" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - double + Neg inf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "-Infinity" ) +with expansion: + "-Infinity" == "-Infinity" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - float + NaN +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "NaN" ) +with expansion: + "NaN" == "NaN" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - float + Pos nf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "Infinity" ) +with expansion: + "Infinity" == "Infinity" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - float + Neg inf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "-Infinity" ) +with expansion: + "-Infinity" == "-Infinity" + ------------------------------------------------------------------------------- JsonWriter serializes numbers independently of the global locale ------------------------------------------------------------------------------- @@ -20159,6 +20231,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected +test cases: 454 | 334 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2423 | 2222 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 9b6f023c..3db4bfc8 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -8217,6 +8217,78 @@ Json.tests.cpp:: PASSED: with expansion: ""\\/\t\r\n"" == ""\\/\t\r\n"" +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - double + NaN +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "NaN" ) +with expansion: + "NaN" == "NaN" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - double + Pos nf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "Infinity" ) +with expansion: + "Infinity" == "Infinity" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - double + Neg inf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "-Infinity" ) +with expansion: + "-Infinity" == "-Infinity" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - float + NaN +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "NaN" ) +with expansion: + "NaN" == "NaN" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - float + Pos nf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "Infinity" ) +with expansion: + "Infinity" == "Infinity" + +------------------------------------------------------------------------------- +JsonWriter serializes non-finite FP using Python spelling - float + Neg inf +------------------------------------------------------------------------------- +Json.tests.cpp: +............................................................................... + +Json.tests.cpp:: PASSED: + REQUIRE( sstream.str() == "-Infinity" ) +with expansion: + "-Infinity" == "-Infinity" + ------------------------------------------------------------------------------- JsonWriter serializes numbers independently of the global locale ------------------------------------------------------------------------------- @@ -20148,6 +20220,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected +test cases: 454 | 334 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2423 | 2222 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index c84565d5..f58412b6 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -774,6 +774,14 @@ at Condition.tests.cpp: + + + + + + + + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index f4ff03d6..c80e5855 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -773,6 +773,14 @@ at Condition.tests.cpp: + + + + + + + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index dceaca40..17c26f36 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -262,6 +262,14 @@ at AssertionHandler.tests.cpp: + + + + + + + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index 250b45ae..4c113189 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -261,6 +261,14 @@ at AssertionHandler.tests.cpp: + + + + + + + + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 7e9a19d6..4ac7f09f 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -2054,6 +2054,18 @@ ok {test-number} - sstream.str() == "\"\\r\"" for: ""\r"" == ""\r"" ok {test-number} - sstream.str() == "\"\\t\"" for: ""\t"" == ""\t"" # JsonWriter escapes characters in strings properly ok {test-number} - sstream.str() == "\"\\\\/\\t\\r\\n\"" for: ""\\/\t\r\n"" == ""\\/\t\r\n"" +# JsonWriter serializes non-finite FP using Python spelling - double +ok {test-number} - sstream.str() == "NaN" for: "NaN" == "NaN" +# JsonWriter serializes non-finite FP using Python spelling - double +ok {test-number} - sstream.str() == "Infinity" for: "Infinity" == "Infinity" +# JsonWriter serializes non-finite FP using Python spelling - double +ok {test-number} - sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" +# JsonWriter serializes non-finite FP using Python spelling - float +ok {test-number} - sstream.str() == "NaN" for: "NaN" == "NaN" +# JsonWriter serializes non-finite FP using Python spelling - float +ok {test-number} - sstream.str() == "Infinity" for: "Infinity" == "Infinity" +# JsonWriter serializes non-finite FP using Python spelling - float +ok {test-number} - sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" # JsonWriter serializes numbers independently of the global locale ok {test-number} - sstream.str(), ContainsSubstring( "\"double\": 1.5," ) && ContainsSubstring( "\"int\": 1234567," ) && ContainsSubstring( "\"bool-1\": true," ) && ContainsSubstring( "\"bool-2\": false," ) && ContainsSubstring( "\"array\": [\n 2.5,\n 1234567\n ]\n}" ) for: "{ "double": 1.5, "int": 1234567, "bool-1": true, "bool-2": false, "array": [ 2.5, 1234567 ] }" ( contains: ""double": 1.5," and contains: ""int": 1234567," and contains: ""bool-1": true," and contains: ""bool-2": false," and contains: ""array": [ 2.5, 1234567 ] }" ) # Lambdas in assertions @@ -4853,5 +4865,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2429 +1..2435 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index edcb7813..3f1d56aa 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -2052,6 +2052,18 @@ ok {test-number} - sstream.str() == "\"\\r\"" for: ""\r"" == ""\r"" ok {test-number} - sstream.str() == "\"\\t\"" for: ""\t"" == ""\t"" # JsonWriter escapes characters in strings properly ok {test-number} - sstream.str() == "\"\\\\/\\t\\r\\n\"" for: ""\\/\t\r\n"" == ""\\/\t\r\n"" +# JsonWriter serializes non-finite FP using Python spelling - double +ok {test-number} - sstream.str() == "NaN" for: "NaN" == "NaN" +# JsonWriter serializes non-finite FP using Python spelling - double +ok {test-number} - sstream.str() == "Infinity" for: "Infinity" == "Infinity" +# JsonWriter serializes non-finite FP using Python spelling - double +ok {test-number} - sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" +# JsonWriter serializes non-finite FP using Python spelling - float +ok {test-number} - sstream.str() == "NaN" for: "NaN" == "NaN" +# JsonWriter serializes non-finite FP using Python spelling - float +ok {test-number} - sstream.str() == "Infinity" for: "Infinity" == "Infinity" +# JsonWriter serializes non-finite FP using Python spelling - float +ok {test-number} - sstream.str() == "-Infinity" for: "-Infinity" == "-Infinity" # JsonWriter serializes numbers independently of the global locale ok {test-number} - sstream.str(), ContainsSubstring( "\"double\": 1.5," ) && ContainsSubstring( "\"int\": 1234567," ) && ContainsSubstring( "\"bool-1\": true," ) && ContainsSubstring( "\"bool-2\": false," ) && ContainsSubstring( "\"array\": [\n 2.5,\n 1234567\n ]\n}" ) for: "{ "double": 1.5, "int": 1234567, "bool-1": true, "bool-2": false, "array": [ 2.5, 1234567 ] }" ( contains: ""double": 1.5," and contains: ""int": 1234567," and contains: ""bool-1": true," and contains: ""bool-2": false," and contains: ""array": [ 2.5, 1234567 ] }" ) # Lambdas in assertions @@ -4842,5 +4854,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2429 +1..2435 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index fc65c1c6..16fe73f9 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -470,6 +470,10 @@ ##teamcity[testFinished name='JsonWriter' duration="{duration}"] ##teamcity[testStarted name='JsonWriter escapes characters in strings properly'] ##teamcity[testFinished name='JsonWriter escapes characters in strings properly' duration="{duration}"] +##teamcity[testStarted name='JsonWriter serializes non-finite FP using Python spelling - double'] +##teamcity[testFinished name='JsonWriter serializes non-finite FP using Python spelling - double' duration="{duration}"] +##teamcity[testStarted name='JsonWriter serializes non-finite FP using Python spelling - float'] +##teamcity[testFinished name='JsonWriter serializes non-finite FP using Python spelling - float' duration="{duration}"] ##teamcity[testStarted name='JsonWriter serializes numbers independently of the global locale'] ##teamcity[testFinished name='JsonWriter serializes numbers independently of the global locale' duration="{duration}"] ##teamcity[testStarted name='Lambdas in assertions'] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index f0a28ed7..acc777f2 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -470,6 +470,10 @@ ##teamcity[testFinished name='JsonWriter' duration="{duration}"] ##teamcity[testStarted name='JsonWriter escapes characters in strings properly'] ##teamcity[testFinished name='JsonWriter escapes characters in strings properly' duration="{duration}"] +##teamcity[testStarted name='JsonWriter serializes non-finite FP using Python spelling - double'] +##teamcity[testFinished name='JsonWriter serializes non-finite FP using Python spelling - double' duration="{duration}"] +##teamcity[testStarted name='JsonWriter serializes non-finite FP using Python spelling - float'] +##teamcity[testFinished name='JsonWriter serializes non-finite FP using Python spelling - float' duration="{duration}"] ##teamcity[testStarted name='JsonWriter serializes numbers independently of the global locale'] ##teamcity[testFinished name='JsonWriter serializes numbers independently of the global locale' duration="{duration}"] ##teamcity[testStarted name='Lambdas in assertions'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index 31801eef..a7f8d3ae 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -9894,6 +9894,78 @@ Approx( 3.14150000000000018 ) + +
+ + + sstream.str() == "NaN" + + + "NaN" == "NaN" + + + +
+
+ + + sstream.str() == "Infinity" + + + "Infinity" == "Infinity" + + + +
+
+ + + sstream.str() == "-Infinity" + + + "-Infinity" == "-Infinity" + + + +
+ +
+ +
+ + + sstream.str() == "NaN" + + + "NaN" == "NaN" + + + +
+
+ + + sstream.str() == "Infinity" + + + "Infinity" == "Infinity" + + + +
+
+ + + sstream.str() == "-Infinity" + + + "-Infinity" == "-Infinity" + + + +
+ +
@@ -23409,6 +23481,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 b24ec091..cbfe936b 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -9894,6 +9894,78 @@ Approx( 3.14150000000000018 )
+ +
+ + + sstream.str() == "NaN" + + + "NaN" == "NaN" + + + +
+
+ + + sstream.str() == "Infinity" + + + "Infinity" == "Infinity" + + + +
+
+ + + sstream.str() == "-Infinity" + + + "-Infinity" == "-Infinity" + + + +
+ +
+ +
+ + + sstream.str() == "NaN" + + + "NaN" == "NaN" + + + +
+
+ + + sstream.str() == "Infinity" + + + "Infinity" == "Infinity" + + + +
+
+ + + sstream.str() == "-Infinity" + + + "-Infinity" == "-Infinity" + + + +
+ +
@@ -23408,6 +23480,6 @@ Approx( -1.95996398454005449 ) - - + + diff --git a/tests/SelfTest/IntrospectiveTests/Json.tests.cpp b/tests/SelfTest/IntrospectiveTests/Json.tests.cpp index 4f6789ec..d026c76c 100644 --- a/tests/SelfTest/IntrospectiveTests/Json.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Json.tests.cpp @@ -7,11 +7,13 @@ // SPDX-License-Identifier: BSL-1.0 #include +#include #include #include #include #include +#include #include #include @@ -199,6 +201,29 @@ TEST_CASE( "JsonWriter serializes numbers independently of the global locale", "\"array\": [\n 2.5,\n 1234567\n ]\n}" ) ); } +TEMPLATE_TEST_CASE( "JsonWriter serializes non-finite FP using Python spelling", + "[JsonWriter][floating-point]", + float, + double ) { + std::stringstream sstream; + + SECTION( "NaN" ) { + Catch::JsonValueWriter{ sstream }.write( + std::numeric_limits::quiet_NaN() ); + REQUIRE( sstream.str() == "NaN" ); + } + SECTION( "Pos nf" ) { + Catch::JsonValueWriter{ sstream }.write( + std::numeric_limits::infinity() ); + REQUIRE( sstream.str() == "Infinity" ); + } + SECTION( "Neg inf" ) { + Catch::JsonValueWriter{ sstream }.write( + -std::numeric_limits::infinity() ); + REQUIRE( sstream.str() == "-Infinity" ); + } +} + TEST_CASE( "JsonWriter benchmarks", "[JsonWriter][!benchmark]" ) { const auto input_length = GENERATE( as{}, 10, 100, 10'000 ); std::string test_input( input_length, 'a' );