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 #include "catch.hpp"
14 
15 #ifdef __clang__
16 #pragma clang diagnostic ignored "-Wc++98-compat"
17 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
18 #endif
19 
20 namespace Catch
21 {
22     template<>
toString(const std::pair<int,int> & value)23     std::string toString<std::pair<int, int> >( const std::pair<int, int>& value )
24     {
25         std::ostringstream oss;
26         oss << "std::pair( " << value.first << ", " << value.second << " )";
27         return oss.str();
28 
29     }
30 }
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 TEST_CASE
34 (
35     "Parsing a std::pair",
36     "[Tricky][std::pair]"
37 )
38 {
39     std::pair<int, int> aNicePair( 1, 2 );
40 
41     REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair );
42 }
43 
44 ///////////////////////////////////////////////////////////////////////////////
45 TEST_CASE
46 (
47     "Where there is more to the expression after the RHS",
48     "[Tricky][failing][.]"
49 )
50 {
51 //    int a = 1, b = 2;
52 //    REQUIRE( a == 2 || b == 2 );
53     WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" );
54 }
55 ///////////////////////////////////////////////////////////////////////////////
56 TEST_CASE
57 (
58     "Where the LHS is not a simple value",
59     "[Tricky][failing][.]"
60 )
61 {
62     /*
63     int a = 1;
64     int b = 2;
65 
66     // This only captures part of the expression, but issues a warning about the rest
67     REQUIRE( a+1 == b-1 );
68     */
69     WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" );
70 }
71 
72 struct Opaque
73 {
74     int val;
operator ==Opaque75     bool operator ==( const Opaque& o ) const
76     {
77         return val == o.val;
78     }
79 };
80 
81 ///////////////////////////////////////////////////////////////////////////////
82 TEST_CASE
83 (
84     "A failing expression with a non streamable type is still captured",
85     "[Tricky][failing][.]"
86 )
87 {
88 
89     Opaque o1, o2;
90     o1.val = 7;
91     o2.val = 8;
92 
93     CHECK( &o1 == &o2 );
94     CHECK( o1 == o2 );
95 }
96 
97 ///////////////////////////////////////////////////////////////////////////////
98 TEST_CASE
99 (
100     "string literals of different sizes can be compared",
101     "[Tricky][failing][.]"
102 )
103 {
104     REQUIRE( std::string( "first" ) == "second" );
105 
106 }
107 
108 ///////////////////////////////////////////////////////////////////////////////
109 TEST_CASE
110 (
111     "An expression with side-effects should only be evaluated once",
112     "[Tricky]"
113 )
114 {
115     int i = 7;
116 
117     REQUIRE( i++ == 7 );
118     REQUIRE( i++ == 8 );
119 
120 }
121 
122 namespace A {
123     struct X
124     {
XA::X125         X() : a(4), b(2), c(7) {}
XA::X126         X(int v) : a(v), b(2), c(7) {}
127         int a;
128         int b;
129         int c;
130     };
131 }
132 
133 namespace B {
134     struct Y
135     {
YB::Y136         Y() : a(4), b(2), c(7) {}
YB::Y137         Y(int v) : a(v), b(2), c(7) {}
138         int a;
139         int b;
140         int c;
141     };
142 }
143 
operator ==(const A::X & lhs,const B::Y & rhs)144 inline bool operator==(const A::X& lhs, const B::Y& rhs)
145 {
146     return (lhs.a == rhs.a);
147 }
148 
operator ==(const B::Y & lhs,const A::X & rhs)149 inline bool operator==(const B::Y& lhs, const A::X& rhs)
150 {
151     return (lhs.a == rhs.a);
152 }
153 
154 
155 ///////////////////////////////////////////////////////////////////////////////
156 /* This, currently, does not compile with LLVM
157 TEST_CASE
158 (
159     "Operators at different namespace levels not hijacked by Koenig lookup"
160     "[Tricky]"
161 )
162 {
163     A::X x;
164     B::Y y;
165     REQUIRE( x == y );
166 }
167 */
168 
169 namespace ObjectWithConversions
170 {
171     struct Object
172     {
operator unsigned intObjectWithConversions::Object173         operator unsigned int() {return 0xc0000000;}
174     };
175 
176     ///////////////////////////////////////////////////////////////////////////////
177     TEST_CASE
178     (
179         "Operators at different namespace levels not hijacked by Koenig lookup",
180         "[Tricky]"
181     )
182     {
183         Object o;
184         REQUIRE(0xc0000000 == o );
185     }
186 }
187 
188 namespace ObjectWithNonConstEqualityOperator
189 {
190     struct Test
191     {
TestObjectWithNonConstEqualityOperator::Test192         Test( unsigned int v )
193         : m_value(v)
194         {}
195 
operator ==ObjectWithNonConstEqualityOperator::Test196         bool operator==( const Test&rhs )
197         {
198             return (m_value == rhs.m_value);
199         }
operator ==ObjectWithNonConstEqualityOperator::Test200         bool operator==( const Test&rhs ) const
201         {
202             return (m_value != rhs.m_value);
203         }
204         unsigned int m_value;
205     };
206 
207     TEST_CASE("Demonstrate that a non-const == is not used", "[Tricky]" )
208     {
209         Test t( 1 );
210         REQUIRE( t == 1u );
211     }
212 }
213 
214 namespace EnumBitFieldTests
215 {
216     enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006,
217         bit30 = 0x40000000, bit31 = 0x80000000,
218         bit30and31 = 0xc0000000};
219 
220     TEST_CASE( "Test enum bit values", "[Tricky]" )
221     {
222         REQUIRE( 0xc0000000 == bit30and31 );
223     }
224 }
225 
226 struct Obj
227 {
ObjObj228     Obj():prop(&p){}
229 
230     int p;
231     int* prop;
232 };
233 
234 TEST_CASE("boolean member", "[Tricky]")
235 {
236     Obj obj;
237     REQUIRE( obj.prop != CATCH_NULL );
238 }
239 
240 // Tests for a problem submitted by Ralph McArdell
241 //
242 // The static bool value should not need to be defined outside the
243 // struct it is declared in - but when evaluating it in a deduced
244 // context it appears to require the extra definition.
245 // The issue was fixed by adding bool overloads to bypass the
246 // templates that were there to deduce it.
247 template <bool B>
248 struct is_true
249 {
250     static const bool value = B;
251 };
252 
253 TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" )
254 {
255     SECTION("compare to true","")
256     {
257         REQUIRE( is_true<true>::value == true );
258         REQUIRE( true == is_true<true>::value );
259     }
260     SECTION("compare to false","")
261     {
262         REQUIRE( is_true<false>::value == false );
263         REQUIRE( false == is_true<false>::value );
264     }
265 
266     SECTION("negation", "")
267     {
268         REQUIRE( !is_true<false>::value );
269     }
270 
271     SECTION("double negation","")
272     {
273         REQUIRE( !!is_true<true>::value );
274     }
275 
276     SECTION("direct","")
277     {
278         REQUIRE( is_true<true>::value );
279         REQUIRE_FALSE( is_true<false>::value );
280     }
281 }
282 
283 // Uncomment these tests to produce an error at test registration time
284 /*
285 TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
286 {
287 
288 }
289 TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
290 {
291 
292 }
293 */
294 
295 struct Boolable
296 {
BoolableBoolable297     explicit Boolable( bool value ) : m_value( value ) {}
298 
operator Catch::SafeBool::typeBoolable299     operator Catch::SafeBool::type() const {
300         return Catch::SafeBool::makeSafe( m_value );
301     }
302 
303     bool m_value;
304 };
305 
306 TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" )
307 {
308     Boolable True( true );
309     Boolable False( false );
310 
311     CHECK( True );
312     CHECK( !False );
313     CHECK_FALSE( False );
314 }
315 
316 TEST_CASE( "Assertions then sections", "[Tricky]" )
317 {
318     // This was causing a failure due to the way the console reporter was handling
319     // the current section
320 
321     REQUIRE( Catch::alwaysTrue() );
322 
323     SECTION( "A section", "" )
324     {
325         REQUIRE( Catch::alwaysTrue() );
326 
327         SECTION( "Another section", "" )
328         {
329             REQUIRE( Catch::alwaysTrue() );
330         }
331         SECTION( "Another other section", "" )
332         {
333             REQUIRE( Catch::alwaysTrue() );
334         }
335     }
336 }
337 
338 struct Awkward
339 {
operator intAwkward340     operator int() const { return 7; }
341 };
342 
343 TEST_CASE( "non streamable - with conv. op", "[Tricky]" )
344 {
345     Awkward awkward;
346     std::string s = Catch::toString( awkward );
347     REQUIRE( s == "7" );
348 }
349 
foo()350 inline void foo() {}
351 
352 typedef void (*fooptr_t)();
353 
354 TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" )
355 {
356     // This was giving a warning in VS2010
357     // #179
358     fooptr_t a = foo;
359 
360     REQUIRE( a );
361     REQUIRE( a == &foo );
362 }
363 
364 struct S
365 {
fS366     void f() {}
367 };
368 
369 
370 TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer]" )
371 {
372     typedef void (S::*MF)();
373     MF m = &S::f;
374 
375     CHECK( m == &S::f );
376 }
377 
378 class ClassName {};
379 
380 TEST_CASE( "pointer to class", "[Tricky]" )
381 {
382    ClassName *p = 0;
383    REQUIRE( p == 0 );
384 }
385 
386 #ifdef CATCH_CONFIG_CPP11_NULLPTR
387 
388 #include <memory>
389 
390 TEST_CASE( "null_ptr", "[Tricky][c++11][.]" )
391 {
392     std::unique_ptr<int> ptr;
393     REQUIRE(ptr.get() == nullptr);
394 }
395 
396 #endif
397 
398 TEST_CASE( "X/level/0/a", "[Tricky]" )      { SUCCEED(""); }
399 TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); }
400 TEST_CASE( "X/level/1/a", "[Tricky]" )      { SUCCEED(""); }
401 TEST_CASE( "X/level/1/b", "[Tricky]" )      { SUCCEED(""); }
402