blob: cc180a2bf3ca6634b1cb84d986529ecbc91f4940 [file] [log] [blame]
//
// esft_regtest.cpp
//
// A regression test for enable_shared_from_this
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <memory>
#include <string>
class X: public boost::enable_shared_from_this< X >
{
private:
int destroyed_;
int deleted_;
int expected_;
private:
X( X const& );
X& operator=( X const& );
public:
static int instances;
public:
explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
{
++instances;
}
~X()
{
BOOST_TEST( deleted_ == expected_ );
BOOST_TEST( destroyed_ == 0 );
++destroyed_;
--instances;
}
typedef void (*deleter_type)( X* );
static void deleter( X * px )
{
++px->deleted_;
}
static void deleter2( X * px )
{
++px->deleted_;
delete px;
}
};
int X::instances = 0;
void test()
{
BOOST_TEST( X::instances == 0 );
{
X x( 0 );
BOOST_TEST( X::instances == 1 );
}
BOOST_TEST( X::instances == 0 );
{
std::auto_ptr<X> px( new X( 0 ) );
BOOST_TEST( X::instances == 1 );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> px( new X( 0 ) );
BOOST_TEST( X::instances == 1 );
boost::weak_ptr<X> wp( px );
BOOST_TEST( !wp.expired() );
px.reset();
BOOST_TEST( wp.expired() );
}
BOOST_TEST( X::instances == 0 );
{
X x( 1 );
boost::shared_ptr<X> px( &x, X::deleter );
BOOST_TEST( X::instances == 1 );
X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
BOOST_TEST( pd != 0 && *pd == X::deleter );
boost::weak_ptr<X> wp( px );
BOOST_TEST( !wp.expired() );
px.reset();
BOOST_TEST( wp.expired() );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> px( new X( 1 ), X::deleter2 );
BOOST_TEST( X::instances == 1 );
X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
BOOST_TEST( pd != 0 && *pd == X::deleter2 );
boost::weak_ptr<X> wp( px );
BOOST_TEST( !wp.expired() );
px.reset();
BOOST_TEST( wp.expired() );
}
BOOST_TEST( X::instances == 0 );
}
struct V: public boost::enable_shared_from_this<V>
{
virtual ~V() {}
std::string m_;
};
struct V2
{
virtual ~V2() {}
std::string m2_;
};
struct W: V2, V
{
};
void test2()
{
boost::shared_ptr<W> p( new W );
}
void test3()
{
V * p = new W;
boost::shared_ptr<void> pv( p );
BOOST_TEST( pv.get() == p );
BOOST_TEST( pv.use_count() == 1 );
}
struct null_deleter
{
void operator()( void const* ) const {}
};
void test4()
{
boost::shared_ptr<V> pv( new V );
boost::shared_ptr<V> pv2( pv.get(), null_deleter() );
BOOST_TEST( pv2.get() == pv.get() );
BOOST_TEST( pv2.use_count() == 1 );
}
void test5()
{
V v;
boost::shared_ptr<V> p1( &v, null_deleter() );
BOOST_TEST( p1.get() == &v );
BOOST_TEST( p1.use_count() == 1 );
try
{
p1->shared_from_this();
}
catch( ... )
{
BOOST_ERROR( "p1->shared_from_this() failed" );
}
p1.reset();
boost::shared_ptr<V> p2( &v, null_deleter() );
BOOST_TEST( p2.get() == &v );
BOOST_TEST( p2.use_count() == 1 );
try
{
p2->shared_from_this();
}
catch( ... )
{
BOOST_ERROR( "p2->shared_from_this() failed" );
}
}
int main()
{
test();
test2();
test3();
test4();
test5();
return boost::report_errors();
}