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