• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstdio>
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;
operator ==Opaque55     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     {
XA::X105         X() : a(4), b(2), c(7) {}
XA::X106         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     {
YB::Y116         Y() : a(4), b(2), c(7) {}
YB::Y117         Y(int v) : a(v), b(2), c(7) {}
118         int a;
119         int b;
120         int c;
121     };
122 }
123 
operator ==(const A::X & lhs,const B::Y & rhs)124 inline bool operator==(const A::X& lhs, const B::Y& rhs)
125 {
126     return (lhs.a == rhs.a);
127 }
128 
operator ==(const B::Y & lhs,const A::X & rhs)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     {
operator unsigned intObjectWithConversions::Object153         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 {
ObjObj189     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 {
BoolableBoolable258     explicit Boolable( bool value ) : m_value( value ) {}
259 
operator boolBoolable260     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 {
operator intAwkward301     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 
foo()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 {
fS327     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 {
constructor_throws__anon97f517d20111::constructor_throws369         [[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( "non-copyable objects", "[.][failing]" ) {
398 #if CHECK_CONFIG_USE_RTTI
399     // Thanks to Agustin Bergé (@k-ballo on the cpplang Slack) for raising this
400     std::type_info const& ti = typeid(int);
401     CHECK( ti == typeid(int) );
402 #endif
403 }
404 
405 TEST_CASE("#1514: stderr/stdout is not captured in tests aborted by an exception", "[output-capture][regression][.]") {
406     std::cout << "This would not be caught previously\n" << std::flush;
407     std::clog << "Nor would this\n" << std::flush;
408     // FAIL aborts the test by throwing a Catch exception
409     FAIL("1514");
410 }
411