Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp
diff options
context:
space:
mode:
authormelak472018-09-20 13:13:35 +0100
committerMartin Hořeňovský2018-09-20 14:13:35 +0200
commitc638c5720970f03033755dd9ebb0e4e6dccb1289 (patch)
treeca5f58bb48ed1f9d8f6383d544a42fcf8592aff6 /projects/SelfTest/UsageTests/ToStringVariant.tests.cpp
parenta575536abe20b58c48863600f8a71e93b4052b81 (diff)
downloadcatch3-c638c5720970f03033755dd9ebb0e4e6dccb1289.tar.gz
Add StringMaker for std::variant, std::monostate (#1380)
The StringMaker is off by default and can be enabled by a new macro `CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER`, to avoid increasing the footprint of stringification machinery by default.
Diffstat (limited to 'projects/SelfTest/UsageTests/ToStringVariant.tests.cpp')
-rw-r--r--projects/SelfTest/UsageTests/ToStringVariant.tests.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp b/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp
new file mode 100644
index 00000000..62f923f0
--- /dev/null
+++ b/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp
@@ -0,0 +1,84 @@
+#define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
+#include "catch.hpp"
+
+#if defined(CATCH_CONFIG_CPP17_VARIANT)
+
+#include <string>
+#include <variant>
+
+TEST_CASE( "variant<std::monostate>", "[toString][variant][approvals]")
+{
+ using type = std::variant<std::monostate>;
+ CHECK( "{ }" == ::Catch::Detail::stringify(type{}) );
+ type value {};
+ CHECK( "{ }" == ::Catch::Detail::stringify(value) );
+ CHECK( "{ }" == ::Catch::Detail::stringify(std::get<0>(value)) );
+}
+
+TEST_CASE( "variant<int>", "[toString][variant][approvals]")
+{
+ using type = std::variant<int>;
+ CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+}
+
+TEST_CASE( "variant<float, int>", "[toString][variant][approvals]")
+{
+ using type = std::variant<float, int>;
+ CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
+ CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+
+ SECTION("valueless by exception") {
+ struct sample {
+ operator int() const { throw 42; }
+ };
+
+ type value{1.5f};
+ REQUIRE_THROWS_AS( value.emplace<int>(sample{}), int );
+ REQUIRE( value.valueless_by_exception() );
+ CHECK( "{valueless variant}" == ::Catch::Detail::stringify(value) );
+ }
+}
+
+TEST_CASE( "variant<string, int>", "[toString][variant][approvals]")
+{
+ using type = std::variant<std::string, int>;
+ CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
+ CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+}
+
+TEST_CASE( "variant<variant<float, int>, string>", "[toString][variant][approvals]")
+{
+ using inner = std::variant<float, int>;
+ using type = std::variant<inner, std::string>;
+ CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
+ CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+ CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
+
+ struct sample {
+ operator int() const { throw 42; }
+ };
+
+ SECTION("valueless nested variant") {
+ type value = inner{0.5f};
+ REQUIRE( std::holds_alternative<inner>(value) );
+ REQUIRE( std::holds_alternative<float>(std::get<inner>(value)) );
+
+ REQUIRE_THROWS_AS( std::get<0>(value).emplace<int>(sample{}), int );
+
+ // outer variant is still valid and contains inner
+ REQUIRE( std::holds_alternative<inner>(value) );
+ // inner variant is valueless
+ REQUIRE( std::get<inner>(value).valueless_by_exception() );
+ CHECK( "{valueless variant}" == ::Catch::Detail::stringify(value) );
+ }
+}
+
+TEST_CASE( "variant<nullptr,int,const char *>", "[toString][variant][approvals]" )
+{
+ using type = std::variant<std::nullptr_t,int,const char *>;
+ CHECK( "nullptr" == ::Catch::Detail::stringify(type{nullptr}) );
+ CHECK( "42" == ::Catch::Detail::stringify(type{42}) );
+ CHECK( "\"Catch me\"" == ::Catch::Detail::stringify(type{"Catch me"}) );
+}
+
+#endif // CATCH_INTERNAL_CONFIG_CPP17_VARIANT