From 126850e76b017ca5b6d5597a3e7545619cb3379a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 1 Feb 2018 14:07:23 +0100 Subject: [PATCH] Prefer operator<< to range-based stringification Fixes #1172 --- include/internal/catch_tostring.h | 2 +- .../Baselines/compact.sw.approved.txt | 8 ++ .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 38 +++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 43 ++++++++++- .../UsageTests/ToStringWhich.tests.cpp | 73 +++++++++++++++++++ 7 files changed, 163 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index a61e45be..9ca5d6e8 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -387,7 +387,7 @@ namespace Catch { } template - struct StringMaker::value && !std::is_array::value>::type> { + struct StringMaker::value && !::Catch::Detail::IsStreamInsertable::value>::type> { static std::string convert( R const& range ) { return rangeToString( range ); } diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt index 25e183bb..947ef425 100644 --- a/projects/SelfTest/Baselines/compact.sw.approved.txt +++ b/projects/SelfTest/Baselines/compact.sw.approved.txt @@ -987,6 +987,14 @@ Misc.tests.cpp:: passed: result == "/"wide load/"" for: ""wide load Misc.tests.cpp:: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load"" +ToStringWhich.tests.cpp:: passed: ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" for: "op<<(streamable_range)" +== +"op<<(streamable_range)" +ToStringWhich.tests.cpp:: passed: ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" for: "stringmaker(streamable_range)" +== +"stringmaker(streamable_range)" +ToStringWhich.tests.cpp:: passed: ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" for: "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }" +ToStringWhich.tests.cpp:: passed: ::Catch::Detail::stringify(disabled_range{}) == "{?}" for: "{?}" == "{?}" ToStringWhich.tests.cpp:: passed: ::Catch::Detail::stringify( v ) == "{ StringMaker }" for: "{ StringMaker }" == "{ StringMaker }" diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 310a3d2e..a94cc4fa 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1064,6 +1064,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 197 | 146 passed | 47 failed | 4 failed as expected -assertions: 992 | 866 passed | 105 failed | 21 failed as expected +test cases: 198 | 147 passed | 47 failed | 4 failed as expected +assertions: 996 | 870 passed | 105 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index eaf2cb41..2b7159e6 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -7894,6 +7894,40 @@ PASSED: with expansion: ""wide load"" == ""wide load"" +------------------------------------------------------------------------------- +toString streamable range +------------------------------------------------------------------------------- +ToStringWhich.tests.cpp: +............................................................................... + +ToStringWhich.tests.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" ) +with expansion: + "op<<(streamable_range)" + == + "op<<(streamable_range)" + +ToStringWhich.tests.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" ) +with expansion: + "stringmaker(streamable_range)" + == + "stringmaker(streamable_range)" + +ToStringWhich.tests.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" ) +with expansion: + "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }" + +ToStringWhich.tests.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(disabled_range{}) == "{?}" ) +with expansion: + "{?}" == "{?}" + ------------------------------------------------------------------------------- toString( vectors ) ------------------------------------------------------------------------------- @@ -8407,6 +8441,6 @@ Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 197 | 132 passed | 61 failed | 4 failed as expected -assertions: 1003 | 862 passed | 120 failed | 21 failed as expected +test cases: 198 | 133 passed | 61 failed | 4 failed as expected +assertions: 1007 | 866 passed | 120 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 4bd6458c..b99f0b8c 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -825,6 +825,7 @@ Tricky.tests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index a95f74f1..ceac33bf 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -8750,6 +8750,45 @@ loose text artifact + + + + ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" + + + "op<<(streamable_range)" +== +"op<<(streamable_range)" + + + + + ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" + + + "stringmaker(streamable_range)" +== +"stringmaker(streamable_range)" + + + + + ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" + + + "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }" + + + + + ::Catch::Detail::stringify(disabled_range{}) == "{?}" + + + "{?}" == "{?}" + + + + @@ -9257,7 +9296,7 @@ loose text artifact - + - + diff --git a/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp b/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp index 2bf467cb..fe961865 100644 --- a/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp +++ b/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp @@ -71,3 +71,76 @@ TEST_CASE( "toString( vectors )", "[toString]" ) { std::vector v(1); REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker }" ); } + +// Conversion should go +// StringMaker specialization, operator<<, range/enum detection, unprintable +struct int_iterator { + using iterator_category = std::input_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = int; + using reference = int&; + using pointer = int*; + + int_iterator() = default; + int_iterator(int i) :val(i) {} + + value_type operator*() const { return val; } + bool operator==(int_iterator rhs) const { return val == rhs.val; } + bool operator!=(int_iterator rhs) const { return val != rhs.val; } + int_iterator operator++() { ++val; return *this; } + int_iterator operator++(int) { + auto temp(*this); + ++val; + return temp; + } +private: + int val = 5; +}; + +struct streamable_range { + int_iterator begin() const { return int_iterator{ 1 }; } + int_iterator end() const { return {}; } +}; + +std::ostream& operator<<(std::ostream& os, const streamable_range&) { + os << "op<<(streamable_range)"; + return os; +} + +struct stringmaker_range { + int_iterator begin() const { return int_iterator{ 1 }; } + int_iterator end() const { return {}; } +}; + +namespace Catch { +template <> +struct StringMaker { + static std::string convert(stringmaker_range const&) { + return "stringmaker(streamable_range)"; + } +}; +} + +struct just_range { + int_iterator begin() const { return int_iterator{ 1 }; } + int_iterator end() const { return {}; } +}; + +struct disabled_range { + int_iterator begin() const { return int_iterator{ 1 }; } + int_iterator end() const { return {}; } +}; + +namespace Catch { +template <> +struct is_range { + static const bool value = false; +}; +} + +TEST_CASE("toString streamable range", "[toString]") { + REQUIRE(::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)"); + REQUIRE(::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)"); + REQUIRE(::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }"); + REQUIRE(::Catch::Detail::stringify(disabled_range{}) == "{?}"); +}