2 // Test boost::polymorphic_cast, boost::polymorphic_downcast and
3 // boost::polymorphic_pointer_cast, boost::polymorphic_pointer_downcast
5 // Copyright 1999 Beman Dawes
6 // Copyright 1999 Dave Abrahams
7 // Copyright 2014 Peter Dimov
8 // Copyright 2014 Boris Rasin, Antony Polukhin
10 // Distributed under the Boost Software License, Version 1.0.
12 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
15 #define BOOST_ENABLE_ASSERT_HANDLER
16 #include <boost/polymorphic_cast.hpp>
17 #include <boost/polymorphic_pointer_cast.hpp>
18 #include <boost/smart_ptr/shared_ptr.hpp>
19 #include <boost/smart_ptr/intrusive_ptr.hpp>
20 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
21 #include <boost/core/lightweight_test.hpp>
25 static bool expect_assertion
= false;
26 static int assertion_failed_count
= 0;
28 //assertion handler throws it to exit like assert, but to be able to catch it and stop
29 //usage: BOOST_TEST_THROWS( function_with_assert(), expected_assertion );
30 struct expected_assertion
{};
32 // BOOST_ASSERT custom handler
33 void boost::assertion_failed( char const * expr
, char const * function
, char const * file
, long line
)
35 if( expect_assertion
)
37 ++assertion_failed_count
;
38 throw expected_assertion();
42 BOOST_ERROR( "unexpected assertion" );
44 BOOST_LIGHTWEIGHT_TEST_OSTREAM
45 << file
<< "(" << line
<< "): assertion '" << expr
<< "' failed in function '"
46 << function
<< "'" << std::endl
;
52 struct Base
: boost::intrusive_ref_counter
<Base
>
55 virtual std::string
kind() { return "Base"; }
61 virtual std::string
kind2() { return "Base2"; }
64 struct Derived
: public Base
, Base2
66 virtual std::string
kind() { return "Derived"; }
69 static void test_polymorphic_cast()
71 Base
* base
= new Derived
;
77 derived
= boost::polymorphic_cast
<Derived
*>( base
);
79 BOOST_TEST( derived
!= 0 );
83 BOOST_TEST_EQ( derived
->kind(), "Derived" );
86 catch( std::bad_cast
const& )
88 BOOST_ERROR( "boost::polymorphic_cast<Derived*>( base ) threw std::bad_cast" );
95 base2
= boost::polymorphic_cast
<Base2
*>( base
); // crosscast
97 BOOST_TEST( base2
!= 0 );
101 BOOST_TEST_EQ( base2
->kind2(), "Base2" );
104 catch( std::bad_cast
const& )
106 BOOST_ERROR( "boost::polymorphic_cast<Base2*>( base ) threw std::bad_cast" );
112 static void test_polymorphic_pointer_cast()
114 Base
* base
= new Derived
;
120 derived
= boost::polymorphic_pointer_cast
<Derived
>( base
);
122 BOOST_TEST( derived
!= 0 );
126 BOOST_TEST_EQ( derived
->kind(), "Derived" );
129 catch( std::bad_cast
const& )
131 BOOST_ERROR( "boost::polymorphic_pointer_cast<Derived>( base ) threw std::bad_cast" );
138 base2
= boost::polymorphic_pointer_cast
<Base2
>( base
); // crosscast
140 BOOST_TEST( base2
!= 0 );
144 BOOST_TEST_EQ( base2
->kind2(), "Base2" );
147 catch( std::bad_cast
const& )
149 BOOST_ERROR( "boost::polymorphic_pointer_cast<Base2>( base ) threw std::bad_cast" );
152 boost::shared_ptr
<Base
> sp_base( base
);
153 boost::shared_ptr
<Base2
> sp_base2
;
156 sp_base2
= boost::polymorphic_pointer_cast
<Base2
>( sp_base
); // crosscast
158 BOOST_TEST( sp_base2
!= 0 );
162 BOOST_TEST_EQ( sp_base2
->kind2(), "Base2" );
165 catch( std::bad_cast
const& )
167 BOOST_ERROR( "boost::polymorphic_pointer_cast<Base2>( sp_base ) threw std::bad_cast" );
170 // we do not `delete base;` because sahred_ptr is holding base
173 static void test_polymorphic_downcast()
175 Base
*base_pointer
= new Derived
;
177 // test raw pointer cast
178 Derived
*derived_pointer
= boost::polymorphic_downcast
<Derived
*>(base_pointer
);
180 BOOST_TEST(derived_pointer
!= 0);
182 if (derived_pointer
!= 0)
184 BOOST_TEST_EQ(derived_pointer
->kind(), "Derived");
187 // test reference cast
188 Derived
& derived_ref
= boost::polymorphic_downcast
<Derived
&>(*base_pointer
);
189 BOOST_TEST_EQ(derived_ref
.kind(), "Derived");
194 static void test_polymorphic_pointer_downcast_builtin()
196 Base
* base
= new Derived
;
198 Derived
* derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
200 BOOST_TEST( derived
!= 0 );
204 BOOST_TEST_EQ( derived
->kind(), "Derived" );
207 // polymorphic_pointer_downcast can't do crosscasts
212 static void test_polymorphic_pointer_downcast_boost_shared()
214 boost::shared_ptr
<Base
> base (new Derived
);
216 boost::shared_ptr
<Derived
> derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
218 BOOST_TEST( derived
!= 0 );
222 BOOST_TEST_EQ( derived
->kind(), "Derived" );
226 static void test_polymorphic_pointer_downcast_intrusive()
228 boost::intrusive_ptr
<Base
> base (new Derived
);
230 boost::intrusive_ptr
<Derived
> derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
232 BOOST_TEST( derived
!= 0 );
236 BOOST_TEST_EQ( derived
->kind(), "Derived" );
240 #ifndef BOOST_NO_CXX11_SMART_PTR
242 static void test_polymorphic_pointer_downcast_std_shared()
244 std::shared_ptr
<Base
> base (new Derived
);
246 std::shared_ptr
<Derived
> derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
248 BOOST_TEST( derived
!= 0 );
252 BOOST_TEST_EQ( derived
->kind(), "Derived" );
258 static void test_polymorphic_cast_fail()
260 Base
* base
= new Base
;
262 BOOST_TEST_THROWS( boost::polymorphic_cast
<Derived
*>( base
), std::bad_cast
);
267 static void test_polymorphic_pointer_cast_fail()
269 Base
* base
= new Base
;
270 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( base
), std::bad_cast
);
273 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( boost::shared_ptr
<Base
>(new Base
) ), std::bad_cast
);
275 #ifndef BOOST_NO_CXX11_SMART_PTR
276 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( std::shared_ptr
<Base
>(new Base
) ), std::bad_cast
);
279 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( boost::intrusive_ptr
<Base
>(new Base
) ), std::bad_cast
);
282 static void test_polymorphic_downcast_fail()
284 Base
* base_pointer
= new Base
;
287 // test raw pointer cast
289 int old_count
= assertion_failed_count
;
290 expect_assertion
= true;
292 BOOST_TEST_THROWS(boost::polymorphic_downcast
<Derived
*>(base_pointer
), expected_assertion
); // should assert
294 BOOST_TEST_EQ(assertion_failed_count
, old_count
+ 1);
295 expect_assertion
= false;
298 // test reference cast
300 int old_count
= assertion_failed_count
;
301 expect_assertion
= true;
303 BOOST_TEST_THROWS(boost::polymorphic_downcast
<Derived
&>(*base_pointer
), expected_assertion
); // should assert
305 BOOST_TEST_EQ(assertion_failed_count
, old_count
+ 1);
306 expect_assertion
= false;
312 static void test_polymorphic_pointer_downcast_builtin_fail()
314 Base
* base
= new Base
;
316 int old_count
= assertion_failed_count
;
317 expect_assertion
= true;
319 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
321 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
322 expect_assertion
= false;
327 static void test_polymorphic_pointer_downcast_boost_shared_fail()
329 boost::shared_ptr
<Base
> base (new Base
);
331 int old_count
= assertion_failed_count
;
332 expect_assertion
= true;
334 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
336 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
337 expect_assertion
= false;
340 #ifndef BOOST_NO_CXX11_SMART_PTR
342 static void test_polymorphic_pointer_downcast_std_shared_fail()
344 std::shared_ptr
<Base
> base (new Base
);
346 int old_count
= assertion_failed_count
;
347 expect_assertion
= true;
349 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
351 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
352 expect_assertion
= false;
357 static void test_polymorphic_pointer_downcast_intrusive_fail()
359 boost::intrusive_ptr
<Base
> base (new Base
);
361 int old_count
= assertion_failed_count
;
362 expect_assertion
= true;
364 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
366 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
367 expect_assertion
= false;
372 test_polymorphic_cast();
373 test_polymorphic_pointer_cast();
374 test_polymorphic_downcast();
375 test_polymorphic_pointer_downcast_builtin();
376 test_polymorphic_pointer_downcast_boost_shared();
377 test_polymorphic_pointer_downcast_intrusive();
378 test_polymorphic_cast_fail();
379 test_polymorphic_pointer_cast_fail();
380 test_polymorphic_downcast_fail();
381 test_polymorphic_pointer_downcast_builtin_fail();
382 test_polymorphic_pointer_downcast_boost_shared_fail();
383 test_polymorphic_pointer_downcast_intrusive_fail();
385 #ifndef BOOST_NO_CXX11_SMART_PTR
386 test_polymorphic_pointer_downcast_std_shared();
387 test_polymorphic_pointer_downcast_std_shared_fail();
390 return boost::report_errors();