mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Split SelfTest test files into Usage and Introspective varieties
Usage: just exercises Catch. The tests are over arbitrary date/ types Introspective: Tests parts of Catch itself.
This commit is contained in:
		
							
								
								
									
										230
									
								
								projects/SelfTest/UsageTests/ApproxTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								projects/SelfTest/UsageTests/ApproxTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| /* | ||||
|  *  Created by Phil on 28/04/2011. | ||||
|  *  Copyright 2011 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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <cmath> | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|     "Some simple comparisons between doubles", | ||||
|     "[Approx]" | ||||
| ) | ||||
| { | ||||
|     double d = 1.23; | ||||
|  | ||||
|     REQUIRE( d == Approx( 1.23 ) ); | ||||
|     REQUIRE( d != Approx( 1.22 ) ); | ||||
|     REQUIRE( d != Approx( 1.24 ) ); | ||||
|  | ||||
|     REQUIRE( Approx( d ) == 1.23 ); | ||||
|     REQUIRE( Approx( d ) != 1.22 ); | ||||
|     REQUIRE( Approx( d ) != 1.24 ); | ||||
|  | ||||
|     REQUIRE(INFINITY == Approx(INFINITY)); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|     "Approximate comparisons with different epsilons", | ||||
|     "[Approx]" | ||||
|  ) | ||||
| { | ||||
|     double d = 1.23; | ||||
|  | ||||
|     REQUIRE( d != Approx( 1.231 ) ); | ||||
|     REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|  "Less-than inequalities with different epsilons", | ||||
|  "[Approx]" | ||||
| ) | ||||
| { | ||||
|   double d = 1.23; | ||||
|  | ||||
|   REQUIRE( d <= Approx( 1.24 ) ); | ||||
|   REQUIRE( d <= Approx( 1.23 ) ); | ||||
|   REQUIRE_FALSE( d <= Approx( 1.22 ) ); | ||||
|   REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|  "Greater-than inequalities with different epsilons", | ||||
|  "[Approx]" | ||||
| ) | ||||
| { | ||||
|   double d = 1.23; | ||||
|  | ||||
|   REQUIRE( d >= Approx( 1.22 ) ); | ||||
|   REQUIRE( d >= Approx( 1.23 ) ); | ||||
|   REQUIRE_FALSE( d >= Approx( 1.24 ) ); | ||||
|   REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|     "Approximate comparisons with floats", | ||||
|     "[Approx]" | ||||
| ) | ||||
| { | ||||
|     REQUIRE( 1.23f == Approx( 1.23f ) ); | ||||
|     REQUIRE( 0.0f == Approx( 0.0f ) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|     "Approximate comparisons with ints", | ||||
|     "[Approx]" | ||||
| ) | ||||
| { | ||||
|     REQUIRE( 1 == Approx( 1 ) ); | ||||
|     REQUIRE( 0 == Approx( 0 ) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|     "Approximate comparisons with mixed numeric types", | ||||
|     "[Approx]" | ||||
| ) | ||||
| { | ||||
|     const double dZero = 0; | ||||
|     const double dSmall = 0.00001; | ||||
|     const double dMedium = 1.234; | ||||
|  | ||||
|     REQUIRE( 1.0f == Approx( 1 ) ); | ||||
|     REQUIRE( 0 == Approx( dZero) ); | ||||
|     REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) ); | ||||
|     REQUIRE( 1.234f == Approx( dMedium ) ); | ||||
|     REQUIRE( dMedium == Approx( 1.234f ) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| TEST_CASE | ||||
| ( | ||||
|     "Use a custom approx", | ||||
|     "[Approx][custom]" | ||||
| ) | ||||
| { | ||||
|     double d = 1.23; | ||||
|  | ||||
|     Approx approx = Approx::custom().epsilon( 0.01 ); | ||||
|  | ||||
|     REQUIRE( d == approx( 1.23 ) ); | ||||
|     REQUIRE( d == approx( 1.22 ) ); | ||||
|     REQUIRE( d == approx( 1.24 ) ); | ||||
|     REQUIRE( d != approx( 1.25 ) ); | ||||
|  | ||||
|     REQUIRE( approx( d ) == 1.23 ); | ||||
|     REQUIRE( approx( d ) == 1.22 ); | ||||
|     REQUIRE( approx( d ) == 1.24 ); | ||||
|     REQUIRE( approx( d ) != 1.25 ); | ||||
| } | ||||
|  | ||||
| inline double divide( double a, double b ) { | ||||
|     return a/b; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Approximate PI", "[Approx][PI]" ) | ||||
| { | ||||
|     REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ); | ||||
|     REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ); | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| TEST_CASE( "Absolute margin", "[Approx]" ) { | ||||
|     REQUIRE( 104.0 != Approx(100.0) ); | ||||
|     REQUIRE( 104.0 == Approx(100.0).margin(5) ); | ||||
|     REQUIRE( 104.0 == Approx(100.0).margin(4) ); | ||||
|     REQUIRE( 104.0 != Approx(100.0).margin(3) ); | ||||
|     REQUIRE( 100.3 != Approx(100.0) ); | ||||
|     REQUIRE( 100.3 == Approx(100.0).margin(0.5) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Approx with exactly-representable margin", "[Approx]") { | ||||
|     CHECK( 0.25f == Approx(0.0f).margin(0.25f) ); | ||||
|  | ||||
|     CHECK( 0.0f == Approx(0.25f).margin(0.25f) ); | ||||
|     CHECK( 0.5f == Approx(0.25f).margin(0.25f) ); | ||||
|  | ||||
|     CHECK( 245.0f == Approx(245.25f).margin(0.25f) ); | ||||
|     CHECK( 245.5f == Approx(245.25f).margin(0.25f) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Approx setters validate their arguments", "[Approx]") { | ||||
|     REQUIRE_NOTHROW(Approx(0).margin(0)); | ||||
|     REQUIRE_NOTHROW(Approx(0).margin(1234656)); | ||||
|  | ||||
|     REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error); | ||||
|  | ||||
|     REQUIRE_NOTHROW(Approx(0).epsilon(0)); | ||||
|     REQUIRE_NOTHROW(Approx(0).epsilon(1)); | ||||
|  | ||||
|     REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error); | ||||
|     REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Default scale is invisible to comparison", "[Approx]") { | ||||
|     REQUIRE(101.000001 != Approx(100).epsilon(0.01)); | ||||
|     REQUIRE(std::pow(10, -5) != Approx(std::pow(10, -7))); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") { | ||||
|     REQUIRE(101.01 != Approx(100).epsilon(0.01)); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Assorted miscellaneous tests", "[Approx]") { | ||||
|     REQUIRE(INFINITY == Approx(INFINITY)); | ||||
|     REQUIRE(NAN != Approx(NAN)); | ||||
|     REQUIRE_FALSE(NAN == Approx(NAN)); | ||||
| } | ||||
|  | ||||
| class StrongDoubleTypedef | ||||
| { | ||||
|   double d_ = 0.0; | ||||
|  | ||||
|   public: | ||||
|     explicit StrongDoubleTypedef(double d) : d_(d) {} | ||||
|     explicit operator double() const { return d_; } | ||||
| }; | ||||
|  | ||||
| inline std::ostream& operator<<( std::ostream& os, StrongDoubleTypedef td ) { | ||||
|     return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")"; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" ) | ||||
| { | ||||
|   StrongDoubleTypedef td(10.0); | ||||
|  | ||||
|   REQUIRE(td == Approx(10.0)); | ||||
|   REQUIRE(Approx(10.0) == td); | ||||
|  | ||||
|   REQUIRE(td != Approx(11.0)); | ||||
|   REQUIRE(Approx(11.0) != td); | ||||
|  | ||||
|   REQUIRE(td <= Approx(10.0)); | ||||
|   REQUIRE(td <= Approx(11.0)); | ||||
|   REQUIRE(Approx(10.0) <= td); | ||||
|   REQUIRE(Approx(9.0) <= td); | ||||
|  | ||||
|   REQUIRE(td >= Approx(9.0)); | ||||
|   REQUIRE(td >= Approx(10.0)); | ||||
|   REQUIRE(Approx(10.0) >= td); | ||||
|   REQUIRE(Approx(11.0) >= td); | ||||
|  | ||||
| } | ||||
							
								
								
									
										103
									
								
								projects/SelfTest/UsageTests/BDDTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								projects/SelfTest/UsageTests/BDDTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| /* | ||||
|  *  Created by Phil on 29/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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| inline bool itDoesThis(){ return true; } | ||||
| inline bool itDoesThat(){ return true; } | ||||
|  | ||||
| SCENARIO( "Do that thing with the thing", "[Tags]" ) { | ||||
|     GIVEN( "This stuff exists" ) { | ||||
|         // make stuff exist | ||||
|         WHEN( "I do this" ) { | ||||
|             // do this | ||||
|             THEN( "it should do this") | ||||
|             { | ||||
|                 REQUIRE( itDoesThis() ); | ||||
|                 AND_THEN( "do that") | ||||
|                     REQUIRE( itDoesThat() ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capacity]" ) { | ||||
|     GIVEN( "an empty vector" ) { | ||||
|         std::vector<int> v; | ||||
|         REQUIRE( v.size() == 0 ); | ||||
|  | ||||
|         WHEN( "it is made larger" ) { | ||||
|             v.resize( 10 ); | ||||
|             THEN( "the size and capacity go up" ) { | ||||
|                 REQUIRE( v.size() == 10 ); | ||||
|                 REQUIRE( v.capacity() >= 10 ); | ||||
|  | ||||
|                 AND_WHEN( "it is made smaller again" ) { | ||||
|                     v.resize( 5 ); | ||||
|                     THEN( "the size goes down but the capacity stays the same" ) { | ||||
|                         REQUIRE( v.size() == 5 ); | ||||
|                         REQUIRE( v.capacity() >= 10 ); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         WHEN( "we reserve more space" ) { | ||||
|             v.reserve( 10 ); | ||||
|             THEN( "The capacity is increased but the size remains the same" ) { | ||||
|                 REQUIRE( v.capacity() >= 10 ); | ||||
|                 REQUIRE( v.size() == 0 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| SCENARIO(   "This is a really long scenario name to see how the list command deals with wrapping", | ||||
|             "[very long tags][lots][long][tags][verbose]" | ||||
|             "[one very long tag name that should cause line wrapping writing out using the list command]" | ||||
|             "[anotherReallyLongTagNameButThisOneHasNoObviousWrapPointsSoShouldSplitWithinAWordUsingADashCharacter]" ) { | ||||
|     GIVEN( "A section name that is so long that it cannot fit in a single console width" ) | ||||
|         WHEN( "The test headers are printed as part of the normal running of the scenario" ) | ||||
|             THEN( "The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" ) | ||||
|                 SUCCEED("boo!"); | ||||
| } | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| // a trivial fixture example to support SCENARIO_METHOD tests | ||||
| struct Fixture | ||||
| { | ||||
|     Fixture() | ||||
|     : d_counter(0) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     int counter() | ||||
|     { | ||||
|         return d_counter++; | ||||
|     } | ||||
|  | ||||
|     int d_counter; | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| SCENARIO_METHOD(Fixture, | ||||
|     "BDD tests requiring Fixtures to provide commonly-accessed data or methods", | ||||
|     "[bdd][fixtures]") { | ||||
|     const int before(counter()); | ||||
|     GIVEN("No operations precede me") { | ||||
|         REQUIRE(before == 0); | ||||
|         WHEN("We get the count") { | ||||
|             const int after(counter()); | ||||
|             THEN("Subsequently values are higher") { | ||||
|                 REQUIRE(after > before); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								projects/SelfTest/UsageTests/Benchmark.tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								projects/SelfTest/UsageTests/Benchmark.tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <map> | ||||
|  | ||||
| TEST_CASE( "benchmarked", "[!benchmark]" ) { | ||||
|  | ||||
|     static const int size = 100; | ||||
|  | ||||
|     std::vector<int> v; | ||||
|     std::map<int, int> m; | ||||
|  | ||||
|     BENCHMARK( "Load up a vector" ) { | ||||
|         v = std::vector<int>(); | ||||
|         for(int i =0; i < size; ++i ) | ||||
|             v.push_back( i ); | ||||
|     } | ||||
|     REQUIRE( v.size() == size ); | ||||
|  | ||||
|     BENCHMARK( "Load up a map" ) { | ||||
|         m = std::map<int, int>(); | ||||
|         for(int i =0; i < size; ++i ) | ||||
|             m.insert( { i, i+1 } ); | ||||
|     } | ||||
|     REQUIRE( m.size() == size ); | ||||
|  | ||||
|     BENCHMARK( "Reserved vector" ) { | ||||
|         v = std::vector<int>(); | ||||
|         v.reserve(size); | ||||
|         for(int i =0; i < size; ++i ) | ||||
|             v.push_back( i ); | ||||
|     } | ||||
|     REQUIRE( v.size() == size ); | ||||
|  | ||||
|     int array[size]; | ||||
|     BENCHMARK( "A fixed size array that should require no allocations" ) { | ||||
|         for(int i =0; i < size; ++i ) | ||||
|             array[i] = i; | ||||
|     } | ||||
|     int sum = 0; | ||||
|     for(int i =0; i < size; ++i ) | ||||
|         sum += array[i]; | ||||
|     REQUIRE( sum > size ); | ||||
| } | ||||
							
								
								
									
										57
									
								
								projects/SelfTest/UsageTests/ClassTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								projects/SelfTest/UsageTests/ClassTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  *  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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     class TestClass | ||||
|     { | ||||
|         std::string s; | ||||
|  | ||||
|     public: | ||||
|         TestClass() | ||||
|         : s( "hello" ) | ||||
|         {} | ||||
|  | ||||
|         void succeedingCase() | ||||
|         { | ||||
|             REQUIRE( s == "hello" ); | ||||
|         } | ||||
|         void failingCase() | ||||
|         { | ||||
|             REQUIRE( s == "world" ); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
|  | ||||
| METHOD_AS_TEST_CASE( TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" ) | ||||
| METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" ) | ||||
|  | ||||
|  | ||||
| struct Fixture | ||||
| { | ||||
|     Fixture() : m_a( 1 ) {} | ||||
|  | ||||
|     int m_a; | ||||
| }; | ||||
|  | ||||
| TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[class]" ) | ||||
| { | ||||
|     REQUIRE( m_a == 1 ); | ||||
| } | ||||
|  | ||||
| // We should be able to write our tests within a different namespace | ||||
| namespace Inner | ||||
| { | ||||
|     TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that fails", "[.][class][failing]" ) | ||||
|     { | ||||
|         REQUIRE( m_a == 2 ); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										97
									
								
								projects/SelfTest/UsageTests/CompilationTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								projects/SelfTest/UsageTests/CompilationTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /* | ||||
|  *  Created by Martin on 17/02/2017. | ||||
|  * | ||||
|  *  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 "catch.hpp" | ||||
|  | ||||
|  | ||||
| // This is a minimal example for an issue we have found in 1.7.0 | ||||
| struct foo { | ||||
|     int i; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| bool operator==(const T& val, foo f){ | ||||
|     return val == f.i; | ||||
| } | ||||
|  | ||||
| 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 | ||||
|  | ||||
| void throws_int(bool b) { | ||||
|     if (b) { | ||||
|         throw 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| 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)); | ||||
| #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||
|     REQUIRE_THAT("aaa", Catch::EndsWith("aaa")); | ||||
| #endif | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| TEST_CASE("#833") { | ||||
|     REQUIRE(templated_tests<int>(3)); | ||||
| } | ||||
|  | ||||
| #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 | ||||
|  | ||||
| // Test containing example where original stream insertable check breaks compilation | ||||
| namespace { | ||||
|     struct A {}; | ||||
|     std::ostream& operator<< (std::ostream &o, const A &) { return o << 0; } | ||||
|  | ||||
|     struct B : private A { | ||||
|         bool operator== (int) const { return true; } | ||||
|     }; | ||||
|  | ||||
|     B f (); | ||||
|     std::ostream g (); | ||||
| } | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| TEST_CASE( "#872" ) { | ||||
|     A dummy; | ||||
|     CAPTURE( dummy ); | ||||
|     B x; | ||||
|     REQUIRE (x == 4); | ||||
| } | ||||
|  | ||||
| struct Y { | ||||
|     uint32_t v : 1; | ||||
| }; | ||||
|  | ||||
| TEST_CASE( "#1027" ) { | ||||
|     Y y{ 0 }; | ||||
|     REQUIRE(y.v == 0); | ||||
|     REQUIRE(0 == y.v); | ||||
| } | ||||
							
								
								
									
										325
									
								
								projects/SelfTest/UsageTests/ConditionTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								projects/SelfTest/UsageTests/ConditionTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,325 @@ | ||||
| /* | ||||
|  *  Created by Phil on 08/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 push | ||||
| #   pragma clang diagnostic ignored "-Wpadded" | ||||
| #   pragma clang diagnostic ignored "-Wdouble-promotion" | ||||
| #endif | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <string> | ||||
| #include <limits> | ||||
| #include <cstdint> | ||||
|  | ||||
| struct TestData { | ||||
|     int int_seven = 7; | ||||
|     std::string str_hello = "hello"; | ||||
|     float float_nine_point_one = 9.1f; | ||||
|     double double_pi = 3.1415926535; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct TestDef { | ||||
|     TestDef& operator + ( const std::string& ) { | ||||
|         return *this; | ||||
|     } | ||||
|     TestDef& operator[]( const std::string& ) { | ||||
|         return *this; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // The "failing" tests all use the CHECK macro, which continues if the specific test fails. | ||||
| // This allows us to see all results, even if an earlier check fails | ||||
|  | ||||
| // Equality tests | ||||
| TEST_CASE( "Equality checks that should succeed" ) | ||||
| { | ||||
|  | ||||
|     TestDef td; | ||||
|     td + "hello" + "hello"; | ||||
|  | ||||
|     TestData data; | ||||
|  | ||||
|     REQUIRE( data.int_seven == 7 ); | ||||
|     REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ); | ||||
|     REQUIRE( data.double_pi == Approx( 3.1415926535 ) ); | ||||
|     REQUIRE( data.str_hello == "hello" ); | ||||
|     REQUIRE( "hello" == data.str_hello ); | ||||
|     REQUIRE( data.str_hello.size() == 5 ); | ||||
|  | ||||
|     double x = 1.1 + 0.1 + 0.1; | ||||
|     REQUIRE( x == Approx( 1.3 ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" ) | ||||
| { | ||||
|     TestData data; | ||||
|  | ||||
|     CHECK( data.int_seven == 6 ); | ||||
|     CHECK( data.int_seven == 8 ); | ||||
|     CHECK( data.int_seven == 0 ); | ||||
|     CHECK( data.float_nine_point_one == Approx( 9.11f ) ); | ||||
|     CHECK( data.float_nine_point_one == Approx( 9.0f ) ); | ||||
|     CHECK( data.float_nine_point_one == Approx( 1 ) ); | ||||
|     CHECK( data.float_nine_point_one == Approx( 0 ) ); | ||||
|     CHECK( data.double_pi == Approx( 3.1415 ) ); | ||||
|     CHECK( data.str_hello == "goodbye" ); | ||||
|     CHECK( data.str_hello == "hell" ); | ||||
|     CHECK( data.str_hello == "hello1" ); | ||||
|     CHECK( data.str_hello.size() == 6 ); | ||||
|  | ||||
|     double x = 1.1 + 0.1 + 0.1; | ||||
|     CHECK( x == Approx( 1.301 ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Inequality checks that should succeed" ) | ||||
| { | ||||
|     TestData data; | ||||
|  | ||||
|     REQUIRE( data.int_seven != 6 ); | ||||
|     REQUIRE( data.int_seven != 8 ); | ||||
|     REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ); | ||||
|     REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ); | ||||
|     REQUIRE( data.float_nine_point_one != Approx( 1 ) ); | ||||
|     REQUIRE( data.float_nine_point_one != Approx( 0 ) ); | ||||
|     REQUIRE( data.double_pi != Approx( 3.1415 ) ); | ||||
|     REQUIRE( data.str_hello != "goodbye" ); | ||||
|     REQUIRE( data.str_hello != "hell" ); | ||||
|     REQUIRE( data.str_hello != "hello1" ); | ||||
|     REQUIRE( data.str_hello.size() != 6 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Inequality checks that should fail", "[.][failing][!shouldfail]" ) | ||||
| { | ||||
|     TestData data; | ||||
|  | ||||
|     CHECK( data.int_seven != 7 ); | ||||
|     CHECK( data.float_nine_point_one != Approx( 9.1f ) ); | ||||
|     CHECK( data.double_pi != Approx( 3.1415926535 ) ); | ||||
|     CHECK( data.str_hello != "hello" ); | ||||
|     CHECK( data.str_hello.size() != 5 ); | ||||
| } | ||||
|  | ||||
| // Ordering comparison tests | ||||
| TEST_CASE( "Ordering comparison checks that should succeed" ) | ||||
| { | ||||
|     TestData data; | ||||
|  | ||||
|     REQUIRE( data.int_seven < 8 ); | ||||
|     REQUIRE( data.int_seven > 6 ); | ||||
|     REQUIRE( data.int_seven > 0 ); | ||||
|     REQUIRE( data.int_seven > -1 ); | ||||
|  | ||||
|     REQUIRE( data.int_seven >= 7 ); | ||||
|     REQUIRE( data.int_seven >= 6 ); | ||||
|     REQUIRE( data.int_seven <= 7 ); | ||||
|     REQUIRE( data.int_seven <= 8 ); | ||||
|  | ||||
|     REQUIRE( data.float_nine_point_one > 9 ); | ||||
|     REQUIRE( data.float_nine_point_one < 10 ); | ||||
|     REQUIRE( data.float_nine_point_one < 9.2 ); | ||||
|  | ||||
|     REQUIRE( data.str_hello <= "hello" ); | ||||
|     REQUIRE( data.str_hello >= "hello" ); | ||||
|  | ||||
|     REQUIRE( data.str_hello < "hellp" ); | ||||
|     REQUIRE( data.str_hello < "zebra" ); | ||||
|     REQUIRE( data.str_hello > "hellm" ); | ||||
|     REQUIRE( data.str_hello > "a" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) | ||||
| { | ||||
|     TestData data; | ||||
|  | ||||
|     CHECK( data.int_seven > 7 ); | ||||
|     CHECK( data.int_seven < 7 ); | ||||
|     CHECK( data.int_seven > 8 ); | ||||
|     CHECK( data.int_seven < 6 ); | ||||
|     CHECK( data.int_seven < 0 ); | ||||
|     CHECK( data.int_seven < -1 ); | ||||
|  | ||||
|     CHECK( data.int_seven >= 8 ); | ||||
|     CHECK( data.int_seven <= 6 ); | ||||
|  | ||||
|     CHECK( data.float_nine_point_one < 9 ); | ||||
|     CHECK( data.float_nine_point_one > 10 ); | ||||
|     CHECK( data.float_nine_point_one > 9.2 ); | ||||
|  | ||||
|     CHECK( data.str_hello > "hello" ); | ||||
|     CHECK( data.str_hello < "hello" ); | ||||
|     CHECK( data.str_hello > "hellp" ); | ||||
|     CHECK( data.str_hello > "z" ); | ||||
|     CHECK( data.str_hello < "hellm" ); | ||||
|     CHECK( data.str_hello < "a" ); | ||||
|  | ||||
|     CHECK( data.str_hello >= "z" ); | ||||
|     CHECK( data.str_hello <= "a" ); | ||||
| } | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #   pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
|  | ||||
| // Comparisons with int literals | ||||
| TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned" ) | ||||
| { | ||||
|     int i = 1; | ||||
|     unsigned int ui = 2; | ||||
|     long l = 3; | ||||
|     unsigned long ul = 4; | ||||
|     char c = 5; | ||||
|     unsigned char uc = 6; | ||||
|  | ||||
|     REQUIRE( i == 1 ); | ||||
|     REQUIRE( ui == 2 ); | ||||
|     REQUIRE( l == 3 ); | ||||
|     REQUIRE( ul == 4 ); | ||||
|     REQUIRE( c == 5 ); | ||||
|     REQUIRE( uc == 6 ); | ||||
|  | ||||
|     REQUIRE( 1 == i ); | ||||
|     REQUIRE( 2 == ui ); | ||||
|     REQUIRE( 3 == l ); | ||||
|     REQUIRE( 4 == ul ); | ||||
|     REQUIRE( 5 == c ); | ||||
|     REQUIRE( 6 == uc ); | ||||
|  | ||||
|     REQUIRE( (std::numeric_limits<uint32_t>::max)() > ul ); | ||||
| } | ||||
|  | ||||
| // Disable warnings about sign conversions for the next two tests | ||||
| // (as we are deliberately invoking them) | ||||
| // - Currently only disabled for GCC/ LLVM. Should add VC++ too | ||||
| #ifdef  __GNUC__ | ||||
| #pragma GCC diagnostic push | ||||
| #pragma GCC diagnostic ignored "-Wsign-compare" | ||||
| #pragma GCC diagnostic ignored "-Wsign-conversion" | ||||
| #endif | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning(disable:4389) // '==' : signed/unsigned mismatch | ||||
| #endif | ||||
|  | ||||
| TEST_CASE( "comparisons between int variables" ) | ||||
| { | ||||
|     long            long_var = 1L; | ||||
|     unsigned char    unsigned_char_var = 1; | ||||
|     unsigned short    unsigned_short_var = 1; | ||||
|     unsigned int    unsigned_int_var = 1; | ||||
|     unsigned long    unsigned_long_var = 1L; | ||||
|  | ||||
|     REQUIRE( long_var == unsigned_char_var ); | ||||
|     REQUIRE( long_var == unsigned_short_var ); | ||||
|     REQUIRE( long_var == unsigned_int_var ); | ||||
|     REQUIRE( long_var == unsigned_long_var ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "comparisons between const int variables" ) | ||||
| { | ||||
|     const unsigned char     unsigned_char_var = 1; | ||||
|     const unsigned short    unsigned_short_var = 1; | ||||
|     const unsigned int      unsigned_int_var = 1; | ||||
|     const unsigned long     unsigned_long_var = 1L; | ||||
|  | ||||
|     REQUIRE( unsigned_char_var == 1 ); | ||||
|     REQUIRE( unsigned_short_var == 1 ); | ||||
|     REQUIRE( unsigned_int_var == 1 ); | ||||
|     REQUIRE( unsigned_long_var == 1 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" ) | ||||
| { | ||||
|     CHECK( ( -1 > 2u ) ); | ||||
|     CHECK( -1 > 2u ); | ||||
|  | ||||
|     CHECK( ( 2u < -1 ) ); | ||||
|     CHECK( 2u < -1 ); | ||||
|  | ||||
|     const int minInt = (std::numeric_limits<int>::min)(); | ||||
|     CHECK( ( minInt > 2u ) ); | ||||
|     CHECK( minInt > 2u ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Comparisons between ints where one side is computed" ) | ||||
| { | ||||
|      CHECK( 54 == 6*9 ); | ||||
| } | ||||
|  | ||||
| #ifdef  __GNUC__ | ||||
| #pragma GCC diagnostic pop | ||||
| #endif | ||||
|  | ||||
| inline const char* returnsConstNull(){ return nullptr; } | ||||
| inline char* returnsNull(){ return nullptr; } | ||||
|  | ||||
| TEST_CASE( "Pointers can be compared to null" ) | ||||
| { | ||||
|     TestData* p = nullptr; | ||||
|     TestData* pNULL = nullptr; | ||||
|  | ||||
|     REQUIRE( p == nullptr ); | ||||
|     REQUIRE( p == pNULL ); | ||||
|  | ||||
|     TestData data; | ||||
|     p = &data; | ||||
|  | ||||
|     REQUIRE( p != nullptr ); | ||||
|  | ||||
|     const TestData* cp = p; | ||||
|     REQUIRE( cp != nullptr ); | ||||
|  | ||||
|     const TestData* const cpc = p; | ||||
|     REQUIRE( cpc != nullptr ); | ||||
|  | ||||
|     REQUIRE( returnsNull() == nullptr ); | ||||
|     REQUIRE( returnsConstNull() == nullptr ); | ||||
|  | ||||
|     REQUIRE( nullptr != p ); | ||||
| } | ||||
|  | ||||
| // Not (!) tests | ||||
| // The problem with the ! operator is that it has right-to-left associativity. | ||||
| // This means we can't isolate it when we decompose. The simple REQUIRE( !false ) form, therefore, | ||||
| // cannot have the operand value extracted. The test will work correctly, and the situation | ||||
| // is detected and a warning issued. | ||||
| // An alternative form of the macros (CHECK_FALSE and REQUIRE_FALSE) can be used instead to capture | ||||
| // the operand value. | ||||
| TEST_CASE( "'Not' checks that should succeed" ) | ||||
| { | ||||
|     bool falseValue = false; | ||||
|  | ||||
|     REQUIRE( false == false ); | ||||
|     REQUIRE( true == true ); | ||||
|     REQUIRE( !false ); | ||||
|     REQUIRE_FALSE( false ); | ||||
|  | ||||
|     REQUIRE( !falseValue ); | ||||
|     REQUIRE_FALSE( falseValue ); | ||||
|  | ||||
|     REQUIRE( !(1 == 2) ); | ||||
|     REQUIRE_FALSE( 1 == 2 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "'Not' checks that should fail", "[.][failing]" ) | ||||
| { | ||||
|     bool trueValue = true; | ||||
|  | ||||
|     CHECK( false != false ); | ||||
|     CHECK( true != true ); | ||||
|     CHECK( !true ); | ||||
|     CHECK_FALSE( true ); | ||||
|  | ||||
|     CHECK( !trueValue ); | ||||
|     CHECK_FALSE( trueValue ); | ||||
|  | ||||
|     CHECK( !(1 == 1) ); | ||||
|     CHECK_FALSE( 1 == 1 ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										35
									
								
								projects/SelfTest/UsageTests/DecompositionTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								projects/SelfTest/UsageTests/DecompositionTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|  *  Created by Martin on 27/5/2017. | ||||
|  *  Copyright 2017 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) | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <cstdio> | ||||
|  | ||||
| struct truthy { | ||||
|     truthy(bool b):m_value(b){} | ||||
|     operator bool() const { | ||||
|         return false; | ||||
|     } | ||||
|     bool m_value; | ||||
| }; | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& o, truthy) { | ||||
|     o << "Hey, its truthy!"; | ||||
|     return o; | ||||
| } | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| TEST_CASE( "Reconstruction should be based on stringification: #914" , "[Decomposition][failing][.]") { | ||||
|     CHECK(truthy(false)); | ||||
| } | ||||
|  | ||||
| TEST_CASE("#1005: Comparing pointer to int and long (NULL can be either on various systems)", "[Decomposition]") { | ||||
|     FILE* fptr = nullptr; | ||||
|     REQUIRE(fptr == 0); | ||||
|     REQUIRE(fptr == 0l); | ||||
| } | ||||
							
								
								
									
										63
									
								
								projects/SelfTest/UsageTests/EnumToString.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								projects/SelfTest/UsageTests/EnumToString.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| #include "catch.hpp" | ||||
|  | ||||
|  | ||||
| // Enum without user-provided stream operator | ||||
| enum Enum1 { Enum1Value0, Enum1Value1 }; | ||||
|  | ||||
| TEST_CASE( "toString(enum)", "[toString][enum]" ) { | ||||
|     Enum1 e0 = Enum1Value0; | ||||
|     CHECK( ::Catch::Detail::stringify(e0) == "0" ); | ||||
|     Enum1 e1 = Enum1Value1; | ||||
|     CHECK( ::Catch::Detail::stringify(e1) == "1" ); | ||||
| } | ||||
|  | ||||
| // Enum with user-provided stream operator | ||||
| enum Enum2 { Enum2Value0, Enum2Value1 }; | ||||
|  | ||||
| std::ostream& operator<<( std::ostream& os, Enum2 v ) { | ||||
|     return os << "E2{" << static_cast<int>(v) << "}"; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { | ||||
|     Enum2 e0 = Enum2Value0; | ||||
|     CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" ); | ||||
|     Enum2 e1 = Enum2Value1; | ||||
|     CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" ); | ||||
| } | ||||
|  | ||||
| // Enum class without user-provided stream operator | ||||
| enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; | ||||
|  | ||||
| // This fails, but has been hidden for a while - not sure if it's a regression or if it never worked | ||||
| // - need to investigate | ||||
| TEST_CASE( "toString(enum class)", "[toString][enum][enumClass][.]" ) { | ||||
|     EnumClass1 e0 = EnumClass1::EnumClass1Value0; | ||||
|     CHECK( ::Catch::Detail::stringify(e0) == "0" ); | ||||
|     EnumClass1 e1 = EnumClass1::EnumClass1Value1; | ||||
|     CHECK( ::Catch::Detail::stringify(e1) == "1" ); | ||||
| } | ||||
|  | ||||
| // Enum class with user-provided stream operator | ||||
| enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 }; | ||||
|  | ||||
| std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { | ||||
|     switch( static_cast<int>( e2 ) ) { | ||||
|         case static_cast<int>( EnumClass2::EnumClass2Value0 ): | ||||
|             return os << "E2/V0"; | ||||
|         case static_cast<int>( EnumClass2::EnumClass2Value1 ): | ||||
|             return os << "E2/V1"; | ||||
|         default: | ||||
|             return os << "Unknown enum value " << static_cast<int>( e2 ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) { | ||||
|     EnumClass2 e0 = EnumClass2::EnumClass2Value0; | ||||
|     CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" ); | ||||
|     EnumClass2 e1 = EnumClass2::EnumClass2Value1; | ||||
|     CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" ); | ||||
|  | ||||
|     EnumClass2 e3 = static_cast<EnumClass2>(10); | ||||
|     CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										229
									
								
								projects/SelfTest/UsageTests/ExceptionTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								projects/SelfTest/UsageTests/ExceptionTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,229 @@ | ||||
| /* | ||||
|  *  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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <string> | ||||
| #include <stdexcept> | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection | ||||
| #endif | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wweak-vtables" | ||||
| #endif | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     inline int thisThrows() | ||||
|     { | ||||
|         if( Catch::alwaysTrue() ) | ||||
|             throw std::domain_error( "expected exception" ); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     int thisDoesntThrow() | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When checked exceptions are thrown they can be expected or unexpected", "[!throws]" ) | ||||
| { | ||||
|     REQUIRE_THROWS_AS( thisThrows(), std::domain_error ); | ||||
|     REQUIRE_NOTHROW( thisDoesntThrow() ); | ||||
|     REQUIRE_THROWS( thisThrows() ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Expected exceptions that don't throw or unexpected exceptions fail the test", "[.][failing][!throws]" ) | ||||
| { | ||||
|     CHECK_THROWS_AS( thisThrows(), std::string ); | ||||
|     CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ); | ||||
|     CHECK_NOTHROW( thisThrows() ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing][!throws]" ) | ||||
| { | ||||
|     if( Catch::alwaysTrue() ) | ||||
|         throw std::domain_error( "unexpected exception" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing][!throws]" ) | ||||
| { | ||||
|     CHECK( 1 == 1 ); | ||||
|     if( Catch::alwaysTrue() ) | ||||
|         throw std::domain_error( "unexpected exception" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing][!throws]" ) | ||||
| { | ||||
|     SECTION( "section name" ) | ||||
|     { | ||||
|         if( Catch::alwaysTrue() ) | ||||
|             throw std::domain_error( "unexpected exception" ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When unchecked exceptions are thrown from functions they are always failures", "[.][failing][!throws]" ) | ||||
| { | ||||
|     CHECK( thisThrows() == 0 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When unchecked exceptions are thrown during a REQUIRE the test should abort fail", "[.][failing][!throws]" ) | ||||
| { | ||||
|     REQUIRE( thisThrows() == 0 ); | ||||
|     FAIL( "This should never happen" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When unchecked exceptions are thrown during a CHECK the test should continue", "[.][failing][!throws]" ) | ||||
| { | ||||
|     try { | ||||
|         CHECK(thisThrows() == 0); | ||||
|     } | ||||
|     catch(...) { | ||||
|         FAIL( "This should never happen" ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "When unchecked exceptions are thrown, but caught, they do not affect the test", "[!throws]" ) | ||||
| { | ||||
|     try | ||||
|     { | ||||
|         throw std::domain_error( "unexpected exception" ); | ||||
|     } | ||||
|     catch(...) | ||||
|     { | ||||
|     } | ||||
| } | ||||
|  | ||||
| class CustomException | ||||
| { | ||||
| public: | ||||
|     CustomException( const std::string& msg ) | ||||
|     : m_msg( msg ) | ||||
|     {} | ||||
|  | ||||
|     std::string getMessage() const | ||||
|     { | ||||
|         return m_msg; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     std::string m_msg; | ||||
| }; | ||||
|  | ||||
| class CustomStdException : public std::exception | ||||
| { | ||||
| public: | ||||
|     CustomStdException( const std::string& msg ) | ||||
|     : m_msg( msg ) | ||||
|     {} | ||||
|     ~CustomStdException() noexcept {} | ||||
|  | ||||
|     std::string getMessage() const | ||||
|     { | ||||
|         return m_msg; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     std::string m_msg; | ||||
| }; | ||||
|  | ||||
|  | ||||
| CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) | ||||
| { | ||||
|     return ex.getMessage(); | ||||
| } | ||||
|  | ||||
| CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) | ||||
| { | ||||
|     return ex.getMessage(); | ||||
| } | ||||
|  | ||||
| CATCH_TRANSLATE_EXCEPTION( double& ex ) | ||||
| { | ||||
|     return Catch::Detail::stringify( ex ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Non-std exceptions can be translated", "[.][failing][!throws]" ) | ||||
| { | ||||
|     if( Catch::alwaysTrue() ) | ||||
|         throw CustomException( "custom exception" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing][!throws]" ) | ||||
| { | ||||
|     if( Catch::alwaysTrue() ) | ||||
|         throw CustomException( "custom std exception" ); | ||||
| } | ||||
|  | ||||
| inline void throwCustom() { | ||||
|     if( Catch::alwaysTrue() ) | ||||
|         throw CustomException( "custom exception - not std" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Custom exceptions can be translated when testing for nothrow", "[.][failing][!throws]" ) | ||||
| { | ||||
|     REQUIRE_NOTHROW( throwCustom() ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Custom exceptions can be translated when testing for throwing as something else", "[.][failing][!throws]" ) | ||||
| { | ||||
|     REQUIRE_THROWS_AS( throwCustom(), std::exception ); | ||||
| } | ||||
|  | ||||
|  | ||||
| TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]"  ) | ||||
| { | ||||
|     if( Catch::alwaysTrue() ) | ||||
|         throw double( 3.14 ); | ||||
| } | ||||
|  | ||||
| #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||
|  | ||||
| TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { | ||||
|     using namespace Catch::Matchers; | ||||
|     SECTION( "exact match" ) | ||||
|         REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); | ||||
|     SECTION( "different case" ) | ||||
|     REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ); | ||||
|     SECTION( "wildcarded" ) { | ||||
|         REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ); | ||||
|         REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ); | ||||
|         REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ); | ||||
|         REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!throws]" ) { | ||||
|     REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); | ||||
|     REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); | ||||
|     REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "#748 - captures with unexpected exceptions", "[.][failing][!throws][!shouldfail]" ) { | ||||
|     int answer = 42; | ||||
|     CAPTURE( answer ); | ||||
|     // the message should be printed on the first two sections but not on the third | ||||
|     SECTION( "outside assertions" ) { | ||||
|         thisThrows(); | ||||
|     } | ||||
|     SECTION( "inside REQUIRE_NOTHROW" ) { | ||||
|         REQUIRE_NOTHROW( thisThrows() ); | ||||
|     } | ||||
|     SECTION( "inside REQUIRE_THROWS" ) { | ||||
|         REQUIRE_THROWS( thisThrows() ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
							
								
								
									
										312
									
								
								projects/SelfTest/UsageTests/MatchersTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								projects/SelfTest/UsageTests/MatchersTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | ||||
| /* | ||||
|  *  Created by Phil on 21/02/2017. | ||||
|  *  Copyright 2017 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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <sstream> | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wweak-vtables" | ||||
| #pragma clang diagnostic ignored "-Wpadded" | ||||
| #endif | ||||
|  | ||||
| #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||
|  | ||||
| inline const char* testStringForMatching() | ||||
| { | ||||
|     return "this string contains 'abc' as a substring"; | ||||
| } | ||||
| inline const char* testStringForMatching2() | ||||
| { | ||||
|     return "some completely different text that contains one common word"; | ||||
| } | ||||
|  | ||||
| using namespace Catch::Matchers; | ||||
|  | ||||
| TEST_CASE("String matchers", "[matchers]" ) { | ||||
|     REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ); | ||||
|     REQUIRE_THAT( testStringForMatching(), Contains( "string", Catch::CaseSensitive::No )); | ||||
|     CHECK_THAT( testStringForMatching(), Contains( "abc" ) ); | ||||
|     CHECK_THAT( testStringForMatching(), Contains( "aBC", Catch::CaseSensitive::No )); | ||||
|  | ||||
|     CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ); | ||||
|     CHECK_THAT( testStringForMatching(), StartsWith( "THIS", Catch::CaseSensitive::No )); | ||||
|     CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ); | ||||
|     CHECK_THAT( testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No )); | ||||
|  | ||||
|     REQUIRE_THAT(testStringForMatching(), Matches("this string contains 'abc' as a substring")); | ||||
|     REQUIRE_THAT(testStringForMatching(), Matches("this string CONTAINS 'abc' as a substring", Catch::CaseSensitive::No)); | ||||
|     REQUIRE_THAT(testStringForMatching(), Matches("^this string contains 'abc' as a substring$")); | ||||
|     REQUIRE_THAT(testStringForMatching(), Matches("^.* 'abc' .*$")); | ||||
|     REQUIRE_THAT(testStringForMatching(), Matches("^.* 'ABC' .*$", Catch::CaseSensitive::No)); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Contains string matcher", "[.][failing][matchers]") { | ||||
|     CHECK_THAT( testStringForMatching(), Contains( "not there", Catch::CaseSensitive::No ) ); | ||||
|     CHECK_THAT( testStringForMatching(), Contains( "STRING" )); | ||||
| } | ||||
|  | ||||
| TEST_CASE("StartsWith string matcher", "[.][failing][matchers]") { | ||||
|     CHECK_THAT( testStringForMatching(), StartsWith( "This String" )); | ||||
|     CHECK_THAT( testStringForMatching(), StartsWith( "string", Catch::CaseSensitive::No ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("EndsWith string matcher", "[.][failing][matchers]") { | ||||
|     CHECK_THAT( testStringForMatching(), EndsWith( "Substring" )); | ||||
|     CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Equals string matcher", "[.][failing][matchers]") { | ||||
|     CHECK_THAT( testStringForMatching(), Equals( "this string contains 'ABC' as a substring" ) ); | ||||
|     CHECK_THAT( testStringForMatching(), Equals( "something else", Catch::CaseSensitive::No )); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Equals", "[matchers]") { | ||||
|     CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" )); | ||||
|     CHECK_THAT( testStringForMatching(), Equals( "this string contains 'ABC' as a substring", Catch::CaseSensitive::No ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Regex string matcher", "[matchers][.failing]") { | ||||
|     CHECK_THAT( testStringForMatching(), Matches("this STRING contains 'abc' as a substring")); | ||||
|     CHECK_THAT( testStringForMatching(), Matches("contains 'abc' as a substring")); | ||||
|     CHECK_THAT( testStringForMatching(), Matches("this string contains 'abc' as a")); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") | ||||
| { | ||||
|     CHECK_THAT( testStringForMatching(), | ||||
|                 Contains( "string" ) && | ||||
|                 Contains( "abc" ) && | ||||
|                 Contains( "substring" ) && | ||||
|                 Contains( "contains" ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") | ||||
| { | ||||
|     CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); | ||||
|     CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") | ||||
| { | ||||
|     CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Matchers can be composed with both && and || - failing", "[matchers][operators][operator||][operator&&][.failing]") | ||||
| { | ||||
|     CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") | ||||
| { | ||||
|     CHECK_THAT( testStringForMatching(), !Contains( "different" ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Matchers can be negated (Not) with the ! operator - failing", "[matchers][operators][not][.failing]") | ||||
| { | ||||
|     CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Vector matchers", "[matchers][vector]" ) { | ||||
|     std::vector<int> v; | ||||
|     v.push_back( 1 ); | ||||
|     v.push_back( 2 ); | ||||
|     v.push_back( 3 ); | ||||
|  | ||||
|     std::vector<int> v2; | ||||
|     v2.push_back( 1 ); | ||||
|     v2.push_back( 2 ); | ||||
|  | ||||
|     std::vector<int> empty; | ||||
|  | ||||
|     SECTION( "Contains (element)" ) { | ||||
|         CHECK_THAT( v, VectorContains( 1 ) ); | ||||
|         CHECK_THAT( v, VectorContains( 2 ) ); | ||||
|     } | ||||
|     SECTION( "Contains (vector)" ) { | ||||
|         CHECK_THAT( v, Contains( v2 ) ); | ||||
|         v2.push_back( 3 ); // now exactly matches | ||||
|         CHECK_THAT( v, Contains( v2 ) ); | ||||
|  | ||||
|         CHECK_THAT( v, Contains( empty) ); | ||||
|         CHECK_THAT( empty, Contains( empty) ); | ||||
|     } | ||||
|     SECTION( "Contains (element), composed" ) { | ||||
|         CHECK_THAT( v, VectorContains( 1 ) && VectorContains( 2 ) ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "Equals" ) { | ||||
|  | ||||
|         // Same vector | ||||
|         CHECK_THAT( v, Equals( v ) ); | ||||
|  | ||||
|         CHECK_THAT( empty, Equals( empty ) ); | ||||
|  | ||||
|         // Different vector with same elements | ||||
|         v2.push_back( 3 ); | ||||
|         CHECK_THAT( v, Equals( v2 ) ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Vector matchers that fail", "[matchers][vector][.][failing]" ) { | ||||
|     std::vector<int> v; | ||||
|     v.push_back( 1 ); | ||||
|     v.push_back( 2 ); | ||||
|     v.push_back( 3 ); | ||||
|  | ||||
|     std::vector<int> v2; | ||||
|     v2.push_back( 1 ); | ||||
|     v2.push_back( 2 ); | ||||
|  | ||||
|     std::vector<int> empty; | ||||
|  | ||||
|     SECTION( "Contains (element)" ) { | ||||
|         CHECK_THAT( v, VectorContains( -1 ) ); | ||||
|         CHECK_THAT( empty, VectorContains( 1 ) ); | ||||
|     } | ||||
|     SECTION( "Contains (vector)" ) { | ||||
|         CHECK_THAT( empty, Contains( v) ); | ||||
|         v2.push_back( 4 ); | ||||
|         CHECK_THAT( v, Contains( v2 ) ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "Equals" ) { | ||||
|  | ||||
|         CHECK_THAT( v, Equals( v2 ) ); | ||||
|         CHECK_THAT( v2, Equals( v ) ); | ||||
|         CHECK_THAT( empty, Equals( v ) ); | ||||
|         CHECK_THAT( v, Equals( empty ) ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection | ||||
| #endif | ||||
|  | ||||
| #include <exception> | ||||
|  | ||||
| struct SpecialException : std::exception { | ||||
|     SpecialException(int i_):i(i_) {} | ||||
|     int i; | ||||
| }; | ||||
|  | ||||
| void doesNotThrow() {} | ||||
|  | ||||
| [[noreturn]] | ||||
| void throws(int i) { | ||||
|     throw SpecialException{ i }; | ||||
| } | ||||
|  | ||||
| [[noreturn]] | ||||
| void throwsAsInt(int i) { | ||||
|     throw i; | ||||
| } | ||||
|  | ||||
| class ExceptionMatcher : public Catch::MatcherBase<SpecialException> { | ||||
|     int m_expected; | ||||
| public: | ||||
|     ExceptionMatcher(int i):m_expected(i) {} | ||||
|     bool match(SpecialException const& se) const override { | ||||
|         return se.i == m_expected; | ||||
|     } | ||||
|  | ||||
|     std::string describe() const override { | ||||
|         std::ostringstream ss; | ||||
|         ss << "special exception has value of " << m_expected; | ||||
|         return ss.str(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| TEST_CASE( "Exception matchers that succeed", "[matchers][exceptions][!throws]" ) { | ||||
|     CHECK_THROWS_MATCHES(throws(1), SpecialException, ExceptionMatcher{ 1 }); | ||||
|     REQUIRE_THROWS_MATCHES(throws(2), SpecialException, ExceptionMatcher{ 2 }); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") { | ||||
|     SECTION("No exception") { | ||||
|         CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }); | ||||
|         REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }); | ||||
|     } | ||||
|     SECTION("Type mismatch") { | ||||
|         CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 }); | ||||
|         REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 }); | ||||
|     } | ||||
|     SECTION("Contents are wrong") { | ||||
|         CHECK_THROWS_MATCHES(throws(3), SpecialException, ExceptionMatcher{ 1 }); | ||||
|         REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{ 1 }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE("Floating point matchers: float", "[matchers][floating-point]") { | ||||
|     SECTION("Margin") { | ||||
|         REQUIRE_THAT(1.f, WithinAbs(1.f, 0)); | ||||
|         REQUIRE_THAT(0.f, WithinAbs(1.f, 1)); | ||||
|  | ||||
|         REQUIRE_THAT(0.f, !WithinAbs(1.f, 0.99f)); | ||||
|         REQUIRE_THAT(0.f, !WithinAbs(1.f, 0.99f)); | ||||
|  | ||||
|         REQUIRE_THAT(0.f, WithinAbs(-0.f, 0)); | ||||
|         REQUIRE_THAT(NAN, !WithinAbs(NAN, 0)); | ||||
|     } | ||||
|     SECTION("ULPs") { | ||||
|         REQUIRE_THAT(1.f, WithinULP(1.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(std::nextafter(1.f, 2.f), WithinULP(1.f, 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1.f, 0.f), WithinULP(1.f, 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1.f, 2.f), !WithinULP(1.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(1.f, WithinULP(1.f, 0)); | ||||
|         REQUIRE_THAT(-0.f, WithinULP(0.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !WithinULP(NAN, 123)); | ||||
|     } | ||||
|     SECTION("Composed") { | ||||
|         REQUIRE_THAT(1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1)); | ||||
|         REQUIRE_THAT(1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") { | ||||
|     SECTION("Margin") { | ||||
|         REQUIRE_THAT(1., WithinAbs(1., 0)); | ||||
|         REQUIRE_THAT(0., WithinAbs(1., 1)); | ||||
|  | ||||
|         REQUIRE_THAT(0., !WithinAbs(1., 0.99)); | ||||
|         REQUIRE_THAT(0., !WithinAbs(1., 0.99)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !WithinAbs(NAN, 0)); | ||||
|     } | ||||
|     SECTION("ULPs") { | ||||
|         REQUIRE_THAT(1., WithinULP(1., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(std::nextafter(1., 2.), WithinULP(1., 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1., 0.), WithinULP(1., 1)); | ||||
|         REQUIRE_THAT(std::nextafter(1., 2.), !WithinULP(1., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(1., WithinULP(1., 0)); | ||||
|         REQUIRE_THAT(-0., WithinULP(0., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !WithinULP(NAN, 123)); | ||||
|     } | ||||
|     SECTION("Composed") { | ||||
|         REQUIRE_THAT(1., WithinAbs(1., 0.5) || WithinULP(2., 1)); | ||||
|         REQUIRE_THAT(1., WithinAbs(2., 0.5) || WithinULP(1., 0)); | ||||
|  | ||||
|         REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123))); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
							
								
								
									
										137
									
								
								projects/SelfTest/UsageTests/MessageTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								projects/SelfTest/UsageTests/MessageTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| /* | ||||
|  *  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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" | ||||
| #endif | ||||
|  | ||||
| TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) { | ||||
|     INFO( "this is a " << "message" );    // This should output the message if a failure occurs | ||||
|     WARN( "this is a " << "warning" );    // This should always output the message but then continue | ||||
| } | ||||
|  | ||||
| TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) { | ||||
|     SUCCEED( "this is a " << "success" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "INFO gets logged on failure", "[failing][messages][.]" ) { | ||||
|     INFO( "this message should be logged" ); | ||||
|     INFO( "so should this" ); | ||||
|     int a = 2; | ||||
|     REQUIRE( a == 1 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "INFO gets logged on failure, even if captured before successful assertions", "[failing][messages][.]" ) { | ||||
|     INFO( "this message may be logged later" ); | ||||
|     int a = 2; | ||||
|     CHECK( a == 2 ); | ||||
|  | ||||
|     INFO( "this message should be logged" ); | ||||
|  | ||||
|     CHECK( a == 1 ); | ||||
|  | ||||
|     INFO( "and this, but later" ); | ||||
|  | ||||
|     CHECK( a == 0 ); | ||||
|  | ||||
|     INFO( "but not this" ); | ||||
|  | ||||
|     CHECK( a == 2 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) { | ||||
|     FAIL( "This is a " << "failure" );    // This should output the message and abort | ||||
|     WARN( "We should never see this"); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "FAIL_CHECK does not abort the test", "[failing][messages][.]" ) { | ||||
|     FAIL_CHECK( "This is a " << "failure" );    // This should output the message then continue | ||||
|     WARN( "This message appears in the output"); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) { | ||||
|     FAIL(); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "SUCCESS does not require an argument", "[messages][.]" ) { | ||||
|    SUCCEED(); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) { | ||||
|     SECTION( "one" ) { | ||||
|         FAIL( "Message from section one" ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "two" ) { | ||||
|         FAIL( "Message from section two" ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) { | ||||
|     SECTION( "one" ) { | ||||
|         std::cout << "Message from section one" << std::endl; | ||||
|     } | ||||
|  | ||||
|     SECTION( "two" ) { | ||||
|         std::cout << "Message from section two" << std::endl; | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Standard error is reported and redirected", "[messages][.][approvals]" ) { | ||||
|     SECTION( "std::cerr" ) { | ||||
|         std::cerr << "Write to std::cerr" << std::endl; | ||||
|     } | ||||
|     SECTION( "std::clog" ) { | ||||
|         std::clog << "Write to std::clog" << std::endl; | ||||
|     } | ||||
|     SECTION( "Interleaved writes to cerr and clog" ) { | ||||
|         std::cerr << "Inter"; | ||||
|         std::clog << "leaved"; | ||||
|         std::cerr << ' '; | ||||
|         std::clog << "writes"; | ||||
|         std::cerr << " to error"; | ||||
|         std::clog << " streams" << std::endl; | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "INFO is reset for each loop", "[messages][failing][.]" ) { | ||||
|     for( int i=0; i<100; i++ ) | ||||
|     { | ||||
|         INFO( "current counter " << i ); | ||||
|         CAPTURE( i ); | ||||
|         REQUIRE( i < 10 ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "The NO_FAIL macro reports a failure but does not fail the test", "[messages]" ) { | ||||
|     CHECK_NOFAIL( 1 == 2 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "just info", "[info][isolated info][messages]" ) { | ||||
|     INFO( "this should never be seen" ); | ||||
| } | ||||
| TEST_CASE( "just failure", "[fail][isolated info][.][messages]" ) { | ||||
|     FAIL( "Previous info should not be seen" ); | ||||
| } | ||||
|  | ||||
|  | ||||
| TEST_CASE( "sends information to INFO", "[.][failing]" ) { | ||||
|     INFO( "hi" ); | ||||
|     int i = 7; | ||||
|     CAPTURE( i ); | ||||
|     REQUIRE( false ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Pointers can be converted to strings", "[messages][.][approvals]" ) { | ||||
|     int p; | ||||
|     WARN( "actual address of p: " << &p ); | ||||
|     WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) ); | ||||
| } | ||||
							
								
								
									
										332
									
								
								projects/SelfTest/UsageTests/MiscTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								projects/SelfTest/UsageTests/MiscTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | ||||
| /* | ||||
|  *  Created by Phil on 29/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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #   pragma clang diagnostic ignored "-Wc++98-compat" | ||||
| #   pragma clang diagnostic ignored "-Wc++98-compat-pedantic" | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #include <iostream> | ||||
| #include <cerrno> | ||||
| #include <limits> | ||||
| #include <sstream> | ||||
|  | ||||
| TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { | ||||
|     int a = 1; | ||||
|     int b = 2; | ||||
|  | ||||
|     SECTION( "s1", "doesn't equal" ) { | ||||
|         REQUIRE( a != b ); | ||||
|         REQUIRE( b != a ); | ||||
|     } | ||||
|  | ||||
|     SECTION( "s2", "not equal" ) { | ||||
|         REQUIRE( a != b); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) { | ||||
|     int a = 1; | ||||
|     int b = 2; | ||||
|  | ||||
|     SECTION( "s1", "doesn't equal" ) { | ||||
|         REQUIRE( a != b ); | ||||
|         REQUIRE( b != a ); | ||||
|  | ||||
|         SECTION( "s2", "not equal" ) { | ||||
|             REQUIRE( a != b); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) { | ||||
|     int a = 1; | ||||
|     int b = 2; | ||||
|  | ||||
|     SECTION( "s1", "doesn't equal" ) { | ||||
|         SECTION( "s2", "equal" ) { | ||||
|             REQUIRE( a == b ); | ||||
|         } | ||||
|  | ||||
|         SECTION( "s3", "not equal" ) { | ||||
|             REQUIRE( a != b ); | ||||
|         } | ||||
|         SECTION( "s4", "less than" ) { | ||||
|             REQUIRE( a < b ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "even more nested SECTION tests", "[sections]" ) { | ||||
|     SECTION( "c" ) { | ||||
|         SECTION( "d (leaf)" ) { | ||||
|             SUCCEED(""); // avoid failing due to no tests | ||||
|         } | ||||
|  | ||||
|         SECTION( "e (leaf)" ) { | ||||
|             SUCCEED(""); // avoid failing due to no tests | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     SECTION( "f (leaf)" ) { | ||||
|         SUCCEED(""); // avoid failing due to no tests | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) { | ||||
|     int a = 1; | ||||
|  | ||||
|     for( int b = 0; b < 10; ++b ) { | ||||
|         std::ostringstream oss; | ||||
|         oss << "b is currently: " << b; | ||||
|         SECTION( "s1", oss.str() ) { | ||||
|             CHECK( b > a ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "looped tests", "[.][failing]" ) { | ||||
|     static const int fib[]  = { 1, 1, 2, 3, 5, 8, 13, 21 }; | ||||
|  | ||||
|     for( std::size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) { | ||||
|         INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" ); | ||||
|         CHECK( ( fib[i] % 2 ) == 0 ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) { | ||||
|     std::cout << "A string sent directly to stdout" << std::endl; | ||||
|  | ||||
|     std::cerr << "A string sent directly to stderr" << std::endl; | ||||
| } | ||||
|  | ||||
| inline const char* makeString( bool makeNull ) { | ||||
|     return makeNull ? nullptr : "valid string"; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "null strings" ) { | ||||
|     REQUIRE( makeString( false ) != static_cast<char*>(nullptr)); | ||||
|     REQUIRE( makeString( true ) == static_cast<char*>(nullptr)); | ||||
| } | ||||
|  | ||||
|  | ||||
| inline bool testCheckedIf( bool flag )  { | ||||
|     CHECKED_IF( flag ) | ||||
|         return true; | ||||
|     else | ||||
|         return false; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "checkedIf" ) { | ||||
|     REQUIRE( testCheckedIf( true ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "checkedIf, failing", "[failing][.]" ) { | ||||
|     REQUIRE( testCheckedIf( false ) ); | ||||
| } | ||||
|  | ||||
| inline bool testCheckedElse( bool flag ) { | ||||
|     CHECKED_ELSE( flag ) | ||||
|         return false; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "checkedElse" ) { | ||||
|     REQUIRE( testCheckedElse( true ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "checkedElse, failing", "[failing][.]" ) { | ||||
|     REQUIRE( testCheckedElse( false ) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "xmlentitycheck" ) { | ||||
|     SECTION( "embedded xml", "<test>it should be possible to embed xml characters, such as <, \" or &, or even whole <xml>documents</xml> within an attribute</test>" ) { | ||||
|         SUCCEED(""); // We need this here to stop it failing due to no tests | ||||
|     } | ||||
|     SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) { | ||||
|         SUCCEED(""); // We need this here to stop it failing due to no tests | ||||
|     } | ||||
| } | ||||
|  | ||||
| TEST_CASE( "send a single char to INFO", "[failing][.]" ) { | ||||
|     INFO(3); | ||||
|     REQUIRE(false); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "atomic if", "[failing][0]") { | ||||
|     std::size_t x = 0; | ||||
|  | ||||
|     if( x ) | ||||
|         REQUIRE(x > 0); | ||||
|     else | ||||
|         REQUIRE(x == 0); | ||||
| } | ||||
|  | ||||
| inline unsigned int Factorial( unsigned int number )  { | ||||
|   return number > 1 ? Factorial(number-1)*number : 1; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Factorials are computed", "[factorial]" ) { | ||||
|   REQUIRE( Factorial(0) == 1 ); | ||||
|   REQUIRE( Factorial(1) == 1 ); | ||||
|   REQUIRE( Factorial(2) == 2 ); | ||||
|   REQUIRE( Factorial(3) == 6 ); | ||||
|   REQUIRE( Factorial(10) == 3628800 ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "An empty test with no assertions", "[empty]" ) {} | ||||
|  | ||||
| TEST_CASE( "Nice descriptive name", "[tag1][tag2][tag3][.]" ) { | ||||
|     WARN( "This one ran" ); | ||||
| } | ||||
| TEST_CASE( "first tag", "[tag1]" ) {} | ||||
| TEST_CASE( "second tag", "[tag2]" ) {} | ||||
|  | ||||
| // | ||||
| //TEST_CASE( "spawn a new process", "[.]" ) | ||||
| //{ | ||||
| //    // !TBD Work in progress | ||||
| //    char line[200]; | ||||
| //    FILE* output = popen("./CatchSelfTest ./failing/matchers/StartsWith", "r"); | ||||
| //    while ( fgets(line, 199, output) ) | ||||
| //        std::cout << line; | ||||
| //} | ||||
|  | ||||
| TEST_CASE( "vectors can be sized and resized", "[vector]" ) { | ||||
|  | ||||
|     std::vector<int> v( 5 ); | ||||
|  | ||||
|     REQUIRE( v.size() == 5 ); | ||||
|     REQUIRE( v.capacity() >= 5 ); | ||||
|  | ||||
|     SECTION( "resizing bigger changes size and capacity" ) { | ||||
|         v.resize( 10 ); | ||||
|  | ||||
|         REQUIRE( v.size() == 10 ); | ||||
|         REQUIRE( v.capacity() >= 10 ); | ||||
|     } | ||||
|     SECTION( "resizing smaller changes size but not capacity" ) { | ||||
|         v.resize( 0 ); | ||||
|  | ||||
|         REQUIRE( v.size() == 0 ); | ||||
|         REQUIRE( v.capacity() >= 5 ); | ||||
|  | ||||
|         SECTION( "We can use the 'swap trick' to reset the capacity" ) { | ||||
|             std::vector<int> empty; | ||||
|             empty.swap( v ); | ||||
|  | ||||
|             REQUIRE( v.capacity() == 0 ); | ||||
|         } | ||||
|     } | ||||
|     SECTION( "reserving bigger changes capacity but not size" ) { | ||||
|         v.reserve( 10 ); | ||||
|  | ||||
|         REQUIRE( v.size() == 5 ); | ||||
|         REQUIRE( v.capacity() >= 10 ); | ||||
|     } | ||||
|     SECTION( "reserving smaller does not change size or capacity" ) { | ||||
|         v.reserve( 0 ); | ||||
|  | ||||
|         REQUIRE( v.size() == 5 ); | ||||
|         REQUIRE( v.capacity() >= 5 ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // https://github.com/philsquared/Catch/issues/166 | ||||
| TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") { | ||||
|     SECTION("Outer", "") | ||||
|         SECTION("Inner", "") | ||||
|             SUCCEED("that's not flying - that's failing in style"); | ||||
|  | ||||
|     FAIL("to infinity and beyond"); | ||||
| } | ||||
|  | ||||
| TEST_CASE("not allowed", "[!throws]") { | ||||
|     // This test case should not be included if you run with -e on the command line | ||||
|     SUCCEED( "" ); | ||||
| } | ||||
|  | ||||
| //TEST_CASE( "Is big endian" ) { | ||||
| //    CHECK( Catch::Detail::Endianness::which() == Catch::Detail::Endianness::Little ); | ||||
| //} | ||||
|  | ||||
| TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) { | ||||
|  | ||||
|     // Based on issue #242 | ||||
|     std::string s1 = "if ($b == 10) {\n\t\t$a\t= 20;\n}"; | ||||
|     std::string s2 = "if ($b == 10) {\n\t$a = 20;\n}\n"; | ||||
|     CHECK( s1 == s2 ); | ||||
| } | ||||
|  | ||||
|  | ||||
| TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) { | ||||
|         const wchar_t * const s = L"wide load"; | ||||
|         std::string result = ::Catch::Detail::stringify( s ); | ||||
|         CHECK( result == "\"wide load\"" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) { | ||||
|         const wchar_t * s = L"wide load"; | ||||
|         std::string result = ::Catch::Detail::stringify( s ); | ||||
|         CHECK( result == "\"wide load\"" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) { | ||||
|         wchar_t * const s = const_cast<wchar_t* const>( L"wide load" ); | ||||
|         std::string result = ::Catch::Detail::stringify( s ); | ||||
|         CHECK( result == "\"wide load\"" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) { | ||||
|         wchar_t * s = const_cast<wchar_t*>( L"wide load" ); | ||||
|         std::string result = ::Catch::Detail::stringify( s ); | ||||
|         CHECK( result == "\"wide load\"" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "long long" ) { | ||||
|     long long l = std::numeric_limits<long long>::max(); | ||||
|  | ||||
|     REQUIRE( l == std::numeric_limits<long long>::max() ); | ||||
| } | ||||
|  | ||||
| //TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) { | ||||
| //    int i = 0; | ||||
| //    int x = 10/i; // This should cause the signal to fire | ||||
| //    CHECK( x == 0 ); | ||||
| //} | ||||
|  | ||||
| TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" ) { | ||||
|     SUCCEED( "oops!" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "# A test name that starts with a #" ) { | ||||
|     SUCCEED( "yay" ); | ||||
| } | ||||
|  | ||||
|  | ||||
| static int f() { | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "#835 -- errno should not be touched by Catch", "[.][failing][!shouldfail]" ) { | ||||
|     errno = 1; | ||||
|     CHECK(f() == 0); | ||||
|     REQUIRE(errno == 1); // Check that f() doesn't touch errno. | ||||
| } | ||||
|  | ||||
| TEST_CASE( "#961 -- Dynamically created sections should all be reported", "[.]" ) { | ||||
|     for (char i = '0'; i < '5'; ++i) { | ||||
|         SECTION(std::string("Looped section ") + i) { | ||||
|             SUCCEED( "Everything is OK" ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										41
									
								
								projects/SelfTest/UsageTests/ToStringChrono.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								projects/SelfTest/UsageTests/ToStringChrono.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <chrono> | ||||
| #include <cstdint> | ||||
|  | ||||
| TEST_CASE("Stringifying std::chrono::duration helpers", "[toString][chrono]") { | ||||
|     // No literals because we still support c++11 | ||||
|     auto hour = std::chrono::hours(1); | ||||
|     auto minute = std::chrono::minutes(1); | ||||
|     auto seconds = std::chrono::seconds(60); | ||||
|     auto micro = std::chrono::microseconds(1); | ||||
|     auto milli = std::chrono::milliseconds(1); | ||||
|     auto nano = std::chrono::nanoseconds(1); | ||||
|     REQUIRE(minute == seconds); | ||||
|     REQUIRE(hour != seconds); | ||||
|     REQUIRE(micro != milli); | ||||
|     REQUIRE(nano != micro); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Stringifying std::chrono::duration with weird ratios", "[toString][chrono]") { | ||||
|     std::chrono::duration<int64_t, std::ratio<30>> half_minute(1); | ||||
|     std::chrono::duration<int64_t, std::ratio<1, 1000000000000000>> femto_second(1); | ||||
|     REQUIRE(half_minute != femto_second); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Stringifying std::chrono::time_point<system_clock>", "[toString][chrono]") { | ||||
|     auto now = std::chrono::system_clock::now(); | ||||
|     auto later = now + std::chrono::minutes(2); | ||||
|     REQUIRE(now != later); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Stringifying std::chrono::time_point<Clock>", "[toString][chrono][!nonportable]") { | ||||
|     auto now = std::chrono::high_resolution_clock::now(); | ||||
|     auto later = now + std::chrono::minutes(2); | ||||
|     REQUIRE(now != later); | ||||
|  | ||||
|     auto now2 = std::chrono::steady_clock::now(); | ||||
|     auto later2 = now2 + std::chrono::minutes(2); | ||||
|     REQUIRE(now2 != later2); | ||||
| } | ||||
							
								
								
									
										53
									
								
								projects/SelfTest/UsageTests/ToStringGeneralTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								projects/SelfTest/UsageTests/ToStringGeneralTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  *  Created by Martin on 17/02/2017. | ||||
|  * | ||||
|  *  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 "catch.hpp" | ||||
|  | ||||
|  | ||||
| TEST_CASE( "Character pretty printing" ){ | ||||
|     SECTION("Specifically escaped"){ | ||||
|         char tab = '\t'; | ||||
|         char newline = '\n'; | ||||
|         char carr_return = '\r'; | ||||
|         char form_feed = '\f'; | ||||
|         CHECK(tab == '\t'); | ||||
|         CHECK(newline == '\n'); | ||||
|         CHECK(carr_return == '\r'); | ||||
|         CHECK(form_feed == '\f'); | ||||
|     } | ||||
|     SECTION("General chars"){ | ||||
|         char space = ' '; | ||||
|         CHECK(space == ' '); | ||||
|         char chars[] = {'a', 'z', 'A', 'Z'}; | ||||
|         for (int i = 0; i < 4; ++i){ | ||||
|             char c = chars[i]; | ||||
|             REQUIRE(c == chars[i]); | ||||
|         } | ||||
|     } | ||||
|     SECTION("Low ASCII"){ | ||||
|         char null_terminator = '\0'; | ||||
|         CHECK(null_terminator == '\0'); | ||||
|         for (int i = 2; i < 6; ++i){ | ||||
|             char c = static_cast<char>(i); | ||||
|             REQUIRE(c == i); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| TEST_CASE( "Capture and info messages" ) { | ||||
|     SECTION("Capture should stringify like assertions") { | ||||
|         int i = 2; | ||||
|         CAPTURE(i); | ||||
|         REQUIRE(true); | ||||
|     } | ||||
|     SECTION("Info should NOT stringify the way assertions do") { | ||||
|         int i = 3; | ||||
|         INFO(i); | ||||
|         REQUIRE(true); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										30
									
								
								projects/SelfTest/UsageTests/ToStringPair.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								projects/SelfTest/UsageTests/ToStringPair.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER | ||||
| #include "catch.hpp" | ||||
|  | ||||
| TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) { | ||||
|     std::pair<int,std::string> value( 34, "xyzzy" ); | ||||
|     REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "std::pair<int,const std::string> -> toString", "[toString][pair]" ) { | ||||
|     std::pair<int,const std::string> value( 34, "xyzzy" ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "std::vector<std::pair<std::string,int> > -> toString", "[toString][pair]" ) { | ||||
|     std::vector<std::pair<std::string,int> > pr; | ||||
|     pr.push_back( std::make_pair("green", 55 ) ); | ||||
|     REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" ); | ||||
| } | ||||
|  | ||||
| // This is pretty contrived - I figure if this works, anything will... | ||||
| TEST_CASE( "pair<pair<int,const char *,pair<std::string,int> > -> toString", "[toString][pair]" ) { | ||||
|     typedef std::pair<int,const char *> left_t; | ||||
|     typedef std::pair<std::string,int> right_t; | ||||
|  | ||||
|     left_t  left( 42, "Arthur" ); | ||||
|     right_t right( "Ford", 24 ); | ||||
|  | ||||
|     std::pair<left_t,right_t> pair( left, right ); | ||||
|     REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ); | ||||
| } | ||||
							
								
								
									
										47
									
								
								projects/SelfTest/UsageTests/ToStringTuple.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								projects/SelfTest/UsageTests/ToStringTuple.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| #define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <tuple> | ||||
|  | ||||
| TEST_CASE( "tuple<>", "[toString][tuple]" ) | ||||
| { | ||||
|     typedef std::tuple<> type; | ||||
|     CHECK( "{ }" == ::Catch::Detail::stringify(type{}) ); | ||||
|     type value {}; | ||||
|     CHECK( "{ }" == ::Catch::Detail::stringify(value) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "tuple<int>", "[toString][tuple]" ) | ||||
| { | ||||
|     typedef std::tuple<int> type; | ||||
|     CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) ); | ||||
| } | ||||
|  | ||||
|  | ||||
| TEST_CASE( "tuple<float,int>", "[toString][tuple]" ) | ||||
| { | ||||
|     typedef std::tuple<float,int> type; | ||||
|     CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) ); | ||||
|     CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "tuple<string,string>", "[toString][tuple]" ) | ||||
| { | ||||
|     typedef std::tuple<std::string,std::string> type; | ||||
|     CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "tuple<tuple<int>,tuple<>,float>", "[toString][tuple]" ) | ||||
| { | ||||
|     typedef std::tuple<std::tuple<int>,std::tuple<>,float> type; | ||||
|     type value { std::tuple<int>{42}, {}, 1.2f }; | ||||
|     CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "tuple<nullptr,int,const char *>", "[toString][tuple]" ) | ||||
| { | ||||
|     typedef std::tuple<std::nullptr_t,int,const char *> type; | ||||
|     type value { nullptr, 42, "Catch me" }; | ||||
|     CHECK( "{ nullptr, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										68
									
								
								projects/SelfTest/UsageTests/ToStringVector.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								projects/SelfTest/UsageTests/ToStringVector.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| #include "catch.hpp" | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| // vedctor | ||||
| TEST_CASE( "vector<int> -> toString", "[toString][vector]" ) | ||||
| { | ||||
|     std::vector<int> vv; | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" ); | ||||
|     vv.push_back( 42 ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ); | ||||
|     vv.push_back( 250 ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "vector<string> -> toString", "[toString][vector]" ) | ||||
| { | ||||
|     std::vector<std::string> vv; | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" ); | ||||
|     vv.push_back( "hello" ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" ); | ||||
|     vv.push_back( "world" ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" ); | ||||
| } | ||||
|  | ||||
| namespace { | ||||
|     /* Minimal Allocator */ | ||||
|     template<typename T> | ||||
|     struct minimal_allocator { | ||||
|         using value_type = T; | ||||
|         using size_type = std::size_t; | ||||
|  | ||||
|         minimal_allocator() = default; | ||||
|         template <typename U> | ||||
|         minimal_allocator(const minimal_allocator<U>&) {} | ||||
|  | ||||
|  | ||||
|         T *allocate( size_type n ) { | ||||
|             return static_cast<T *>( ::operator new( n * sizeof(T) ) ); | ||||
|         } | ||||
|         void deallocate( T *p, size_type /*n*/ ) { | ||||
|             ::operator delete( static_cast<void *>(p) ); | ||||
|         } | ||||
|         template<typename U> | ||||
|         bool operator==( const minimal_allocator<U>& ) const { return true; } | ||||
|         template<typename U> | ||||
|         bool operator!=( const minimal_allocator<U>& ) const { return false; } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| TEST_CASE( "vector<int,allocator> -> toString", "[toString][vector,allocator]" ) { | ||||
|     std::vector<int,minimal_allocator<int> > vv; | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" ); | ||||
|     vv.push_back( 42 ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ); | ||||
|     vv.push_back( 250 ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "vec<vec<string,alloc>> -> toString", "[toString][vector,allocator]" ) { | ||||
|     using inner = std::vector<std::string, minimal_allocator<std::string>>; | ||||
|     using vector = std::vector<inner>; | ||||
|     vector v; | ||||
|     REQUIRE( ::Catch::Detail::stringify(v) == "{  }" ); | ||||
|     v.push_back( inner { "hello" } ); | ||||
|     v.push_back( inner { "world" } ); | ||||
|     REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" ); | ||||
| } | ||||
							
								
								
									
										73
									
								
								projects/SelfTest/UsageTests/ToStringWhich.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								projects/SelfTest/UsageTests/ToStringWhich.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| #include "catch.hpp" | ||||
| /* | ||||
|     Demonstrate which version of toString/StringMaker is being used | ||||
|     for various types | ||||
| */ | ||||
|  | ||||
|  | ||||
| struct has_operator { }; | ||||
| struct has_maker {}; | ||||
| struct has_maker_and_operator {}; | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& os, const has_operator&) { | ||||
|     os << "operator<<( has_operator )"; | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& os, const has_maker_and_operator&) { | ||||
|     os << "operator<<( has_maker_and_operator )"; | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| namespace Catch { | ||||
|     template<> | ||||
|     struct StringMaker<has_maker> { | ||||
|         static std::string convert( const has_maker& ) { | ||||
|             return "StringMaker<has_maker>"; | ||||
|         } | ||||
|     }; | ||||
|     template<> | ||||
|     struct StringMaker<has_maker_and_operator> { | ||||
|         static std::string convert( const has_maker_and_operator& ) { | ||||
|             return "StringMaker<has_maker_and_operator>"; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| // Call the operator | ||||
| TEST_CASE( "stringify( has_operator )", "[toString]" ) { | ||||
|     has_operator item; | ||||
|     REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" ); | ||||
| } | ||||
|  | ||||
| // Call the stringmaker | ||||
| TEST_CASE( "stringify( has_maker )", "[toString]" ) { | ||||
|     has_maker item; | ||||
|     REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" ); | ||||
| } | ||||
|  | ||||
| // Call the stringmaker | ||||
| TEST_CASE( "stringify( has_maker_and_toString )", "[.][toString]" ) { | ||||
|     has_maker_and_operator item; | ||||
|     REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" ); | ||||
| } | ||||
|  | ||||
| // Vectors... | ||||
|  | ||||
| // Don't run this in approval tests as it is sensitive to two phase lookup differences | ||||
| TEST_CASE( "toString( vectors<has_toString )", "[.][toString][!nonportable]" ) { | ||||
|     std::vector<has_operator> v(1); | ||||
|     REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "toString( vectors<has_maker )", "[toString]" ) { | ||||
|     std::vector<has_maker> v(1); | ||||
|     REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" ); | ||||
| } | ||||
|  | ||||
|  | ||||
| // Don't run this in approval tests as it is sensitive to two phase lookup differences | ||||
| TEST_CASE( "toString( vectors<has_maker_and_toString )", "[.][toString][!nonportable]" ) { | ||||
|     std::vector<has_maker_and_operator> v(1); | ||||
|     REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_toString> }" ); | ||||
| } | ||||
							
								
								
									
										448
									
								
								projects/SelfTest/UsageTests/TrickyTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										448
									
								
								projects/SelfTest/UsageTests/TrickyTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,448 @@ | ||||
| /* | ||||
|  *  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( Catch::alwaysTrue() ); | ||||
|  | ||||
|     SECTION( "A section" ) | ||||
|     { | ||||
|         REQUIRE( Catch::alwaysTrue() ); | ||||
|  | ||||
|         SECTION( "Another section" ) | ||||
|         { | ||||
|             REQUIRE( Catch::alwaysTrue() ); | ||||
|         } | ||||
|         SECTION( "Another other section" ) | ||||
|         { | ||||
|             REQUIRE( Catch::alwaysTrue() ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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 ); | ||||
| } | ||||
							
								
								
									
										29
									
								
								projects/SelfTest/UsageTests/VariadicMacrosTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								projects/SelfTest/UsageTests/VariadicMacrosTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* | ||||
|  *  Created by Phil on 15/03/2013. | ||||
|  *  Copyright 2013 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) | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
|  | ||||
| TEST_CASE() | ||||
| { | ||||
|     SUCCEED( "anonymous test case" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Test case with one argument" ) | ||||
| { | ||||
|     SUCCEED( "no assertions" ); | ||||
| } | ||||
|  | ||||
| TEST_CASE( "Variadic macros", "[variadic][sections]" ) | ||||
| { | ||||
|     SECTION( "Section with one argument" ) | ||||
|     { | ||||
|         SUCCEED( "no assertions" ); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash