Martin Hořeňovský | 7db4d8d | 2017-02-07 13:32:48 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Created by Martin on 17/02/2017. |
| 3 | * |
| 4 | * Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 5 | * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 6 | */ |
| 7 | |
Phil Nash | e41e8e8 | 2018-01-04 10:03:08 +0000 | [diff] [blame] | 8 | #define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER |
Martin Hořeňovský | 7db4d8d | 2017-02-07 13:32:48 +0100 | [diff] [blame] | 9 | #include "catch.hpp" |
| 10 | |
Phil Nash | e41e8e8 | 2018-01-04 10:03:08 +0000 | [diff] [blame] | 11 | #include <map> |
| 12 | #include <set> |
Martin Hořeňovský | 7db4d8d | 2017-02-07 13:32:48 +0100 | [diff] [blame] | 13 | |
| 14 | TEST_CASE( "Character pretty printing" ){ |
Martin Hořeňovský | 7db4d8d | 2017-02-07 13:32:48 +0100 | [diff] [blame] | 15 | SECTION("Specifically escaped"){ |
| 16 | char tab = '\t'; |
| 17 | char newline = '\n'; |
| 18 | char carr_return = '\r'; |
| 19 | char form_feed = '\f'; |
| 20 | CHECK(tab == '\t'); |
| 21 | CHECK(newline == '\n'); |
| 22 | CHECK(carr_return == '\r'); |
| 23 | CHECK(form_feed == '\f'); |
| 24 | } |
| 25 | SECTION("General chars"){ |
| 26 | char space = ' '; |
| 27 | CHECK(space == ' '); |
| 28 | char chars[] = {'a', 'z', 'A', 'Z'}; |
| 29 | for (int i = 0; i < 4; ++i){ |
| 30 | char c = chars[i]; |
| 31 | REQUIRE(c == chars[i]); |
| 32 | } |
| 33 | } |
| 34 | SECTION("Low ASCII"){ |
| 35 | char null_terminator = '\0'; |
| 36 | CHECK(null_terminator == '\0'); |
| 37 | for (int i = 2; i < 6; ++i){ |
| 38 | char c = static_cast<char>(i); |
| 39 | REQUIRE(c == i); |
| 40 | } |
Martin Hořeňovský | 377c9a7 | 2017-05-27 14:42:54 +0200 | [diff] [blame] | 41 | } |
Martin Hořeňovský | 7db4d8d | 2017-02-07 13:32:48 +0100 | [diff] [blame] | 42 | } |
Martin Hořeňovský | be4f6ab | 2017-03-03 14:34:50 +0100 | [diff] [blame] | 43 | |
| 44 | |
| 45 | TEST_CASE( "Capture and info messages" ) { |
| 46 | SECTION("Capture should stringify like assertions") { |
| 47 | int i = 2; |
| 48 | CAPTURE(i); |
| 49 | REQUIRE(true); |
| 50 | } |
| 51 | SECTION("Info should NOT stringify the way assertions do") { |
| 52 | int i = 3; |
| 53 | INFO(i); |
| 54 | REQUIRE(true); |
| 55 | } |
| 56 | } |
Phil Nash | e41e8e8 | 2018-01-04 10:03:08 +0000 | [diff] [blame] | 57 | |
| 58 | TEST_CASE( "std::map is convertible string", "[toString]" ) { |
| 59 | |
| 60 | SECTION( "empty" ) { |
| 61 | std::map<std::string, int> emptyMap; |
| 62 | |
| 63 | REQUIRE( Catch::Detail::stringify( emptyMap ) == "{ }" ); |
| 64 | } |
| 65 | |
| 66 | SECTION( "single item" ) { |
| 67 | std::map<std::string, int> map = { { "one", 1 } }; |
| 68 | |
| 69 | REQUIRE( Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" ); |
| 70 | } |
| 71 | |
| 72 | SECTION( "several items" ) { |
| 73 | std::map<std::string, int> map = { |
| 74 | { "abc", 1 }, |
| 75 | { "def", 2 }, |
| 76 | { "ghi", 3 } |
| 77 | }; |
| 78 | |
| 79 | REQUIRE( Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" ); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | TEST_CASE( "std::set is convertible string", "[toString]" ) { |
| 84 | |
| 85 | SECTION( "empty" ) { |
| 86 | std::set<std::string> emptySet; |
| 87 | |
| 88 | REQUIRE( Catch::Detail::stringify( emptySet ) == "{ }" ); |
| 89 | } |
| 90 | |
| 91 | SECTION( "single item" ) { |
| 92 | std::set<std::string> set = { "one" }; |
| 93 | |
| 94 | REQUIRE( Catch::Detail::stringify( set ) == "{ \"one\" }" ); |
| 95 | } |
| 96 | |
| 97 | SECTION( "several items" ) { |
| 98 | std::set<std::string> set = { "abc", "def", "ghi" }; |
| 99 | |
| 100 | REQUIRE( Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" ); |
| 101 | } |
| 102 | } |
Martin Hořeňovský | 8d854c6 | 2018-01-14 18:06:21 +0100 | [diff] [blame] | 103 | |
| 104 | TEST_CASE("Static arrays are convertible to string", "[toString]") { |
| 105 | SECTION("Single item") { |
| 106 | int singular[1] = { 1 }; |
| 107 | REQUIRE(Catch::Detail::stringify(singular) == "{ 1 }"); |
| 108 | } |
| 109 | SECTION("Multiple") { |
| 110 | int arr[3] = { 3, 2, 1 }; |
| 111 | REQUIRE(Catch::Detail::stringify(arr) == "{ 3, 2, 1 }"); |
| 112 | } |
| 113 | SECTION("Non-trivial inner items") { |
| 114 | std::vector<std::string> arr[2] = { {"1:1", "1:2", "1:3"}, {"2:1", "2:2"} }; |
| 115 | REQUIRE(Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })"); |
| 116 | } |
| 117 | } |
Martin Hořeňovský | 6c5c4c4 | 2018-05-12 17:46:25 +0200 | [diff] [blame] | 118 | |
melak47 | a575536 | 2018-09-04 17:01:26 +0200 | [diff] [blame] | 119 | #ifdef CATCH_CONFIG_CPP17_STRING_VIEW |
| 120 | |
| 121 | TEST_CASE("String views are stringified like other strings", "[toString][approvals]") { |
| 122 | std::string_view view{"abc"}; |
| 123 | CHECK(Catch::Detail::stringify(view) == R"("abc")"); |
| 124 | |
| 125 | std::string_view arr[] { view }; |
| 126 | CHECK(Catch::Detail::stringify(arr) == R"({ "abc" })"); |
| 127 | } |
| 128 | |
| 129 | #endif |
| 130 | |
Martin Hořeňovský | 1161011 | 2019-05-02 21:32:54 +0200 | [diff] [blame] | 131 | TEST_CASE("Precision of floating point stringification can be set", "[toString][floatingPoint]") { |
| 132 | SECTION("Floats") { |
| 133 | using sm = Catch::StringMaker<float>; |
| 134 | const auto oldPrecision = sm::precision; |
| 135 | |
| 136 | const float testFloat = 1.12345678901234567899f; |
| 137 | auto str1 = sm::convert(testFloat); |
| 138 | sm::precision = 5; |
| 139 | // "1." prefix = 2 chars, f suffix is another char |
| 140 | CHECK(str1.size() == 3 + 5); |
| 141 | |
| 142 | sm::precision = 10; |
| 143 | auto str2 = sm::convert(testFloat); |
| 144 | REQUIRE(str2.size() == 3 + 10); |
| 145 | sm::precision = oldPrecision; |
| 146 | } |
| 147 | SECTION("Double") { |
| 148 | using sm = Catch::StringMaker<double>; |
| 149 | const auto oldPrecision = sm::precision; |
| 150 | |
| 151 | const double testDouble = 1.123456789012345678901234567899; |
| 152 | sm::precision = 5; |
| 153 | auto str1 = sm::convert(testDouble); |
| 154 | // "1." prefix = 2 chars |
| 155 | CHECK(str1.size() == 2 + 5); |
| 156 | |
| 157 | sm::precision = 15; |
| 158 | auto str2 = sm::convert(testDouble); |
| 159 | REQUIRE(str2.size() == 2 + 15); |
| 160 | |
| 161 | sm::precision = oldPrecision; |
| 162 | } |
| 163 | } |
mlimber | 53a83e8 | 2019-04-26 11:14:33 -0400 | [diff] [blame] | 164 | |
Martin Hořeňovský | e1d8117 | 2018-07-02 11:13:07 +0200 | [diff] [blame] | 165 | namespace { |
| 166 | |
Martin Hořeňovský | 6c5c4c4 | 2018-05-12 17:46:25 +0200 | [diff] [blame] | 167 | struct WhatException : std::exception { |
| 168 | char const* what() const noexcept override { |
Ryan Pavlik | edde6f4 | 2019-04-08 16:30:28 -0500 | [diff] [blame] | 169 | return "This exception has overridden what() method"; |
Martin Hořeňovský | 6c5c4c4 | 2018-05-12 17:46:25 +0200 | [diff] [blame] | 170 | } |
| 171 | ~WhatException() override; |
| 172 | }; |
| 173 | |
| 174 | struct OperatorException : std::exception { |
| 175 | ~OperatorException() override; |
| 176 | }; |
| 177 | |
| 178 | std::ostream& operator<<(std::ostream& out, OperatorException const&) { |
| 179 | out << "OperatorException"; |
| 180 | return out; |
| 181 | } |
| 182 | |
| 183 | struct StringMakerException : std::exception { |
| 184 | ~StringMakerException() override; |
| 185 | }; |
| 186 | |
Martin Hořeňovský | e1d8117 | 2018-07-02 11:13:07 +0200 | [diff] [blame] | 187 | } // end anonymous namespace |
| 188 | |
Martin Hořeňovský | 6c5c4c4 | 2018-05-12 17:46:25 +0200 | [diff] [blame] | 189 | namespace Catch { |
| 190 | template <> |
| 191 | struct StringMaker<StringMakerException> { |
| 192 | static std::string convert(StringMakerException const&) { |
| 193 | return "StringMakerException"; |
| 194 | } |
| 195 | }; |
| 196 | } |
| 197 | |
| 198 | // Avoid -Wweak-tables |
| 199 | WhatException::~WhatException() = default; |
| 200 | OperatorException::~OperatorException() = default; |
| 201 | StringMakerException::~StringMakerException() = default; |
| 202 | |
| 203 | |
| 204 | |
| 205 | |
| 206 | TEST_CASE("Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified", "[toString][exception]") { |
Ryan Pavlik | edde6f4 | 2019-04-08 16:30:28 -0500 | [diff] [blame] | 207 | REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method"); |
Martin Hořeňovský | 6c5c4c4 | 2018-05-12 17:46:25 +0200 | [diff] [blame] | 208 | REQUIRE(::Catch::Detail::stringify(OperatorException{}) == "OperatorException"); |
| 209 | REQUIRE(::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException"); |
| 210 | } |