| /* |
| * Created by Phil on 09/11/2010. |
| * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. |
| * |
| * 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) |
| */ |
| |
| #ifdef __clang__ |
| #pragma clang diagnostic ignored "-Wpadded" |
| #endif |
| |
| #ifdef _MSC_VER |
| #pragma warning (disable : 4702) // Disable unreachable code warning for the last test |
| // that is triggered when compiling as Win32|Release |
| #endif |
| |
| #include "catch.hpp" |
| |
| #include <stdio.h> |
| #include <sstream> |
| |
| namespace Catch { |
| std::string toString( const std::pair<int, int>& value ) { |
| std::ostringstream oss; |
| oss << "std::pair( " << value.first << ", " << value.second << " )"; |
| return oss.str(); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "Parsing a std::pair", |
| "[Tricky][std::pair]" |
| ) |
| { |
| std::pair<int, int> aNicePair( 1, 2 ); |
| |
| REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair ); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "Where there is more to the expression after the RHS", |
| "[Tricky][failing][.]" |
| ) |
| { |
| // int a = 1, b = 2; |
| // REQUIRE( a == 2 || b == 2 ); |
| WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "Where the LHS is not a simple value", |
| "[Tricky][failing][.]" |
| ) |
| { |
| /* |
| int a = 1; |
| int b = 2; |
| |
| // This only captures part of the expression, but issues a warning about the rest |
| REQUIRE( a+1 == b-1 ); |
| */ |
| WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); |
| } |
| |
| struct Opaque |
| { |
| int val; |
| bool operator ==( const Opaque& o ) const |
| { |
| return val == o.val; |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "A failing expression with a non streamable type is still captured", |
| "[Tricky][failing][.]" |
| ) |
| { |
| |
| Opaque o1, o2; |
| o1.val = 7; |
| o2.val = 8; |
| |
| CHECK( &o1 == &o2 ); |
| CHECK( o1 == o2 ); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "string literals of different sizes can be compared", |
| "[Tricky][failing][.]" |
| ) |
| { |
| REQUIRE( std::string( "first" ) == "second" ); |
| |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "An expression with side-effects should only be evaluated once", |
| "[Tricky]" |
| ) |
| { |
| int i = 7; |
| |
| REQUIRE( i++ == 7 ); |
| REQUIRE( i++ == 8 ); |
| |
| } |
| |
| namespace A { |
| struct X |
| { |
| X() : a(4), b(2), c(7) {} |
| X(int v) : a(v), b(2), c(7) {} |
| int a; |
| int b; |
| int c; |
| }; |
| } |
| |
| namespace B { |
| struct Y |
| { |
| Y() : a(4), b(2), c(7) {} |
| Y(int v) : a(v), b(2), c(7) {} |
| int a; |
| int b; |
| int c; |
| }; |
| } |
| |
| inline bool operator==(const A::X& lhs, const B::Y& rhs) |
| { |
| return (lhs.a == rhs.a); |
| } |
| |
| inline bool operator==(const B::Y& lhs, const A::X& rhs) |
| { |
| return (lhs.a == rhs.a); |
| } |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| /* This, currently, does not compile with LLVM |
| TEST_CASE |
| ( |
| "Operators at different namespace levels not hijacked by Koenig lookup" |
| "[Tricky]" |
| ) |
| { |
| A::X x; |
| B::Y y; |
| REQUIRE( x == y ); |
| } |
| */ |
| |
| namespace ObjectWithConversions |
| { |
| struct Object |
| { |
| operator unsigned int() const {return 0xc0000000;} |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| TEST_CASE |
| ( |
| "Operators at different namespace levels not hijacked by Koenig lookup", |
| "[Tricky][approvals]" |
| ) |
| { |
| Object o; |
| REQUIRE(0xc0000000 == o ); |
| } |
| } |
| |
| namespace EnumBitFieldTests |
| { |
| enum Bits : uint32_t { |
| bit0 = 0x0001, |
| bit1 = 0x0002, |
| bit2 = 0x0004, |
| bit3 = 0x0008, |
| bit1and2 = bit1 | bit2, |
| bit30 = 0x40000000, |
| bit31 = 0x80000000, |
| bit30and31 = bit30 | bit31 |
| }; |
| |
| TEST_CASE( "Test enum bit values", "[Tricky]" ) |
| { |
| REQUIRE( 0xc0000000 == bit30and31 ); |
| } |
| } |
| |
| struct Obj |
| { |
| Obj():prop(&p){} |
| |
| int p; |
| int* prop; |
| }; |
| |
| TEST_CASE("boolean member", "[Tricky]") |
| { |
| Obj obj; |
| REQUIRE( obj.prop != nullptr ); |
| } |
| |
| // Tests for a problem submitted by Ralph McArdell |
| // |
| // The static bool value should not need to be defined outside the |
| // struct it is declared in - but when evaluating it in a deduced |
| // context it appears to require the extra definition. |
| // The issue was fixed by adding bool overloads to bypass the |
| // templates that were there to deduce it. |
| template <bool B> |
| struct is_true |
| { |
| static const bool value = B; |
| }; |
| |
| TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" ) |
| { |
| SECTION("compare to true","") |
| { |
| REQUIRE( is_true<true>::value == true ); |
| REQUIRE( true == is_true<true>::value ); |
| } |
| SECTION("compare to false","") |
| { |
| REQUIRE( is_true<false>::value == false ); |
| REQUIRE( false == is_true<false>::value ); |
| } |
| |
| SECTION("negation", "") |
| { |
| REQUIRE( !is_true<false>::value ); |
| } |
| |
| SECTION("double negation","") |
| { |
| REQUIRE( !!is_true<true>::value ); |
| } |
| |
| SECTION("direct","") |
| { |
| REQUIRE( is_true<true>::value ); |
| REQUIRE_FALSE( is_true<false>::value ); |
| } |
| } |
| |
| // Uncomment these tests to produce an error at test registration time |
| /* |
| TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) |
| { |
| |
| } |
| TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) |
| { |
| |
| } |
| */ |
| |
| struct Boolable |
| { |
| explicit Boolable( bool value ) : m_value( value ) {} |
| |
| explicit operator bool() const { |
| return m_value; |
| } |
| |
| bool m_value; |
| }; |
| |
| TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" ) |
| { |
| Boolable True( true ); |
| Boolable False( false ); |
| |
| CHECK( True ); |
| CHECK( !False ); |
| CHECK_FALSE( False ); |
| } |
| |
| TEST_CASE( "Assertions then sections", "[Tricky]" ) |
| { |
| // This was causing a failure due to the way the console reporter was handling |
| // the current section |
| |
| REQUIRE( true ); |
| |
| SECTION( "A section" ) |
| { |
| REQUIRE( true ); |
| |
| SECTION( "Another section" ) |
| { |
| REQUIRE( true ); |
| } |
| SECTION( "Another other section" ) |
| { |
| REQUIRE( true ); |
| } |
| } |
| } |
| |
| struct Awkward |
| { |
| operator int() const { return 7; } |
| }; |
| |
| TEST_CASE( "non streamable - with conv. op", "[Tricky]" ) |
| { |
| Awkward awkward; |
| std::string s = ::Catch::Detail::stringify( awkward ); |
| REQUIRE( s == "7" ); |
| } |
| |
| inline void foo() {} |
| |
| typedef void (*fooptr_t)(); |
| |
| TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" ) |
| { |
| // This was giving a warning in VS2010 |
| // #179 |
| fooptr_t a = foo; |
| |
| REQUIRE( a ); |
| REQUIRE( a == &foo ); |
| } |
| |
| struct S |
| { |
| void f() {} |
| }; |
| |
| |
| TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer][approvals]" ) |
| { |
| typedef void (S::*MF)(); |
| MF m = &S::f; |
| |
| CHECK( m == &S::f ); |
| } |
| |
| class ClassName {}; |
| |
| TEST_CASE( "pointer to class", "[Tricky]" ) |
| { |
| ClassName *p = 0; |
| REQUIRE( p == 0 ); |
| } |
| |
| #include <memory> |
| |
| TEST_CASE( "null_ptr", "[Tricky]" ) |
| { |
| std::unique_ptr<int> ptr; |
| REQUIRE(ptr.get() == nullptr); |
| } |
| |
| TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); } |
| TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); } |
| TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); } |
| TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); } |
| |
| TEST_CASE( "has printf" ) { |
| |
| // This can cause problems as, currently, stdout itself is not redirected - only the cout (and cerr) buffer |
| printf( "loose text artifact\n" ); |
| } |
| |
| namespace { |
| struct constructor_throws { |
| [[noreturn]] constructor_throws() { |
| throw 1; |
| } |
| }; |
| } |
| |
| TEST_CASE("Commas in various macros are allowed") { |
| REQUIRE_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} ); |
| CHECK_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} ); |
| REQUIRE_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} ); |
| CHECK_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} ); |
| |
| REQUIRE(std::vector<int>{1, 2} == std::vector<int>{1, 2}); |
| CHECK( std::vector<int>{1, 2} == std::vector<int>{1, 2} ); |
| REQUIRE_FALSE(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3}); |
| CHECK_FALSE( std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} ); |
| |
| CHECK_NOFAIL( std::vector<int>{1, 2} == std::vector<int>{1, 2} ); |
| CHECKED_IF( std::vector<int>{1, 2} == std::vector<int>{1, 2} ) { |
| REQUIRE(true); |
| } CHECKED_ELSE( std::vector<int>{1, 2} == std::vector<int>{1, 2} ) { |
| CHECK(true); |
| } |
| } |
| |
| TEST_CASE( "null deref", "[.][failing][!nonportable]" ) { |
| CHECK( false ); |
| int *x = NULL; |
| *x = 1; |
| } |
| |
| TEST_CASE( "non-copyable objects", "[.][failing]" ) { |
| // Thanks to Agustin Bergé (@k-ballo on the cpplang Slack) for raising this |
| std::type_info const& ti = typeid(int); |
| CHECK( ti == typeid(int) ); |
| } |
| |
| // #925 |
| using signal_t = void (*) (void*); |
| |
| struct TestClass { |
| signal_t testMethod_uponComplete_arg = nullptr; |
| }; |
| |
| namespace utility { |
| inline static void synchronizing_callback( void * ) { } |
| } |
| |
| TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) { |
| |
| TestClass test; |
| REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg); |
| } |
| |
| TEST_CASE( "Bitfields can be captured (#1027)" ) { |
| struct Y { |
| uint32_t v : 1; |
| }; |
| Y y{ 0 }; |
| REQUIRE( y.v == 0 ); |
| REQUIRE( 0 == y.v ); |
| } |