/* * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #include // Setup for #1403 -- look for global overloads of operator << for classes // in a different namespace. #include namespace foo { struct helper_1403 { bool operator==(helper_1403) const { return true; } }; } namespace bar { template struct TypeList {}; } #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wmissing-declarations" #endif std::ostream& operator<<(std::ostream& out, foo::helper_1403 const&) { return out << "[1403 helper]"; } /////////////////////////////// #include #include #include namespace { namespace CompilationTests { #ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU #define COMPILATION_TEST_HELPERS_INCLUDED // Comparison operators can return non-booleans. // This is unusual, but should be supported. struct logic_t { logic_t operator< (logic_t) const { return {}; } logic_t operator<=(logic_t) const { return {}; } logic_t operator> (logic_t) const { return {}; } logic_t operator>=(logic_t) const { return {}; } logic_t operator==(logic_t) const { return {}; } logic_t operator!=(logic_t) const { return {}; } explicit operator bool() const { return true; } }; // This is a minimal example for an issue we have found in 1.7.0 struct foo { int i; }; template bool operator==(const T &val, foo f) { return val == f.i; } struct Y { uint32_t v : 1; }; void throws_int(bool b) { if (b) { throw 1; } } template bool templated_tests(T t) { int a = 3; REQUIRE(a == t); CHECK(a == t); REQUIRE_THROWS(throws_int(true)); CHECK_THROWS_AS(throws_int(true), int); REQUIRE_NOTHROW(throws_int(false)); REQUIRE_THAT("aaa", Catch::Matchers::EndsWith("aaa")); return true; } struct A { }; std::ostream &operator<<(std::ostream &o, const A &) { return o << 0; } struct B : private A { bool operator==(int) const { return true; } }; #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #endif #ifdef __GNUC__ // Note that because -~GCC~-, this warning cannot be silenced temporarily, by pushing diagnostic stack... // Luckily it is firing in test files and thus can be silenced for the whole file, without losing much. #pragma GCC diagnostic ignored "-Wunused-function" #endif B f(); std::ostream g(); #ifdef __clang__ #pragma clang diagnostic pop #endif template struct Fixture_1245 {}; #endif TEST_CASE("#809") { foo f; f.i = 42; REQUIRE(42 == f); } // ------------------------------------------------------------------ // Changes to REQUIRE_THROWS_AS made it stop working in a template in // an unfixable way (as long as C++03 compatibility is being kept). // To prevent these from happening in the future, this needs to compile TEST_CASE("#833") { REQUIRE(templated_tests(3)); } // Test containing example where original stream insertable check breaks compilation TEST_CASE("#872") { A dummy; CAPTURE(dummy); B x; REQUIRE (x == 4); } TEST_CASE("#1027") { Y y{0}; REQUIRE(y.v == 0); REQUIRE(0 == y.v); } // Comparison operators can return non-booleans. // This is unusual, but should be supported. TEST_CASE("#1147") { logic_t t1, t2; REQUIRE(t1 == t2); REQUIRE(t1 != t2); REQUIRE(t1 < t2); REQUIRE(t1 > t2); REQUIRE(t1 <= t2); REQUIRE(t1 >= t2); } // unsigned array TEST_CASE("#1238") { unsigned char uarr[] = "123"; CAPTURE(uarr); signed char sarr[] = "456"; CAPTURE(sarr); REQUIRE(std::memcmp(uarr, "123", sizeof(uarr)) == 0); REQUIRE(std::memcmp(sarr, "456", sizeof(sarr)) == 0); } TEST_CASE_METHOD((Fixture_1245), "#1245", "[compilation]") { SUCCEED(); } TEST_CASE("#1403", "[compilation]") { ::foo::helper_1403 h1, h2; REQUIRE(h1 == h2); } TEST_CASE("Optionally static assertions", "[compilation]") { STATIC_REQUIRE( std::is_void::value ); STATIC_REQUIRE_FALSE( std::is_void::value ); } TEST_CASE("#1548", "[compilation]") { using namespace bar; REQUIRE(std::is_same, TypeList>::value); } // #925 using signal_t = void (*) (void*); struct TestClass { signal_t testMethod_uponComplete_arg = nullptr; }; namespace utility { inline static void synchronizing_callback( void * ) { } } #if defined (_MSC_VER) #pragma warning(push) // The function pointer comparison below triggers warning because of // calling conventions #pragma warning(disable:4244) #endif TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) { TestClass test; REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg); } #if defined (_MSC_VER) #pragma warning(pop) #endif TEST_CASE( "#1027: Bitfields can be captured" ) { struct Y { uint32_t v : 1; }; Y y{ 0 }; REQUIRE( y.v == 0 ); REQUIRE( 0 == y.v ); } TEST_CASE("#1319: Sections can have description (even if it is not saved", "[compilation]") { SECTION("SectionName", "This is a long form section description") { SUCCEED(); } } TEST_CASE("Lambdas in assertions") { REQUIRE([]() { return true; }()); } }} // namespace CompilationTests namespace { struct HasBitOperators { int value; friend HasBitOperators operator| (HasBitOperators lhs, HasBitOperators rhs) { return { lhs.value | rhs.value }; } friend HasBitOperators operator& (HasBitOperators lhs, HasBitOperators rhs) { return { lhs.value & rhs.value }; } explicit operator bool() const { return !!value; } friend std::ostream& operator<<(std::ostream& out, HasBitOperators val) { out << "Val: " << val.value; return out; } }; } TEST_CASE("Assertion macros support bit operators and bool conversions", "[compilation][bitops]") { HasBitOperators lhs{ 1 }, rhs{ 2 }; REQUIRE(lhs | rhs); REQUIRE_FALSE(lhs & rhs); REQUIRE(HasBitOperators{ 1 } & HasBitOperators{ 1 }); }