From 21b99d6f589090983136bf764514261dc863ed9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 27 Sep 2021 18:30:31 +0200 Subject: [PATCH] Add StringRef::compare for three way comparison --- src/catch2/internal/catch_stringref.cpp | 21 +++++ src/catch2/internal/catch_stringref.hpp | 10 +- .../Baselines/automake.sw.approved.txt | 1 + .../Baselines/compact.sw.approved.txt | 10 ++ .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 68 +++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 4 +- .../Baselines/sonarqube.sw.approved.txt | 2 + tests/SelfTest/Baselines/tap.sw.approved.txt | 22 ++++- .../Baselines/teamcity.sw.approved.txt | 2 + tests/SelfTest/Baselines/xml.sw.approved.txt | 93 ++++++++++++++++++- .../IntrospectiveTests/String.tests.cpp | 27 ++++++ 12 files changed, 254 insertions(+), 10 deletions(-) diff --git a/src/catch2/internal/catch_stringref.cpp b/src/catch2/internal/catch_stringref.cpp index 36a6d246..0aa535db 100644 --- a/src/catch2/internal/catch_stringref.cpp +++ b/src/catch2/internal/catch_stringref.cpp @@ -29,6 +29,27 @@ namespace Catch { return strncmp(m_start, rhs.m_start, rhs.m_size) < 0; } + int StringRef::compare( StringRef rhs ) const { + auto cmpResult = + strncmp( m_start, rhs.m_start, std::min( m_size, rhs.m_size ) ); + + // This means that strncmp found a difference before the strings + // ended, and we can return it directly + if ( cmpResult != 0 ) { + return cmpResult; + } + + // If strings are equal up to length, then their comparison results on + // their size + if ( m_size < rhs.m_size ) { + return -1; + } else if ( m_size > rhs.m_size ) { + return 1; + } else { + return 0; + } + } + auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { return os.write(str.data(), str.size()); } diff --git a/src/catch2/internal/catch_stringref.hpp b/src/catch2/internal/catch_stringref.hpp index 17f5d07d..3d42fc25 100644 --- a/src/catch2/internal/catch_stringref.hpp +++ b/src/catch2/internal/catch_stringref.hpp @@ -69,7 +69,6 @@ namespace Catch { return m_size; } - public: // substrings and searches // Returns a substring of [start, start + length). // If start + length > size(), then the substring is [start, start + size()). // If start > size(), then the substring is empty. @@ -87,7 +86,6 @@ namespace Catch { return m_start; } - public: // iterators constexpr const_iterator begin() const { return m_start; } constexpr const_iterator end() const { return m_start + m_size; } @@ -95,6 +93,14 @@ namespace Catch { friend std::string& operator += (std::string& lhs, StringRef const& sr); friend std::ostream& operator << (std::ostream& os, StringRef const& sr); friend std::string operator+(StringRef lhs, StringRef rhs); + + /** + * Provides a three-way comparison with rhs + * + * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive + * number if lhs > rhs + */ + int compare( StringRef rhs ) const; }; diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index 7b401531..54d94cc2 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -207,6 +207,7 @@ Message from section two :test-result: PASS String matchers :test-result: PASS StringRef :test-result: PASS StringRef at compilation time +:test-result: PASS StringRef::compare :test-result: PASS Stringifying char arrays with statically known sizes - char :test-result: PASS Stringifying char arrays with statically known sizes - signed char :test-result: PASS Stringifying char arrays with statically known sizes - unsigned char diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index 1813ff3c..8b3df2ac 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -1537,6 +1537,16 @@ String.tests.cpp:: passed: with 1 message: '!(sr1.empty())' String.tests.cpp:: passed: with 1 message: 'sr1.size() == 3' String.tests.cpp:: passed: with 1 message: 'sr2.empty()' String.tests.cpp:: passed: with 1 message: 'sr2.size() == 0' +String.tests.cpp:: passed: sr1.compare(sr2) < 0 for: -1 < 0 +String.tests.cpp:: passed: sr2.compare(sr1) > 0 for: 1 > 0 +String.tests.cpp:: passed: sr1.compare(sr3) == 0 for: 0 == 0 +String.tests.cpp:: passed: sr3.compare(sr1) == 0 for: 0 == 0 +String.tests.cpp:: passed: sr1.compare(sr2) < 0 for: -1 < 0 +String.tests.cpp:: passed: sr2.compare(sr1) > 0 for: 1 > 0 +String.tests.cpp:: passed: sr1.compare(sr3) > 0 for: 3 > 0 +String.tests.cpp:: passed: sr2.compare(sr3) > 0 for: 3 > 0 +String.tests.cpp:: passed: sr3.compare(sr1) < 0 for: -3 < 0 +String.tests.cpp:: passed: sr3.compare(sr2) < 0 for: -3 < 0 ToString.tests.cpp:: passed: ::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc"" ToString.tests.cpp:: passed: ::Catch::Detail::stringify( no_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc"" ToString.tests.cpp:: passed: ::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc"" diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 13b39435..a8a8fcb4 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1386,6 +1386,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 369 | 293 passed | 70 failed | 6 failed as expected -assertions: 2106 | 1954 passed | 129 failed | 23 failed as expected +test cases: 370 | 294 passed | 70 failed | 6 failed as expected +assertions: 2116 | 1964 passed | 129 failed | 23 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index ba1d14c9..12ca8ad7 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -10906,6 +10906,70 @@ String.tests.cpp:: PASSED: with message: sr2.size() == 0 +------------------------------------------------------------------------------- +StringRef::compare + Same length on both sides +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: PASSED: + REQUIRE( sr1.compare(sr2) < 0 ) +with expansion: + -1 < 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr2.compare(sr1) > 0 ) +with expansion: + 1 > 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr1.compare(sr3) == 0 ) +with expansion: + 0 == 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr3.compare(sr1) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef::compare + Different lengths +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: PASSED: + REQUIRE( sr1.compare(sr2) < 0 ) +with expansion: + -1 < 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr2.compare(sr1) > 0 ) +with expansion: + 1 > 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr1.compare(sr3) > 0 ) +with expansion: + 3 > 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr2.compare(sr3) > 0 ) +with expansion: + 3 > 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr3.compare(sr1) < 0 ) +with expansion: + -3 < 0 + +String.tests.cpp:: PASSED: + REQUIRE( sr3.compare(sr2) < 0 ) +with expansion: + -3 < 0 + ------------------------------------------------------------------------------- Stringifying char arrays with statically known sizes - char ------------------------------------------------------------------------------- @@ -16954,6 +17018,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 369 | 277 passed | 86 failed | 6 failed as expected -assertions: 2123 | 1954 passed | 146 failed | 23 failed as expected +test cases: 370 | 278 passed | 86 failed | 6 failed as expected +assertions: 2133 | 1964 passed | 146 failed | 23 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index f6285201..57225235 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -1196,6 +1196,8 @@ Matchers.tests.cpp: + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index c95948c3..6c43b6b3 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -204,6 +204,8 @@ + + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index a82febac..6583d673 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -2753,6 +2753,26 @@ ok {test-number} - with 1 message: 'sr1.size() == 3' ok {test-number} - with 1 message: 'sr2.empty()' # StringRef at compilation time ok {test-number} - with 1 message: 'sr2.size() == 0' +# StringRef::compare +ok {test-number} - sr1.compare(sr2) < 0 for: -1 < 0 +# StringRef::compare +ok {test-number} - sr2.compare(sr1) > 0 for: 1 > 0 +# StringRef::compare +ok {test-number} - sr1.compare(sr3) == 0 for: 0 == 0 +# StringRef::compare +ok {test-number} - sr3.compare(sr1) == 0 for: 0 == 0 +# StringRef::compare +ok {test-number} - sr1.compare(sr2) < 0 for: -1 < 0 +# StringRef::compare +ok {test-number} - sr2.compare(sr1) > 0 for: 1 > 0 +# StringRef::compare +ok {test-number} - sr1.compare(sr3) > 0 for: 3 > 0 +# StringRef::compare +ok {test-number} - sr2.compare(sr3) > 0 for: 3 > 0 +# StringRef::compare +ok {test-number} - sr3.compare(sr1) < 0 for: -3 < 0 +# StringRef::compare +ok {test-number} - sr3.compare(sr2) < 0 for: -3 < 0 # Stringifying char arrays with statically known sizes - char ok {test-number} - ::Catch::Detail::stringify( with_null_terminator ) == R"("abc")"s for: ""abc"" == ""abc"" # Stringifying char arrays with statically known sizes - char @@ -4248,5 +4268,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2123 +1..2133 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 3867ec4a..d61c69df 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -514,6 +514,8 @@ Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringFor ##teamcity[testFinished name='StringRef' duration="{duration}"] ##teamcity[testStarted name='StringRef at compilation time'] ##teamcity[testFinished name='StringRef at compilation time' duration="{duration}"] +##teamcity[testStarted name='StringRef::compare'] +##teamcity[testFinished name='StringRef::compare' duration="{duration}"] ##teamcity[testStarted name='Stringifying char arrays with statically known sizes - char'] ##teamcity[testFinished name='Stringifying char arrays with statically known sizes - char' duration="{duration}"] ##teamcity[testStarted name='Stringifying char arrays with statically known sizes - signed char'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index 917010be..a20b2ffb 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -12945,6 +12945,95 @@ Message from section two + +
+ + + sr1.compare(sr2) < 0 + + + -1 < 0 + + + + + sr2.compare(sr1) > 0 + + + 1 > 0 + + + + + sr1.compare(sr3) == 0 + + + 0 == 0 + + + + + sr3.compare(sr1) == 0 + + + 0 == 0 + + + +
+
+ + + sr1.compare(sr2) < 0 + + + -1 < 0 + + + + + sr2.compare(sr1) > 0 + + + 1 > 0 + + + + + sr1.compare(sr3) > 0 + + + 3 > 0 + + + + + sr2.compare(sr3) > 0 + + + 3 > 0 + + + + + sr3.compare(sr1) < 0 + + + -3 < 0 + + + + + sr3.compare(sr2) < 0 + + + -3 < 0 + + + +
+ +
@@ -19953,6 +20042,6 @@ loose text artifact - - + + diff --git a/tests/SelfTest/IntrospectiveTests/String.tests.cpp b/tests/SelfTest/IntrospectiveTests/String.tests.cpp index 4b9cc0e3..c44b7230 100644 --- a/tests/SelfTest/IntrospectiveTests/String.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/String.tests.cpp @@ -165,3 +165,30 @@ TEST_CASE("StringRef at compilation time", "[Strings][StringRef][constexpr]") { STATIC_REQUIRE(sr2.size() == 0); } } + +TEST_CASE("StringRef::compare", "[Strings][StringRef]") { + using Catch::StringRef; + + SECTION("Same length on both sides") { + StringRef sr1("abcdc"); + StringRef sr2("abcdd"); + StringRef sr3("abcdc"); + + REQUIRE(sr1.compare(sr2) < 0); + REQUIRE(sr2.compare(sr1) > 0); + REQUIRE(sr1.compare(sr3) == 0); + REQUIRE(sr3.compare(sr1) == 0); + } + SECTION("Different lengths") { + StringRef sr1("def"); + StringRef sr2("deff"); + StringRef sr3("ab"); + + REQUIRE(sr1.compare(sr2) < 0); + REQUIRE(sr2.compare(sr1) > 0); + REQUIRE(sr1.compare(sr3) > 0); + REQUIRE(sr2.compare(sr3) > 0); + REQUIRE(sr3.compare(sr1) < 0); + REQUIRE(sr3.compare(sr2) < 0); + } +}