move/test/unique_ptr_ctordtor.cpp

812 lines
20 KiB
C++

//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Howard Hinnant 2009
// (C) Copyright Ion Gaztanaga 2014-2014.
//
// 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)
//
// See http://www.boost.org/libs/move for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/move/utility_core.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/core/lightweight_test.hpp>
//////////////////////////////////////////////
//
// The initial implementation of these tests
// was written by Howard Hinnant.
//
// These test were later refactored grouping
// and porting them to Boost.Move.
//
// Many thanks to Howard for releasing his C++03
// unique_ptr implementation with such detailed
// test cases.
//
//////////////////////////////////////////////
#include "unique_ptr_test_utils_beg.hpp"
namespace bml = ::boost::movelib;
////////////////////////////////
// unique_ptr_dtor_null
////////////////////////////////
namespace unique_ptr_dtor_null{
// The deleter is not called if get() == 0
void test()
{
//Single unique_ptr
{
def_constr_deleter<int> d;
BOOST_TEST(d.state() == 5);
{
bml::unique_ptr<int, def_constr_deleter<int>&> p(0, d);
BOOST_TEST(p.get() == 0);
BOOST_TEST(&p.get_deleter() == &d);
}
BOOST_TEST(d.state() == 5);
}
{
//Unbounded array unique_ptr
def_constr_deleter<int[]> d;
BOOST_TEST(d.state() == 5);
{
bml::unique_ptr<int[], def_constr_deleter<int[]>&> p(0, d);
BOOST_TEST(p.get() == 0);
BOOST_TEST(&p.get_deleter() == &d);
}
BOOST_TEST(d.state() == 5);
}
{
//Bounded array unique_ptr
def_constr_deleter<int[2]> d;
BOOST_TEST(d.state() == 5);
{
bml::unique_ptr<int[2], def_constr_deleter<int[2]>&> p(0, d);
BOOST_TEST(p.get() == 0);
BOOST_TEST(&p.get_deleter() == &d);
}
BOOST_TEST(d.state() == 5);
}
}
} //namespace unique_ptr_dtor_null{
////////////////////////////////
// unique_ptr_ctor_default_delreq
////////////////////////////////
namespace unique_ptr_ctor_default_delreq{
// default unique_ptr ctor should only require default deleter ctor
void test()
{
//Single unique_ptr
{
bml::unique_ptr<int> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int, def_constr_deleter<int> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[]> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int[], def_constr_deleter<int[]> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[]> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int[], def_constr_deleter<int[]> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
//Unbounded array unique_ptr
{
bml::unique_ptr<int[2]> p;
BOOST_TEST(p.get() == 0);
}
{
bml::unique_ptr<int[2], def_constr_deleter<int[2]> > p;
BOOST_TEST(p.get() == 0);
BOOST_TEST(p.get_deleter().state() == 5);
}
}
} //namespace unique_ptr_ctor_default_delreq{
////////////////////////////////
// unique_ptr_ctor_default_nocomplete
////////////////////////////////
namespace unique_ptr_ctor_default_nocomplete{
// default unique_ptr ctor shouldn't require complete type
void test()
{
//Single unique_ptr
reset_counters();
{
J<I> s;
BOOST_TEST(s.get() == 0);
}
check(0);
{
J<I, def_constr_deleter<I> > s;
BOOST_TEST(s.get() == 0);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Unbounded array unique_ptr
reset_counters();
{
J<I[]> s;
BOOST_TEST(s.get() == 0);
}
check(0);
{
J<I[], def_constr_deleter<I[]> > s;
BOOST_TEST(s.get() == 0);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Bounded array unique_ptr
reset_counters();
{
J<I[2]> s;
BOOST_TEST(s.get() == 0);
}
check(0);
{
J<I[2], def_constr_deleter<I[2]> > s;
BOOST_TEST(s.get() == 0);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
}
} //namespace unique_ptr_ctor_default_nocomplete{
////////////////////////////////
// unique_ptr_ctor_pointer_delreq
////////////////////////////////
namespace unique_ptr_ctor_pointer_delreq{
// unique_ptr(pointer) ctor should only require default deleter ctor
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
bml::unique_ptr<A> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
A* p = new A;
BOOST_TEST(A::count == 1);
bml::unique_ptr<A, def_constr_deleter<A> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[], def_constr_deleter<A[]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[2]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<A[2], def_constr_deleter<A[2]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_delreq{
////////////////////////////////
// unique_ptr_ctor_pointer_nocomplete
////////////////////////////////
namespace unique_ptr_ctor_pointer_nocomplete{
// unique_ptr(pointer) ctor shouldn't require complete type
void test()
{
//Single unique_ptr
reset_counters();
{
I* p = get();
check(1);
J<I> s(p);
BOOST_TEST(s.get() == p);
}
check(0);
{
I* p = get();
check(1);
J<I, def_constr_deleter<I> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Unbounded array unique_ptr
reset_counters();
{
I* p = get_array(2);
check(2);
J<I[]> s(p);
BOOST_TEST(s.get() == p);
}
check(0);
{
I* p = get_array(2);
check(2);
J<I[], def_constr_deleter<I[]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
//Bounded array unique_ptr
reset_counters();
{
I* p = get_array(2);
check(2);
J<I[]> s(p);
BOOST_TEST(s.get() == p);
}
check(0);
{
I* p = get_array(2);
check(2);
J<I[2], def_constr_deleter<I[2]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
check(0);
}
} //namespace unique_ptr_ctor_pointer_nocomplete{
////////////////////////////////
// unique_ptr_ctor_pointer_convert
////////////////////////////////
namespace unique_ptr_ctor_pointer_convert{
// unique_ptr(pointer) ctor should work with derived pointers
// or same types (cv aside) for unique_ptr<arrays>
void test()
{
//Single unique_ptr
reset_counters();
{
B* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
bml::unique_ptr<A> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
{
B* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
bml::unique_ptr<A, def_constr_deleter<A> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const volatile A[], def_constr_deleter<const volatile A[]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[2]> s(p);
BOOST_TEST(s.get() == p);
}
BOOST_TEST(A::count == 0);
{
const A* p = new const A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const volatile A[2], def_constr_deleter<const volatile A[2]> > s(p);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_convert{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_movedel
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_movedel{
// test move ctor. Should only require a MoveConstructible deleter, or if
// deleter is a reference, not even that.
// unique_ptr(pointer, deleter()) only requires MoveConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
move_constr_deleter<A> d;
bml::unique_ptr<A, move_constr_deleter<A> > s(p, ::boost::move(d));
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
bml::unique_ptr<A, move_constr_deleter<A> > s2(s.release(), move_constr_deleter<A>(6));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s2.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
move_constr_deleter<A[]> d;
bml::unique_ptr<A[], move_constr_deleter<A[]> > s(p, ::boost::move(d));
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
bml::unique_ptr<A[], move_constr_deleter<A[]> > s2(s.release(), move_constr_deleter<A[]>(6));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s2.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
move_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s(p, ::boost::move(d));
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
bml::unique_ptr<A[2], move_constr_deleter<A[2]> > s2(s.release(), move_constr_deleter<A[2]>(6));
BOOST_TEST(s2.get() == p);
BOOST_TEST(s2.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_movedel{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_copydel
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_copydel{
// unique_ptr(pointer, d) requires CopyConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
copy_constr_deleter<A> d;
bml::unique_ptr<A, copy_constr_deleter<A> > s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
copy_constr_deleter<A[]> d;
bml::unique_ptr<A[], copy_constr_deleter<A[]> > s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
copy_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], copy_constr_deleter<A[2]> > s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_copydel{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_dfctrdelref
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{
// unique_ptr<T, D&>(pointer, d) does not requires CopyConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
def_constr_deleter<A> d;
bml::unique_ptr<A, def_constr_deleter<A>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[]> d;
bml::unique_ptr<A[], def_constr_deleter<A[]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], def_constr_deleter<A[2]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
d.set_state(6);
BOOST_TEST(s.get_deleter().state() == 6);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_dfctrdelconstref
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{
// unique_ptr<T, const D&>(pointer, d) does not requires CopyConstructible deleter
void test()
{
//Single unique_ptr
reset_counters();
{
A* p = new A;
BOOST_TEST(A::count == 1);
def_constr_deleter<A> d;
bml::unique_ptr<A, const def_constr_deleter<A>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[]> d;
bml::unique_ptr<A[], const def_constr_deleter<A[]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
def_constr_deleter<A[2]> d;
bml::unique_ptr<A[2], const def_constr_deleter<A[2]>&> s(p, d);
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_convert
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_convert{
// unique_ptr(pointer, deleter) should work with derived pointers
// or same (cv aside) types for array unique_ptrs
void test()
{
//Single unique_ptr
reset_counters();
{
B* p = new B;
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
bml::unique_ptr<A, copy_constr_deleter<A> > s(p, copy_constr_deleter<A>());
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Unbounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[], copy_constr_deleter<const A[]> > s(p, copy_constr_deleter<const A[]>());
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
//Bounded array unique_ptr
reset_counters();
{
A* p = new A[2];
BOOST_TEST(A::count == 2);
bml::unique_ptr<const A[2], copy_constr_deleter<const A[2]> > s(p, copy_constr_deleter<const A[2]>());
BOOST_TEST(s.get() == p);
BOOST_TEST(s.get_deleter().state() == 5);
}
BOOST_TEST(A::count == 0);
BOOST_TEST(B::count == 0);
}
} //namespace unique_ptr_ctor_pointer_deleter_convert{
////////////////////////////////
// unique_ptr_ctor_pointer_deleter_void
////////////////////////////////
namespace unique_ptr_ctor_pointer_deleter_void{
// unique_ptr(pointer, deleter) should work with function pointers
// unique_ptr<void> should work
bool my_free_called = false;
void my_free(void*)
{
my_free_called = true;
}
void test()
{
{
int i = 0;
bml::unique_ptr<void, void (*)(void*)> s(&i, my_free);
BOOST_TEST(s.get() == &i);
BOOST_TEST(s.get_deleter() == my_free);
BOOST_TEST(!my_free_called);
}
BOOST_TEST(my_free_called);
}
} //namespace unique_ptr_ctor_pointer_deleter_void{
////////////////////////////////
// return_unique_single_conversion
////////////////////////////////
namespace return_unique_single_conversion{
template<class T>
bml::unique_ptr<T> make_unique_ptr_of_t()
{
return bml::unique_ptr<T>(new T);
}
template<class T>
bml::unique_ptr<T const> return_const_unique_of_t()
{
return bml::unique_ptr<T const> (make_unique_ptr_of_t<T>());
}
void test()
{
reset_counters();
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A> p(return_const_unique_of_t<A>());
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A> p(return_const_unique_of_t<B>());
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
}
} //namespace return_unique_single_conversion{
////////////////////////////////
// return_unique_array_conversion
////////////////////////////////
namespace return_unique_array_conversion{
template<class T>
bml::unique_ptr<T[]> return_unique_array_of_t(std::size_t n)
{
return bml::unique_ptr<T[]>(new T[n]);
}
template<class T>
bml::unique_ptr<const T[]> return_const_array_of_t(std::size_t n)
{
return bml::unique_ptr<const T[]>(return_unique_array_of_t<T>(n));
}
template<class T>
bml::unique_ptr<T[2]> return_unique_array_of_t_2()
{
return bml::unique_ptr<T[2]>(new T[2]);
}
template<class T>
bml::unique_ptr<const T[2]> return_const_array_of_t_2()
{
return bml::unique_ptr<const T[2]>(return_unique_array_of_t_2<T>());
}
void test()
{
reset_counters();
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A[]> p(return_unique_array_of_t<A>(2));
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[]> p(return_unique_array_of_t<volatile A>(2));
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[2]> p(return_const_array_of_t_2<A>());
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[]> p(return_const_array_of_t_2<A>());
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
}
} //namespace return_unique_array_conversion{
////////////////////////////////
// main
////////////////////////////////
int main()
{
//Constructors/Destructor
unique_ptr_dtor_null::test();
unique_ptr_ctor_default_delreq::test();
unique_ptr_ctor_default_nocomplete::test();
unique_ptr_ctor_pointer_delreq::test();
unique_ptr_ctor_pointer_nocomplete::test();
unique_ptr_ctor_pointer_convert::test();
unique_ptr_ctor_pointer_deleter_movedel::test();
unique_ptr_ctor_pointer_deleter_copydel::test();
unique_ptr_ctor_pointer_deleter_dfctrdelref::test();
unique_ptr_ctor_pointer_deleter_dfctrdelconstref::test();
unique_ptr_ctor_pointer_deleter_convert::test();
unique_ptr_ctor_pointer_deleter_void::test();
return_unique_single_conversion::test();
return_unique_array_conversion::test();
//Test results
return boost::report_errors();
}
#include "unique_ptr_test_utils_end.hpp"