Make JSONWriter's number handling locale-independent

Closes #3176
This commit is contained in:
Martin Hořeňovský
2026-07-23 00:10:28 +02:00
parent 8494e2dce4
commit 0cc833ea95
19 changed files with 211 additions and 19 deletions
+6 -1
View File
@@ -9,6 +9,8 @@
#include <catch2/internal/catch_jsonwriter.hpp>
#include <catch2/internal/catch_unreachable.hpp>
#include <locale>
namespace Catch {
namespace {
@@ -126,7 +128,10 @@ namespace Catch {
JsonValueWriter::JsonValueWriter( std::ostream& os,
std::uint64_t indent_level ):
m_os{ os }, m_indent_level{ indent_level } {}
m_os{ os }, m_indent_level{ indent_level } {
// We use C locale so that writing of numerical values is locale-independent.
m_sstream.imbue( std::locale::classic() );
}
JsonObjectWriter JsonValueWriter::writeObject() && {
return JsonObjectWriter{ m_os, m_indent_level };
@@ -190,6 +190,7 @@ 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 numbers independently of the global locale
:test-result: PASS Lambdas in assertions
:test-result: PASS Less-than inequalities with different epsilons
:test-result: PASS ManuallyRegistered
@@ -188,6 +188,7 @@
: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 numbers independently of the global locale
:test-result: PASS Lambdas in assertions
:test-result: PASS Less-than inequalities with different epsilons
:test-result: PASS ManuallyRegistered
@@ -1248,6 +1248,20 @@ Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\n\"" for: ""\n"" ==
Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\r\"" for: ""\r"" == ""\r""
Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\t\"" for: ""\t"" == ""\t""
Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\\\/\\t\\r\\n\"" for: ""\\/\t\r\n"" == ""\\/\t\r\n""
Json.tests.cpp:<line number>: 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,
"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
]
}" )
Compilation.tests.cpp:<line number>: passed: []() { return true; }() for: true
Approx.tests.cpp:<line number>: passed: d <= Approx( 1.24 ) for: 1.22999999999999998
<=
@@ -3000,7 +3014,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
test cases: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected
@@ -1246,6 +1246,20 @@ Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\n\"" for: ""\n"" ==
Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\r\"" for: ""\r"" == ""\r""
Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\t\"" for: ""\t"" == ""\t""
Json.tests.cpp:<line number>: passed: sstream.str() == "\"\\\\/\\t\\r\\n\"" for: ""\\/\t\r\n"" == ""\\/\t\r\n""
Json.tests.cpp:<line number>: 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,
"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
]
}" )
Compilation.tests.cpp:<line number>: passed: []() { return true; }() for: true
Approx.tests.cpp:<line number>: passed: d <= Approx( 1.24 ) for: 1.22999999999999998
<=
@@ -2989,7 +3003,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
test cases: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected
@@ -1743,6 +1743,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 451 | 349 passed | 76 failed | 7 skipped | 19 failed as expected
assertions: 2394 | 2215 passed | 136 failed | 43 failed as expected
test cases: 452 | 350 passed | 76 failed | 7 skipped | 19 failed as expected
assertions: 2395 | 2216 passed | 136 failed | 43 failed as expected
@@ -8219,6 +8219,31 @@ Json.tests.cpp:<line number>: PASSED:
with expansion:
""\\/\t\r\n"" == ""\\/\t\r\n""
-------------------------------------------------------------------------------
JsonWriter serializes numbers independently of the global locale
-------------------------------------------------------------------------------
Json.tests.cpp:<line number>
...............................................................................
Json.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 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}" ) )
with expansion:
"{
"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
-------------------------------------------------------------------------------
@@ -20134,6 +20159,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
test cases: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected
@@ -8217,6 +8217,31 @@ Json.tests.cpp:<line number>: PASSED:
with expansion:
""\\/\t\r\n"" == ""\\/\t\r\n""
-------------------------------------------------------------------------------
JsonWriter serializes numbers independently of the global locale
-------------------------------------------------------------------------------
Json.tests.cpp:<line number>
...............................................................................
Json.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 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}" ) )
with expansion:
"{
"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
-------------------------------------------------------------------------------
@@ -20123,6 +20148,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected
test cases: 452 | 332 passed | 96 failed | 6 skipped | 18 failed as expected
assertions: 2417 | 2216 passed | 158 failed | 43 failed as expected
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2428" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2429" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@@ -774,6 +774,7 @@ at Condition.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="JsonWriter escapes characters in strings properly/carriage return in a string is escaped" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="JsonWriter escapes characters in strings properly/tab in a string is escaped" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="JsonWriter escapes characters in strings properly/combination of characters is escaped" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="JsonWriter serializes numbers independently of the global locale" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Lambdas in assertions" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Less-than inequalities with different epsilons" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="ManuallyRegistered" time="{duration}" status="run"/>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2428" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="141" skipped="12" tests="2429" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@@ -773,6 +773,7 @@ at Condition.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="JsonWriter escapes characters in strings properly/carriage return in a string is escaped" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="JsonWriter escapes characters in strings properly/tab in a string is escaped" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="JsonWriter escapes characters in strings properly/combination of characters is escaped" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="JsonWriter serializes numbers independently of the global locale" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Lambdas in assertions" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Less-than inequalities with different epsilons" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="ManuallyRegistered" time="{duration}" status="run"/>
@@ -262,6 +262,7 @@ at AssertionHandler.tests.cpp:<line number>
<testCase name="JsonWriter escapes characters in strings properly/carriage return in a string is escaped" duration="{duration}"/>
<testCase name="JsonWriter escapes characters in strings properly/tab in a string is escaped" duration="{duration}"/>
<testCase name="JsonWriter escapes characters in strings properly/combination of characters is escaped" duration="{duration}"/>
<testCase name="JsonWriter serializes numbers independently of the global locale" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp">
<testCase name="Parse uints" duration="{duration}"/>
@@ -261,6 +261,7 @@ at AssertionHandler.tests.cpp:<line number>
<testCase name="JsonWriter escapes characters in strings properly/carriage return in a string is escaped" duration="{duration}"/>
<testCase name="JsonWriter escapes characters in strings properly/tab in a string is escaped" duration="{duration}"/>
<testCase name="JsonWriter escapes characters in strings properly/combination of characters is escaped" duration="{duration}"/>
<testCase name="JsonWriter serializes numbers independently of the global locale" duration="{duration}"/>
</file>
<file path="tests/<exe-name>/IntrospectiveTests/Parse.tests.cpp">
<testCase name="Parse uints" duration="{duration}"/>
+3 -1
View File
@@ -2054,6 +2054,8 @@ 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 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
ok {test-number} - []() { return true; }() for: true
# Less-than inequalities with different epsilons
@@ -4851,5 +4853,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} -
# xmlentitycheck
ok {test-number} -
1..2428
1..2429
@@ -2052,6 +2052,8 @@ 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 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
ok {test-number} - []() { return true; }() for: true
# Less-than inequalities with different epsilons
@@ -4840,5 +4842,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} -
# xmlentitycheck
ok {test-number} -
1..2428
1..2429
@@ -470,6 +470,8 @@
##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 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']
##teamcity[testFinished name='Lambdas in assertions' duration="{duration}"]
##teamcity[testStarted name='Less-than inequalities with different epsilons']
@@ -470,6 +470,8 @@
##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 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']
##teamcity[testFinished name='Lambdas in assertions' duration="{duration}"]
##teamcity[testStarted name='Less-than inequalities with different epsilons']
+26 -2
View File
@@ -9894,6 +9894,30 @@ Approx( 3.14150000000000018 )
</Section>
<OverallResult success="true" skips="0"/>
</TestCase>
<TestCase name="JsonWriter serializes numbers independently of the global locale" tags="[JsonWriter]" filename="tests/<exe-name>/IntrospectiveTests/Json.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/IntrospectiveTests/Json.tests.cpp" >
<Original>
sstream.str(), ContainsSubstring( "\"double\": 1.5," ) &amp;&amp; ContainsSubstring( "\"int\": 1234567," ) &amp;&amp; ContainsSubstring( "\"bool-1\": true," ) &amp;&amp; ContainsSubstring( "\"bool-2\": false," ) &amp;&amp; ContainsSubstring( "\"array\": [\n 2.5,\n 1234567\n ]\n}" )
</Original>
<Expanded>
"{
"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
]
}" )
</Expanded>
</Expression>
<OverallResult success="true" skips="0"/>
</TestCase>
<TestCase name="Lambdas in assertions" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
@@ -23385,6 +23409,6 @@ Approx( -1.95996398454005449 )
</Section>
<OverallResult success="true" skips="0"/>
</TestCase>
<OverallResults successes="2215" failures="158" expectedFailures="43" skips="12"/>
<OverallResultsCases successes="331" failures="96" expectedFailures="18" skips="6"/>
<OverallResults successes="2216" failures="158" expectedFailures="43" skips="12"/>
<OverallResultsCases successes="332" failures="96" expectedFailures="18" skips="6"/>
</Catch2TestRun>
@@ -9894,6 +9894,30 @@ Approx( 3.14150000000000018 )
</Section>
<OverallResult success="true" skips="0"/>
</TestCase>
<TestCase name="JsonWriter serializes numbers independently of the global locale" tags="[JsonWriter]" filename="tests/<exe-name>/IntrospectiveTests/Json.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/IntrospectiveTests/Json.tests.cpp" >
<Original>
sstream.str(), ContainsSubstring( "\"double\": 1.5," ) &amp;&amp; ContainsSubstring( "\"int\": 1234567," ) &amp;&amp; ContainsSubstring( "\"bool-1\": true," ) &amp;&amp; ContainsSubstring( "\"bool-2\": false," ) &amp;&amp; ContainsSubstring( "\"array\": [\n 2.5,\n 1234567\n ]\n}" )
</Original>
<Expanded>
"{
"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
]
}" )
</Expanded>
</Expression>
<OverallResult success="true" skips="0"/>
</TestCase>
<TestCase name="Lambdas in assertions" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" >
<Original>
@@ -23384,6 +23408,6 @@ Approx( -1.95996398454005449 )
</Section>
<OverallResult success="true" skips="0"/>
</TestCase>
<OverallResults successes="2215" failures="158" expectedFailures="43" skips="12"/>
<OverallResultsCases successes="331" failures="96" expectedFailures="18" skips="6"/>
<OverallResults successes="2216" failures="158" expectedFailures="43" skips="12"/>
<OverallResultsCases successes="332" failures="96" expectedFailures="18" skips="6"/>
</Catch2TestRun>
@@ -12,6 +12,7 @@
#include <catch2/internal/catch_jsonwriter.hpp>
#include <catch2/matchers/catch_matchers_string.hpp>
#include <locale>
#include <sstream>
namespace {
@@ -20,6 +21,27 @@ namespace {
return os << "custom";
}
// Obviously wrong numpunct if it is actually used by the JSON writer.
class TestNumpunct : public std::numpunct<char> {
char do_decimal_point() const override { return '?'; }
char do_thousands_sep() const override { return '!'; }
std::string do_grouping() const override { return "\1"; }
std::string do_truename() const override { return "real"; }
std::string do_falsename() const override { return "fake"; }
};
class LocaleGuard {
std::locale m_previous_locale;
public:
explicit LocaleGuard( std::locale const& locale ):
m_previous_locale{ std::locale() } {
std::locale::global( locale );
}
~LocaleGuard() { std::locale::global( m_previous_locale ); }
};
TEST_CASE( "JsonWriter", "[JSON][JsonWriter]" ) {
std::stringstream stream;
@@ -152,6 +174,31 @@ TEST_CASE( "JsonWriter escapes characters in strings properly", "[JsonWriter]" )
}
}
TEST_CASE( "JsonWriter serializes numbers independently of the global locale",
"[JsonWriter]" ) {
using Catch::Matchers::ContainsSubstring;
LocaleGuard locale_guard{ std::locale{ std::locale(), new TestNumpunct } };
std::stringstream sstream;
{
auto writer = Catch::JsonValueWriter{ sstream }.writeObject();
writer.write( "double" ).write( 1.5 );
writer.write( "int" ).write( 1234567 );
writer.write( "bool-1" ).write( true );
writer.write( "bool-2" ).write( false );
writer.write( "array" ).writeArray().write( 2.5 ).write( 1234567 );
}
REQUIRE_THAT( 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}" ) );
}
TEST_CASE( "JsonWriter benchmarks", "[JsonWriter][!benchmark]" ) {
const auto input_length = GENERATE( as<size_t>{}, 10, 100, 10'000 );
std::string test_input( input_length, 'a' );