diff --git a/src/catch2/internal/catch_case_insensitive_comparisons.cpp b/src/catch2/internal/catch_case_insensitive_comparisons.cpp index 3f81b219..904c2289 100644 --- a/src/catch2/internal/catch_case_insensitive_comparisons.cpp +++ b/src/catch2/internal/catch_case_insensitive_comparisons.cpp @@ -22,5 +22,14 @@ namespace Catch { []( char l, char r ) { return toLower( l ) < toLower( r ); } ); } + bool + CaseInsensitiveEqualTo::operator()( StringRef lhs, + StringRef rhs ) const { + return std::equal( + lhs.begin(), lhs.end(), + rhs.begin(), rhs.end(), + []( char l, char r ) { return toLower( l ) == toLower( r ); } ); + } + } // namespace Detail } // namespace Catch diff --git a/src/catch2/internal/catch_case_insensitive_comparisons.hpp b/src/catch2/internal/catch_case_insensitive_comparisons.hpp index 6dfe712b..5742e6b7 100644 --- a/src/catch2/internal/catch_case_insensitive_comparisons.hpp +++ b/src/catch2/internal/catch_case_insensitive_comparisons.hpp @@ -20,6 +20,12 @@ namespace Catch { StringRef rhs ) const; }; + //! Provides case-insensitive `op==` semantics when called + struct CaseInsensitiveEqualTo { + bool operator()( StringRef lhs, + StringRef rhs ) const; + }; + } // namespace Detail } // namespace Catch diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index 8fff84db..ea0e0ce2 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -100,6 +100,8 @@ Nor would this :test-result: PASS CAPTURE can deal with complex expressions involving commas :test-result: PASS CAPTURE parses string and character constants :test-result: PASS Capture and info messages +:test-result: PASS CaseInsensitiveEqualsTo is case insensitive +:test-result: PASS CaseInsensitiveLess is case insensitive :test-result: PASS Character pretty printing :test-result: PASS Clara::Arg supports single-arg parse the way Opt does :test-result: PASS Clara::Opt supports accept-many lambdas diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index 66b385a5..da97ee82 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -334,6 +334,21 @@ Message.tests.cpp:: passed: with 7 messages: 'std::vector{1, 2 Message.tests.cpp:: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{'' ToStringGeneral.tests.cpp:: passed: true with 1 message: 'i := 2' ToStringGeneral.tests.cpp:: passed: true with 1 message: '3' +Details.tests.cpp:: passed: eq( "", "" ) for: true +Details.tests.cpp:: passed: !(eq( "", "a" )) for: !false +Details.tests.cpp:: passed: eq( "a", "a" ) for: true +Details.tests.cpp:: passed: eq( "a", "A" ) for: true +Details.tests.cpp:: passed: eq( "A", "a" ) for: true +Details.tests.cpp:: passed: eq( "A", "A" ) for: true +Details.tests.cpp:: passed: !(eq( "a", "b" )) for: !false +Details.tests.cpp:: passed: !(eq( "a", "B" )) for: !false +Details.tests.cpp:: passed: lt( "", "a" ) for: true +Details.tests.cpp:: passed: !(lt( "a", "a" )) for: !false +Details.tests.cpp:: passed: !(lt( "", "" )) for: !false +Details.tests.cpp:: passed: lt( "a", "b" ) for: true +Details.tests.cpp:: passed: lt( "a", "B" ) for: true +Details.tests.cpp:: passed: lt( "A", "b" ) for: true +Details.tests.cpp:: passed: lt( "A", "B" ) for: true ToStringGeneral.tests.cpp:: passed: tab == '\t' for: '\t' == '\t' ToStringGeneral.tests.cpp:: passed: newline == '\n' for: '\n' == '\n' ToStringGeneral.tests.cpp:: passed: carr_return == '\r' for: '\r' == '\r' diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 4147f373..be4f8e78 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1426,6 +1426,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 377 | 300 passed | 70 failed | 7 failed as expected -assertions: 2154 | 1998 passed | 129 failed | 27 failed as expected +test cases: 379 | 302 passed | 70 failed | 7 failed as expected +assertions: 2169 | 2013 passed | 129 failed | 27 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 764ac970..7d637d7e 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -2801,6 +2801,109 @@ ToStringGeneral.tests.cpp:: PASSED: with message: 3 +------------------------------------------------------------------------------- +CaseInsensitiveEqualsTo is case insensitive + Degenerate cases +------------------------------------------------------------------------------- +Details.tests.cpp: +............................................................................... + +Details.tests.cpp:: PASSED: + REQUIRE( eq( "", "" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE_FALSE( eq( "", "a" ) ) +with expansion: + !false + +------------------------------------------------------------------------------- +CaseInsensitiveEqualsTo is case insensitive + Plain comparisons +------------------------------------------------------------------------------- +Details.tests.cpp: +............................................................................... + +Details.tests.cpp:: PASSED: + REQUIRE( eq( "a", "a" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE( eq( "a", "A" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE( eq( "A", "a" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE( eq( "A", "A" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE_FALSE( eq( "a", "b" ) ) +with expansion: + !false + +Details.tests.cpp:: PASSED: + REQUIRE_FALSE( eq( "a", "B" ) ) +with expansion: + !false + +------------------------------------------------------------------------------- +CaseInsensitiveLess is case insensitive + Degenerate cases +------------------------------------------------------------------------------- +Details.tests.cpp: +............................................................................... + +Details.tests.cpp:: PASSED: + REQUIRE( lt( "", "a" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE_FALSE( lt( "a", "a" ) ) +with expansion: + !false + +Details.tests.cpp:: PASSED: + REQUIRE_FALSE( lt( "", "" ) ) +with expansion: + !false + +------------------------------------------------------------------------------- +CaseInsensitiveLess is case insensitive + Plain comparisons +------------------------------------------------------------------------------- +Details.tests.cpp: +............................................................................... + +Details.tests.cpp:: PASSED: + REQUIRE( lt( "a", "b" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE( lt( "a", "B" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE( lt( "A", "b" ) ) +with expansion: + true + +Details.tests.cpp:: PASSED: + REQUIRE( lt( "A", "B" ) ) +with expansion: + true + ------------------------------------------------------------------------------- Character pretty printing Specifically escaped @@ -17321,6 +17424,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 377 | 284 passed | 86 failed | 7 failed as expected -assertions: 2171 | 1998 passed | 146 failed | 27 failed as expected +test cases: 379 | 286 passed | 86 failed | 7 failed as expected +assertions: 2186 | 2013 passed | 146 failed | 27 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index 49640ad3..3181ebbd 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -378,6 +378,10 @@ Exception.tests.cpp: + + + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index dc1f7a54..0762507d 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -89,6 +89,12 @@ + + + + + + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index fe02346f..a02d3417 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -666,6 +666,36 @@ ok {test-number} - with 11 messages: '("comma, in string", "escaped, \", ") := " ok {test-number} - true with 1 message: 'i := 2' # Capture and info messages ok {test-number} - true with 1 message: '3' +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - eq( "", "" ) for: true +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - !(eq( "", "a" )) for: !false +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - eq( "a", "a" ) for: true +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - eq( "a", "A" ) for: true +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - eq( "A", "a" ) for: true +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - eq( "A", "A" ) for: true +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - !(eq( "a", "b" )) for: !false +# CaseInsensitiveEqualsTo is case insensitive +ok {test-number} - !(eq( "a", "B" )) for: !false +# CaseInsensitiveLess is case insensitive +ok {test-number} - lt( "", "a" ) for: true +# CaseInsensitiveLess is case insensitive +ok {test-number} - !(lt( "a", "a" )) for: !false +# CaseInsensitiveLess is case insensitive +ok {test-number} - !(lt( "", "" )) for: !false +# CaseInsensitiveLess is case insensitive +ok {test-number} - lt( "a", "b" ) for: true +# CaseInsensitiveLess is case insensitive +ok {test-number} - lt( "a", "B" ) for: true +# CaseInsensitiveLess is case insensitive +ok {test-number} - lt( "A", "b" ) for: true +# CaseInsensitiveLess is case insensitive +ok {test-number} - lt( "A", "B" ) for: true # Character pretty printing ok {test-number} - tab == '\t' for: '\t' == '\t' # Character pretty printing @@ -4344,5 +4374,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2171 +1..2186 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index b570833f..cadec0c4 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -233,6 +233,10 @@ Exception.tests.cpp:|nunexpected exception with message:|n "unexpe ##teamcity[testFinished name='CAPTURE parses string and character constants' duration="{duration}"] ##teamcity[testStarted name='Capture and info messages'] ##teamcity[testFinished name='Capture and info messages' duration="{duration}"] +##teamcity[testStarted name='CaseInsensitiveEqualsTo is case insensitive'] +##teamcity[testFinished name='CaseInsensitiveEqualsTo is case insensitive' duration="{duration}"] +##teamcity[testStarted name='CaseInsensitiveLess is case insensitive'] +##teamcity[testFinished name='CaseInsensitiveLess is case insensitive' duration="{duration}"] ##teamcity[testStarted name='Character pretty printing'] ##teamcity[testFinished name='Character pretty printing' duration="{duration}"] ##teamcity[testStarted name='Clara::Arg supports single-arg parse the way Opt does'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index d09dde34..4602696b 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -3013,6 +3013,144 @@ Nor would this + +
+ + + eq( "", "" ) + + + true + + + + + !(eq( "", "a" )) + + + !false + + + +
+
+ + + eq( "a", "a" ) + + + true + + + + + eq( "a", "A" ) + + + true + + + + + eq( "A", "a" ) + + + true + + + + + eq( "A", "A" ) + + + true + + + + + !(eq( "a", "b" )) + + + !false + + + + + !(eq( "a", "B" )) + + + !false + + + +
+ +
+ +
+ + + lt( "", "a" ) + + + true + + + + + !(lt( "a", "a" )) + + + !false + + + + + !(lt( "", "" )) + + + !false + + + +
+
+ + + lt( "a", "b" ) + + + true + + + + + lt( "a", "B" ) + + + true + + + + + lt( "A", "b" ) + + + true + + + + + lt( "A", "B" ) + + + true + + + +
+ +
@@ -20290,6 +20428,6 @@ loose text artifact
- - + + diff --git a/tests/SelfTest/IntrospectiveTests/Details.tests.cpp b/tests/SelfTest/IntrospectiveTests/Details.tests.cpp index bddb0d5b..38adcbac 100644 --- a/tests/SelfTest/IntrospectiveTests/Details.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Details.tests.cpp @@ -5,6 +5,7 @@ #include #include +#include #if defined(_MSC_VER) #pragma warning(push) @@ -22,3 +23,35 @@ TEST_CASE("Check that our error handling macros throw the right exceptions", "[! #if defined(_MSC_VER) #pragma warning(pop) // unreachable code in the macro expansions #endif + +TEST_CASE("CaseInsensitiveLess is case insensitive", "[comparisons][string-case]") { + Catch::Detail::CaseInsensitiveLess lt; + SECTION( "Degenerate cases" ) { + REQUIRE( lt( "", "a" ) ); + REQUIRE_FALSE( lt( "a", "a" ) ); + REQUIRE_FALSE( lt( "", "" ) ); + } + SECTION("Plain comparisons") { + REQUIRE( lt( "a", "b" ) ); + REQUIRE( lt( "a", "B" ) ); + REQUIRE( lt( "A", "b" ) ); + REQUIRE( lt( "A", "B" ) ); + } +} + +TEST_CASE( "CaseInsensitiveEqualsTo is case insensitive", + "[comparisons][string-case]" ) { + Catch::Detail::CaseInsensitiveEqualTo eq; + SECTION( "Degenerate cases" ) { + REQUIRE( eq( "", "" ) ); + REQUIRE_FALSE( eq( "", "a" ) ); + } + SECTION( "Plain comparisons" ) { + REQUIRE( eq( "a", "a" ) ); + REQUIRE( eq( "a", "A" ) ); + REQUIRE( eq( "A", "a" ) ); + REQUIRE( eq( "A", "A" ) ); + REQUIRE_FALSE( eq( "a", "b" ) ); + REQUIRE_FALSE( eq( "a", "B" ) ); + } +}