1 /* 2 * Created by Phil on 09/11/2010. 3 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 9 #ifdef __clang__ 10 #pragma clang diagnostic ignored "-Wpadded" 11 #endif 12 13 #ifdef _MSC_VER 14 #pragma warning (disable : 4702) // Disable unreachable code warning for the last test 15 // that is triggered when compiling as Win32|Release 16 #endif 17 18 #include "catch.hpp" 19 20 #include <stdio.h> 21 #include <sstream> 22 #include <iostream> 23 24 /////////////////////////////////////////////////////////////////////////////// 25 TEST_CASE 26 ( 27 "Where there is more to the expression after the RHS", 28 "[Tricky][failing][.]" 29 ) 30 { 31 // int a = 1, b = 2; 32 // REQUIRE( a == 2 || b == 2 ); 33 WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); 34 } 35 /////////////////////////////////////////////////////////////////////////////// 36 TEST_CASE 37 ( 38 "Where the LHS is not a simple value", 39 "[Tricky][failing][.]" 40 ) 41 { 42 /* 43 int a = 1; 44 int b = 2; 45 46 // This only captures part of the expression, but issues a warning about the rest 47 REQUIRE( a+1 == b-1 ); 48 */ 49 WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); 50 } 51 52 struct Opaque 53 { 54 int val; 55 bool operator ==( const Opaque& o ) const 56 { 57 return val == o.val; 58 } 59 }; 60 61 /////////////////////////////////////////////////////////////////////////////// 62 TEST_CASE 63 ( 64 "A failing expression with a non streamable type is still captured", 65 "[Tricky][failing][.]" 66 ) 67 { 68 69 Opaque o1, o2; 70 o1.val = 7; 71 o2.val = 8; 72 73 CHECK( &o1 == &o2 ); 74 CHECK( o1 == o2 ); 75 } 76 77 /////////////////////////////////////////////////////////////////////////////// 78 TEST_CASE 79 ( 80 "string literals of different sizes can be compared", 81 "[Tricky][failing][.]" 82 ) 83 { 84 REQUIRE( std::string( "first" ) == "second" ); 85 86 } 87 88 /////////////////////////////////////////////////////////////////////////////// 89 TEST_CASE 90 ( 91 "An expression with side-effects should only be evaluated once", 92 "[Tricky]" 93 ) 94 { 95 int i = 7; 96 97 REQUIRE( i++ == 7 ); 98 REQUIRE( i++ == 8 ); 99 100 } 101 102 namespace A { 103 struct X 104 { 105 X() : a(4), b(2), c(7) {} 106 X(int v) : a(v), b(2), c(7) {} 107 int a; 108 int b; 109 int c; 110 }; 111 } 112 113 namespace B { 114 struct Y 115 { 116 Y() : a(4), b(2), c(7) {} 117 Y(int v) : a(v), b(2), c(7) {} 118 int a; 119 int b; 120 int c; 121 }; 122 } 123 124 inline bool operator==(const A::X& lhs, const B::Y& rhs) 125 { 126 return (lhs.a == rhs.a); 127 } 128 129 inline bool operator==(const B::Y& lhs, const A::X& rhs) 130 { 131 return (lhs.a == rhs.a); 132 } 133 134 135 /////////////////////////////////////////////////////////////////////////////// 136 /* This, currently, does not compile with LLVM 137 TEST_CASE 138 ( 139 "Operators at different namespace levels not hijacked by Koenig lookup" 140 "[Tricky]" 141 ) 142 { 143 A::X x; 144 B::Y y; 145 REQUIRE( x == y ); 146 } 147 */ 148 149 namespace ObjectWithConversions 150 { 151 struct Object 152 { 153 operator unsigned int() const {return 0xc0000000;} 154 }; 155 156 /////////////////////////////////////////////////////////////////////////////// 157 TEST_CASE 158 ( 159 "Implicit conversions are supported inside assertion macros", 160 "[Tricky][approvals]" 161 ) 162 { 163 Object o; 164 REQUIRE(0xc0000000 == o ); 165 } 166 } 167 168 namespace EnumBitFieldTests 169 { 170 enum Bits : uint32_t { 171 bit0 = 0x0001, 172 bit1 = 0x0002, 173 bit2 = 0x0004, 174 bit3 = 0x0008, 175 bit1and2 = bit1 | bit2, 176 bit30 = 0x40000000, 177 bit31 = 0x80000000, 178 bit30and31 = bit30 | bit31 179 }; 180 181 TEST_CASE( "Test enum bit values", "[Tricky]" ) 182 { 183 REQUIRE( 0xc0000000 == bit30and31 ); 184 } 185 } 186 187 struct Obj 188 { 189 Obj():prop(&p){} 190 191 int p; 192 int* prop; 193 }; 194 195 TEST_CASE("boolean member", "[Tricky]") 196 { 197 Obj obj; 198 REQUIRE( obj.prop != nullptr ); 199 } 200 201 // Tests for a problem submitted by Ralph McArdell 202 // 203 // The static bool value should not need to be defined outside the 204 // struct it is declared in - but when evaluating it in a deduced 205 // context it appears to require the extra definition. 206 // The issue was fixed by adding bool overloads to bypass the 207 // templates that were there to deduce it. 208 template <bool B> 209 struct is_true 210 { 211 static const bool value = B; 212 }; 213 214 TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" ) 215 { 216 SECTION("compare to true") 217 { 218 REQUIRE( is_true<true>::value == true ); 219 REQUIRE( true == is_true<true>::value ); 220 } 221 SECTION("compare to false") 222 { 223 REQUIRE( is_true<false>::value == false ); 224 REQUIRE( false == is_true<false>::value ); 225 } 226 227 SECTION("negation") 228 { 229 REQUIRE( !is_true<false>::value ); 230 } 231 232 SECTION("double negation") 233 { 234 REQUIRE( !!is_true<true>::value ); 235 } 236 237 SECTION("direct") 238 { 239 REQUIRE( is_true<true>::value ); 240 REQUIRE_FALSE( is_true<false>::value ); 241 } 242 } 243 244 // Uncomment these tests to produce an error at test registration time 245 /* 246 TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) 247 { 248 249 } 250 TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) 251 { 252 253 } 254 */ 255 256 struct Boolable 257 { 258 explicit Boolable( bool value ) : m_value( value ) {} 259 260 explicit operator bool() const { 261 return m_value; 262 } 263 264 bool m_value; 265 }; 266 267 TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" ) 268 { 269 Boolable True( true ); 270 Boolable False( false ); 271 272 CHECK( True ); 273 CHECK( !False ); 274 CHECK_FALSE( False ); 275 } 276 277 TEST_CASE( "Assertions then sections", "[Tricky]" ) 278 { 279 // This was causing a failure due to the way the console reporter was handling 280 // the current section 281 282 REQUIRE( true ); 283 284 SECTION( "A section" ) 285 { 286 REQUIRE( true ); 287 288 SECTION( "Another section" ) 289 { 290 REQUIRE( true ); 291 } 292 SECTION( "Another other section" ) 293 { 294 REQUIRE( true ); 295 } 296 } 297 } 298 299 struct Awkward 300 { 301 operator int() const { return 7; } 302 }; 303 304 TEST_CASE( "non streamable - with conv. op", "[Tricky]" ) 305 { 306 Awkward awkward; 307 std::string s = ::Catch::Detail::stringify( awkward ); 308 REQUIRE( s == "7" ); 309 } 310 311 inline void foo() {} 312 313 typedef void (*fooptr_t)(); 314 315 TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" ) 316 { 317 // This was giving a warning in VS2010 318 // #179 319 fooptr_t a = foo; 320 321 REQUIRE( a ); 322 REQUIRE( a == &foo ); 323 } 324 325 struct S 326 { 327 void f() {} 328 }; 329 330 331 TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer][approvals]" ) 332 { 333 typedef void (S::*MF)(); 334 MF m = &S::f; 335 336 CHECK( m == &S::f ); 337 } 338 339 class ClassName {}; 340 341 TEST_CASE( "pointer to class", "[Tricky]" ) 342 { 343 ClassName *p = 0; 344 REQUIRE( p == 0 ); 345 } 346 347 #include <memory> 348 349 TEST_CASE( "null_ptr", "[Tricky]" ) 350 { 351 std::unique_ptr<int> ptr; 352 REQUIRE(ptr.get() == nullptr); 353 } 354 355 TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); } 356 TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); } 357 TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); } 358 TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); } 359 360 TEST_CASE( "has printf" ) { 361 362 // This can cause problems as, currently, stdout itself is not redirected - only the cout (and cerr) buffer 363 printf( "loose text artifact\n" ); 364 } 365 366 namespace { 367 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 368 struct constructor_throws { 369 [[noreturn]] constructor_throws() { 370 throw 1; 371 } 372 }; 373 #endif 374 } 375 376 TEST_CASE("Commas in various macros are allowed") { 377 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 378 REQUIRE_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} ); 379 CHECK_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} ); 380 #endif 381 REQUIRE_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} ); 382 CHECK_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} ); 383 384 REQUIRE(std::vector<int>{1, 2} == std::vector<int>{1, 2}); 385 CHECK( std::vector<int>{1, 2} == std::vector<int>{1, 2} ); 386 REQUIRE_FALSE(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3}); 387 CHECK_FALSE( std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} ); 388 389 CHECK_NOFAIL( std::vector<int>{1, 2} == std::vector<int>{1, 2} ); 390 CHECKED_IF( std::vector<int>{1, 2} == std::vector<int>{1, 2} ) { 391 REQUIRE(true); 392 } CHECKED_ELSE( std::vector<int>{1, 2} == std::vector<int>{1, 2} ) { 393 CHECK(true); 394 } 395 } 396 397 TEST_CASE( "null deref", "[.][failing][!nonportable]" ) { 398 CHECK( false ); 399 int *x = NULL; 400 *x = 1; 401 } 402 403 TEST_CASE( "non-copyable objects", "[.][failing]" ) { 404 #if CHECK_CONFIG_USE_RTTI 405 // Thanks to Agustin Berg (@k-ballo on the cpplang Slack) for raising this 406 std::type_info const& ti = typeid(int); 407 CHECK( ti == typeid(int) ); 408 #endif 409 } 410 411 // #925 412 using signal_t = void (*) (void*); 413 414 struct TestClass { 415 signal_t testMethod_uponComplete_arg = nullptr; 416 }; 417 418 namespace utility { 419 inline static void synchronizing_callback( void * ) { } 420 } 421 422 TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) { 423 424 TestClass test; 425 REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg); 426 } 427 428 TEST_CASE( "Bitfields can be captured (#1027)" ) { 429 struct Y { 430 uint32_t v : 1; 431 }; 432 Y y{ 0 }; 433 REQUIRE( y.v == 0 ); 434 REQUIRE( 0 == y.v ); 435 } 436 437 TEST_CASE("#1514: stderr/stdout is not captured in tests aborted by an exception", "[output-capture][regression][.]") { 438 std::cout << "This would not be caught previously\n" << std::flush; 439 std::clog << "Nor would this\n" << std::flush; 440 // FAIL aborts the test by throwing a Catch exception 441 FAIL("1514"); 442 } 443