SGSharedPtr: add unit tests

Add unit tests for move ctor and move assignment operator, as well for a
few other SGSharedPtr methods.
This commit is contained in:
Florent Rougon
2017-11-11 13:31:42 +01:00
parent fedafb9352
commit f22b9ba9f1

View File

@@ -3,6 +3,8 @@
// Unit tests for reference counting and smart pointer classes
#include <iostream>
#include <utility>
#include <cstdlib> // EXIT_SUCCESS
#include <simgear/misc/test_macros.hxx>
@@ -37,6 +39,7 @@ void test_SGSharedPtr()
SG_CHECK_EQUAL( ReferenceCounted::count(ptr.get()), 1 );
SG_CHECK_EQUAL( ptr.getNumRefs(), 1 );
// Test SGSharedPtr's copy assignment operator
RefPtr ptr2 = ptr;
SG_CHECK_EQUAL( ptr.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptr2.getNumRefs(), 2 );
@@ -44,6 +47,7 @@ void test_SGSharedPtr()
SG_CHECK_EQUAL( ptr, ptr2 );
SG_CHECK_EQUAL( ptr.get(), ptr2.get() );
// Test SGSharedPtr::reset() with no argument
ptr.reset();
SG_CHECK_IS_NULL( ptr.get() );
SG_CHECK_EQUAL( ptr.getNumRefs(), 0 );
@@ -55,6 +59,121 @@ void test_SGSharedPtr()
SG_CHECK_EQUAL( ptr.getNumRefs(), 0 );
SG_CHECK_EQUAL( ptr2.getNumRefs(), 0 );
SG_CHECK_EQUAL( instance_count, 0) ;
// Test operator==() and operator!=() for SGSharedPtr
{
RefPtr ptrA(new ReferenceCounted());
RefPtr ptrB(ptrA);
RefPtr ptrC(new ReferenceCounted());
RefPtr emptyPtr{};
SG_CHECK_EQUAL( ptrA, ptrB );
SG_CHECK_EQUAL( ptrA.get(), ptrB.get() ); // same thing by definition
SG_CHECK_NE( ptrA, ptrC );
SG_CHECK_NE( ptrA.get(), ptrC.get() );
SG_CHECK_NE( ptrB, ptrC );
SG_CHECK_NE( ptrA, emptyPtr );
SG_CHECK_EQUAL( emptyPtr, emptyPtr );
}
// Test SGSharedPtr::reset(T* p) and SGSharedPtr::operator T*()
{
RefPtr ptrA(new ReferenceCounted());
SG_CHECK_EQUAL( ptrA.getNumRefs(), 1 );
RefPtr ptrB(new ReferenceCounted());
SG_CHECK_NE( ptrA, ptrB );
ptrB.reset(ptrA);
SG_CHECK_EQUAL( ptrA, ptrB );
SG_CHECK_EQUAL( ptrA.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrB.getNumRefs(), 2 );
RefPtr ptrC(new ReferenceCounted());
SG_CHECK_NE( ptrA, ptrC );
SG_CHECK_EQUAL( ptrC.getNumRefs(), 1 );
// ptrA is implicit converted to ReferenceCounted*
ptrC.reset(ptrA);
SG_CHECK_EQUAL( ptrA.getNumRefs(), 3 );
SG_CHECK_EQUAL( ptrB.getNumRefs(), 3 );
SG_CHECK_EQUAL( ptrC.getNumRefs(), 3 );
SG_CHECK_EQUAL( ptrA, ptrB );
SG_CHECK_EQUAL( ptrB, ptrC );
}
// Test SGSharedPtr's copy constructor
{
RefPtr ptrA(new ReferenceCounted());
SG_CHECK_EQUAL( ptrA.getNumRefs(), 1 );
RefPtr ptrB(ptrA);
SG_CHECK_EQUAL( ptrA.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrB.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrA, ptrB );
}
// Test SGSharedPtr's move constructor
{
RefPtr ptrA(new ReferenceCounted());
RefPtr ptrB(ptrA);
RefPtr ptrC(std::move(ptrA));
SG_CHECK_EQUAL( ptrB.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrC.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrB, ptrC );
// Although our implementation has these two properties, they are
// absolutely *not* guaranteed by the C++ move semantics:
SG_CHECK_EQUAL( ptrA.getNumRefs(), 0 );
SG_CHECK_IS_NULL( ptrA.get() );
}
// Test SGSharedPtr's move assignment operator: self-move, supposedly
// undefined behavior but certainly safer as a no-op---which the
// copy-and-swap idiom offers for free.
{
RefPtr ptrA(new ReferenceCounted());
RefPtr ptrB(ptrA);
ptrA = std::move(ptrA);
SG_CHECK_EQUAL( ptrA.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrB.getNumRefs(), 2 );
SG_CHECK_IS_NOT_NULL( ptrA.get() );
SG_CHECK_EQUAL( ptrA, ptrB );
}
// Test SGSharedPtr's move assignment operator: move to an empty SGSharedPtr
{
RefPtr ptrA;
RefPtr ptrB(new ReferenceCounted());
ptrA = std::move(ptrB);
SG_CHECK_EQUAL( ptrA.getNumRefs(), 1 );
SG_CHECK_IS_NOT_NULL( ptrA.get() );
// Implementation detail that is *not* guaranteed by the C++ move
// semantics:
SG_CHECK_EQUAL( ptrB.getNumRefs(), 0 );
SG_CHECK_IS_NULL( ptrB.get() );
}
// Test SGSharedPtr's move assignment operator: move to a non-empty
// SGSharedPtr
{
RefPtr ptrA(new ReferenceCounted());
RefPtr ptrB(ptrA);
RefPtr ptrC(new ReferenceCounted());
SG_CHECK_EQUAL( ptrA.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrB.getNumRefs(), 2 );
SG_CHECK_EQUAL( ptrC.getNumRefs(), 1 );
SG_CHECK_EQUAL( ptrA, ptrB );
SG_CHECK_NE( ptrA, ptrC );
ptrA = std::move(ptrC);
SG_CHECK_EQUAL( ptrA.getNumRefs(), 1 );
SG_CHECK_EQUAL( ptrB.getNumRefs(), 1 );
SG_CHECK_NE( ptrA, ptrB );
// Implementation detail that is *not* guaranteed by the C++ move
// semantics:
SG_CHECK_IS_NULL( ptrC.get() );
}
}
class Base1: