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
= new Derived
;
177 Derived
* derived
= boost::polymorphic_downcast
<Derived
*>( base
);
179 BOOST_TEST( derived
!= 0 );
183 BOOST_TEST_EQ( derived
->kind(), "Derived" );
186 // polymorphic_downcast can't do crosscasts
191 static void test_polymorphic_pointer_downcast_builtin()
193 Base
* base
= new Derived
;
195 Derived
* derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
197 BOOST_TEST( derived
!= 0 );
201 BOOST_TEST_EQ( derived
->kind(), "Derived" );
204 // polymorphic_pointer_downcast can't do crosscasts
209 static void test_polymorphic_pointer_downcast_boost_shared()
211 boost::shared_ptr
<Base
> base (new Derived
);
213 boost::shared_ptr
<Derived
> derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
215 BOOST_TEST( derived
!= 0 );
219 BOOST_TEST_EQ( derived
->kind(), "Derived" );
223 static void test_polymorphic_pointer_downcast_intrusive()
225 boost::intrusive_ptr
<Base
> base (new Derived
);
227 boost::intrusive_ptr
<Derived
> derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
229 BOOST_TEST( derived
!= 0 );
233 BOOST_TEST_EQ( derived
->kind(), "Derived" );
237 #ifndef BOOST_NO_CXX11_SMART_PTR
239 static void test_polymorphic_pointer_downcast_std_shared()
241 std::shared_ptr
<Base
> base (new Derived
);
243 std::shared_ptr
<Derived
> derived
= boost::polymorphic_pointer_downcast
<Derived
>( base
);
245 BOOST_TEST( derived
!= 0 );
249 BOOST_TEST_EQ( derived
->kind(), "Derived" );
255 static void test_polymorphic_cast_fail()
257 Base
* base
= new Base
;
259 BOOST_TEST_THROWS( boost::polymorphic_cast
<Derived
*>( base
), std::bad_cast
);
264 static void test_polymorphic_pointer_cast_fail()
266 Base
* base
= new Base
;
267 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( base
), std::bad_cast
);
270 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( boost::shared_ptr
<Base
>(new Base
) ), std::bad_cast
);
272 #ifndef BOOST_NO_CXX11_SMART_PTR
273 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( std::shared_ptr
<Base
>(new Base
) ), std::bad_cast
);
276 BOOST_TEST_THROWS( boost::polymorphic_pointer_cast
<Derived
>( boost::intrusive_ptr
<Base
>(new Base
) ), std::bad_cast
);
279 static void test_polymorphic_downcast_fail()
281 Base
* base
= new Base
;
283 int old_count
= assertion_failed_count
;
284 expect_assertion
= true;
286 BOOST_TEST_THROWS( boost::polymorphic_downcast
<Derived
*>( base
), expected_assertion
); // should assert
288 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
289 expect_assertion
= false;
294 static void test_polymorphic_pointer_downcast_builtin_fail()
296 Base
* base
= new Base
;
298 int old_count
= assertion_failed_count
;
299 expect_assertion
= true;
301 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
303 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
304 expect_assertion
= false;
309 static void test_polymorphic_pointer_downcast_boost_shared_fail()
311 boost::shared_ptr
<Base
> base (new Base
);
313 int old_count
= assertion_failed_count
;
314 expect_assertion
= true;
316 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
318 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
319 expect_assertion
= false;
322 #ifndef BOOST_NO_CXX11_SMART_PTR
324 static void test_polymorphic_pointer_downcast_std_shared_fail()
326 std::shared_ptr
<Base
> base (new Base
);
328 int old_count
= assertion_failed_count
;
329 expect_assertion
= true;
331 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
333 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
334 expect_assertion
= false;
339 static void test_polymorphic_pointer_downcast_intrusive_fail()
341 boost::intrusive_ptr
<Base
> base (new Base
);
343 int old_count
= assertion_failed_count
;
344 expect_assertion
= true;
346 BOOST_TEST_THROWS( boost::polymorphic_pointer_downcast
<Derived
>( base
), expected_assertion
); // should assert
348 BOOST_TEST_EQ( assertion_failed_count
, old_count
+ 1 );
349 expect_assertion
= false;
354 test_polymorphic_cast();
355 test_polymorphic_pointer_cast();
356 test_polymorphic_downcast();
357 test_polymorphic_pointer_downcast_builtin();
358 test_polymorphic_pointer_downcast_boost_shared();
359 test_polymorphic_pointer_downcast_intrusive();
360 test_polymorphic_cast_fail();
361 test_polymorphic_pointer_cast_fail();
362 test_polymorphic_downcast_fail();
363 test_polymorphic_pointer_downcast_builtin_fail();
364 test_polymorphic_pointer_downcast_boost_shared_fail();
365 test_polymorphic_pointer_downcast_intrusive_fail();
367 #ifndef BOOST_NO_CXX11_SMART_PTR
368 test_polymorphic_pointer_downcast_std_shared();
369 test_polymorphic_pointer_downcast_std_shared_fail();
372 return boost::report_errors();