ToStringGeneral.tests.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. #define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
  8. #include "catch.hpp"
  9. #include <map>
  10. #include <set>
  11. TEST_CASE( "Character pretty printing" ){
  12. SECTION("Specifically escaped"){
  13. char tab = '\t';
  14. char newline = '\n';
  15. char carr_return = '\r';
  16. char form_feed = '\f';
  17. CHECK(tab == '\t');
  18. CHECK(newline == '\n');
  19. CHECK(carr_return == '\r');
  20. CHECK(form_feed == '\f');
  21. }
  22. SECTION("General chars"){
  23. char space = ' ';
  24. CHECK(space == ' ');
  25. char chars[] = {'a', 'z', 'A', 'Z'};
  26. for (int i = 0; i < 4; ++i){
  27. char c = chars[i];
  28. REQUIRE(c == chars[i]);
  29. }
  30. }
  31. SECTION("Low ASCII"){
  32. char null_terminator = '\0';
  33. CHECK(null_terminator == '\0');
  34. for (int i = 2; i < 6; ++i){
  35. char c = static_cast<char>(i);
  36. REQUIRE(c == i);
  37. }
  38. }
  39. }
  40. TEST_CASE( "Capture and info messages" ) {
  41. SECTION("Capture should stringify like assertions") {
  42. int i = 2;
  43. CAPTURE(i);
  44. REQUIRE(true);
  45. }
  46. SECTION("Info should NOT stringify the way assertions do") {
  47. int i = 3;
  48. INFO(i);
  49. REQUIRE(true);
  50. }
  51. }
  52. TEST_CASE( "std::map is convertible string", "[toString]" ) {
  53. SECTION( "empty" ) {
  54. std::map<std::string, int> emptyMap;
  55. REQUIRE( Catch::Detail::stringify( emptyMap ) == "{ }" );
  56. }
  57. SECTION( "single item" ) {
  58. std::map<std::string, int> map = { { "one", 1 } };
  59. REQUIRE( Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" );
  60. }
  61. SECTION( "several items" ) {
  62. std::map<std::string, int> map = {
  63. { "abc", 1 },
  64. { "def", 2 },
  65. { "ghi", 3 }
  66. };
  67. REQUIRE( Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" );
  68. }
  69. }
  70. TEST_CASE( "std::set is convertible string", "[toString]" ) {
  71. SECTION( "empty" ) {
  72. std::set<std::string> emptySet;
  73. REQUIRE( Catch::Detail::stringify( emptySet ) == "{ }" );
  74. }
  75. SECTION( "single item" ) {
  76. std::set<std::string> set = { "one" };
  77. REQUIRE( Catch::Detail::stringify( set ) == "{ \"one\" }" );
  78. }
  79. SECTION( "several items" ) {
  80. std::set<std::string> set = { "abc", "def", "ghi" };
  81. REQUIRE( Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" );
  82. }
  83. }
  84. TEST_CASE("Static arrays are convertible to string", "[toString]") {
  85. SECTION("Single item") {
  86. int singular[1] = { 1 };
  87. REQUIRE(Catch::Detail::stringify(singular) == "{ 1 }");
  88. }
  89. SECTION("Multiple") {
  90. int arr[3] = { 3, 2, 1 };
  91. REQUIRE(Catch::Detail::stringify(arr) == "{ 3, 2, 1 }");
  92. }
  93. SECTION("Non-trivial inner items") {
  94. std::vector<std::string> arr[2] = { {"1:1", "1:2", "1:3"}, {"2:1", "2:2"} };
  95. REQUIRE(Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })");
  96. }
  97. }
  98. #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
  99. TEST_CASE("String views are stringified like other strings", "[toString][approvals]") {
  100. std::string_view view{"abc"};
  101. CHECK(Catch::Detail::stringify(view) == R"("abc")");
  102. std::string_view arr[] { view };
  103. CHECK(Catch::Detail::stringify(arr) == R"({ "abc" })");
  104. }
  105. #endif
  106. TEST_CASE("Precision of floating point stringification can be set", "[toString][floatingPoint]") {
  107. SECTION("Floats") {
  108. using sm = Catch::StringMaker<float>;
  109. const auto oldPrecision = sm::precision;
  110. const float testFloat = 1.12345678901234567899f;
  111. auto str1 = sm::convert(testFloat);
  112. sm::precision = 5;
  113. // "1." prefix = 2 chars, f suffix is another char
  114. CHECK(str1.size() == 3 + 5);
  115. sm::precision = 10;
  116. auto str2 = sm::convert(testFloat);
  117. REQUIRE(str2.size() == 3 + 10);
  118. sm::precision = oldPrecision;
  119. }
  120. SECTION("Double") {
  121. using sm = Catch::StringMaker<double>;
  122. const auto oldPrecision = sm::precision;
  123. const double testDouble = 1.123456789012345678901234567899;
  124. sm::precision = 5;
  125. auto str1 = sm::convert(testDouble);
  126. // "1." prefix = 2 chars
  127. CHECK(str1.size() == 2 + 5);
  128. sm::precision = 15;
  129. auto str2 = sm::convert(testDouble);
  130. REQUIRE(str2.size() == 2 + 15);
  131. sm::precision = oldPrecision;
  132. }
  133. }
  134. namespace {
  135. struct WhatException : std::exception {
  136. char const* what() const noexcept override {
  137. return "This exception has overridden what() method";
  138. }
  139. ~WhatException() override;
  140. };
  141. struct OperatorException : std::exception {
  142. ~OperatorException() override;
  143. };
  144. std::ostream& operator<<(std::ostream& out, OperatorException const&) {
  145. out << "OperatorException";
  146. return out;
  147. }
  148. struct StringMakerException : std::exception {
  149. ~StringMakerException() override;
  150. };
  151. } // end anonymous namespace
  152. namespace Catch {
  153. template <>
  154. struct StringMaker<StringMakerException> {
  155. static std::string convert(StringMakerException const&) {
  156. return "StringMakerException";
  157. }
  158. };
  159. }
  160. // Avoid -Wweak-tables
  161. WhatException::~WhatException() = default;
  162. OperatorException::~OperatorException() = default;
  163. StringMakerException::~StringMakerException() = default;
  164. TEST_CASE("Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified", "[toString][exception]") {
  165. REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method");
  166. REQUIRE(::Catch::Detail::stringify(OperatorException{}) == "OperatorException");
  167. REQUIRE(::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException");
  168. }