From 48f121b6d429efa285505359663f4c2af6c84b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 22 Sep 2025 22:41:14 +0200 Subject: [PATCH] WIP --- .../IntrospectiveTests/ToString.tests.cpp | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp b/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp index be639ce3..8593e0d5 100644 --- a/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp @@ -6,11 +6,13 @@ // SPDX-License-Identifier: BSL-1.0 +#include +#include +#include +#include #include #include #include -#include -#include #include @@ -139,3 +141,70 @@ TEST_CASE( "Exception thrown inside stringify does not fail the test", "[toStrin ThrowsOnStringification tos; CHECK( tos == tos ); } + +namespace { + [[maybe_unused]] + std::string convertIntoString( Catch::StringRef string, + bool escapeInvisibles ) { + std::string ret; + // This is enough for the "don't escape invisibles" case, and a good + // lower bound on the "escape invisibles" case. + ret.reserve( string.size() + 2 ); + + if ( !escapeInvisibles ) { + ret += '"'; + ret += string; + ret += '"'; + return ret; + } + + size_t last_start = 0; + auto write_to = [&]( size_t idx ) { + if ( last_start < idx ) { + //ret.append( string.data() + last_start, idx - last_start ); + ret += string.substr( last_start, idx - last_start ); + } + last_start = idx + 1; + }; + + ret += '"'; + for ( size_t i = 0; i < string.size(); ++i ) { + const char c = string[i]; + if (c == '\r' || c == '\n' || c == '\t' || c == '\f') { + write_to( i ); + if ( c == '\r' ) { ret.append( "\\r" ); } + if ( c == '\n' ) { ret.append( "\\n" ); } + if ( c == '\t' ) { ret.append( "\\t" ); } + if ( c == '\f' ) { ret.append( "\\f" ); } + } + } + write_to( string.size() ); + ret += '"'; + + return ret; + } +} + + +TEST_CASE( "string escaping benchmark", "[toString][!benchmark]" ) { + const auto input_length = GENERATE( as{}, 10, 100, 10'000, 100'000 ); + std::string test_input( input_length, 'a' ); + BENCHMARK( "no-escape string, no-escaping, len=" + + std::to_string( input_length ) ) { + return Catch::Detail::convertIntoString( test_input, false ); + }; + BENCHMARK( "no-escape string, escaping, len=" + + std::to_string( input_length ) ) { + return Catch::Detail::convertIntoString( test_input, true ); + }; + + std::string escape_input( input_length, '\r' ); + BENCHMARK( "full escape string, no-escaping, len=" + + std::to_string( input_length ) ) { + return Catch::Detail::convertIntoString( escape_input, false ); + }; + BENCHMARK( "full escape string, escaping, len=" + + std::to_string( input_length ) ) { + return Catch::Detail::convertIntoString( escape_input, true ); + }; +}