mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-30 13:47:10 +01:00
more tests and other changes
- ported complete suite of boost::any tests - improved reference casting - added swap in SOO version
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
|
#include "Poco/MetaProgramming.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
@@ -84,6 +85,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
~Any()
|
~Any()
|
||||||
|
/// Destructor. If Any is locally held, calls Placeholder destructor;
|
||||||
|
/// otherwise, deletes the placeholder from the heap.
|
||||||
{
|
{
|
||||||
if(!empty())
|
if(!empty())
|
||||||
{
|
{
|
||||||
@@ -94,24 +97,44 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Any& swap(Any& other)
|
||||||
|
/// Swaps the content of the two Anys.
|
||||||
|
///
|
||||||
|
/// When small object optimizaton (SOO) is enabled,
|
||||||
|
/// swap is only exception-safe when both (*this and
|
||||||
|
/// other) objects are allocated on the heap.
|
||||||
|
{
|
||||||
|
if (!isLocal() && !other.isLocal())
|
||||||
|
{
|
||||||
|
std::swap(_placeholder.pHolder, other._placeholder.pHolder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Any tmp(*this);
|
||||||
|
if (isLocal()) this->~Any();
|
||||||
|
construct(other);
|
||||||
|
other = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
Any & operator=(const ValueType& value)
|
Any & operator = (const ValueType& rhs)
|
||||||
/// Assignment operator for all types != Any.
|
/// Assignment operator for all types != Any.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// Any a = 13;
|
/// Any a = 13;
|
||||||
/// Any a = string("12345");
|
/// Any a = string("12345");
|
||||||
{
|
{
|
||||||
if (isLocal()) this->~Any();
|
Any(rhs).swap(*this);
|
||||||
construct(value);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Any& operator = (Any value)
|
Any& operator = (Any rhs)
|
||||||
/// Assignment operator for Any.
|
/// Assignment operator for Any.
|
||||||
{
|
{
|
||||||
if (isLocal()) this->~Any();
|
Any(rhs).swap(*this);
|
||||||
construct(value);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +215,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void construct(const ValueType & value)
|
void construct(const ValueType& value)
|
||||||
{
|
{
|
||||||
if (sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE)
|
if (sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE)
|
||||||
{
|
{
|
||||||
@@ -206,7 +229,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void construct(const Any & other)
|
void construct(const Any& other)
|
||||||
{
|
{
|
||||||
if(other.empty())
|
if(other.empty())
|
||||||
erase(_placeholder.holder);
|
erase(_placeholder.holder);
|
||||||
@@ -408,9 +431,9 @@ ValueType AnyCast(const Any& operand)
|
|||||||
/// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
|
/// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
|
||||||
/// these cases.
|
/// these cases.
|
||||||
{
|
{
|
||||||
ValueType* result = AnyCast<ValueType>(const_cast<Any*>(&operand));
|
typedef TypeWrapper<ValueType>::TYPE NonRef;
|
||||||
if (!result) throw BadCastException("Failed to convert between const Any types");
|
|
||||||
return *result;
|
return AnyCast<NonRef&>(const_cast<Any&>(operand));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -425,7 +448,9 @@ ValueType AnyCast(Any& operand)
|
|||||||
/// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
|
/// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
|
||||||
/// these cases.
|
/// these cases.
|
||||||
{
|
{
|
||||||
ValueType* result = AnyCast<ValueType>(&operand);
|
typedef TypeWrapper<ValueType>::TYPE NonRef;
|
||||||
|
|
||||||
|
NonRef* result = AnyCast<NonRef>(&operand);
|
||||||
if (!result) throw BadCastException("Failed to convert between Any types");
|
if (!result) throw BadCastException("Failed to convert between Any types");
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,156 @@ AnyTest::~AnyTest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testDefaultCtor()
|
||||||
|
{
|
||||||
|
const Any value;
|
||||||
|
|
||||||
|
assert (value.empty());
|
||||||
|
assert (0 == AnyCast<int>(&value));
|
||||||
|
assert (value.type() == typeid(void));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testConvertingCtor()
|
||||||
|
{
|
||||||
|
std::string text = "test message";
|
||||||
|
Any value = text;
|
||||||
|
|
||||||
|
assert (!value.empty());
|
||||||
|
assert (value.type() == typeid(std::string));
|
||||||
|
assert (0 == AnyCast<int>(&value));
|
||||||
|
assert (0 != AnyCast<std::string>(&value));
|
||||||
|
assert (AnyCast<std::string>(value) == text);
|
||||||
|
assert (AnyCast<std::string>(&value) != &text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testCopyCtor()
|
||||||
|
{
|
||||||
|
std::string text = "test message";
|
||||||
|
Any original = text, copy = original;
|
||||||
|
|
||||||
|
assert (!copy.empty());
|
||||||
|
assert (original.type() == copy.type());
|
||||||
|
assert (AnyCast<std::string>(original) == AnyCast<std::string>(copy));
|
||||||
|
assert (text == AnyCast<std::string>(copy));
|
||||||
|
assert(AnyCast<std::string>(&original) != AnyCast<std::string>(©));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testCopyAssign()
|
||||||
|
{
|
||||||
|
std::string text = "test message";
|
||||||
|
Any original = text, copy;
|
||||||
|
Any* assignResult = &(copy = original);
|
||||||
|
|
||||||
|
assert(!copy.empty());
|
||||||
|
assert(original.type() == copy.type());
|
||||||
|
assert(AnyCast<std::string>(original) == AnyCast<std::string>(copy));
|
||||||
|
assert(text == AnyCast<std::string>(copy));
|
||||||
|
assert(AnyCast<std::string>(&original) != AnyCast<std::string>(©));
|
||||||
|
assert(assignResult == ©);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testConvertingAssign()
|
||||||
|
{
|
||||||
|
std::string text = "test message";
|
||||||
|
Any value;
|
||||||
|
Any* assignResult = &(value = text);
|
||||||
|
|
||||||
|
assert (!value.empty());
|
||||||
|
assert(value.type() == typeid(std::string));
|
||||||
|
assert(0 == AnyCast<int>(&value));
|
||||||
|
assert(0 != AnyCast<std::string>(&value));
|
||||||
|
assert(AnyCast<std::string>(value) == text);
|
||||||
|
assert(AnyCast<std::string>(&value) != &text);
|
||||||
|
assert(assignResult == &value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testCastToReference()
|
||||||
|
{
|
||||||
|
Any a(137);
|
||||||
|
const Any b(a);
|
||||||
|
|
||||||
|
int& ra = AnyCast<int &>(a);
|
||||||
|
int const& ra_c = AnyCast<int const &>(a);
|
||||||
|
int volatile& ra_v = AnyCast<int volatile &>(a);
|
||||||
|
int const volatile& ra_cv = AnyCast<int const volatile&>(a);
|
||||||
|
|
||||||
|
// cv references to same obj
|
||||||
|
assert (&ra == &ra_c && &ra == &ra_v && &ra == &ra_cv);
|
||||||
|
|
||||||
|
int const & rb_c = AnyCast<int const &>(b);
|
||||||
|
int const volatile & rb_cv = AnyCast<int const volatile &>(b);
|
||||||
|
|
||||||
|
assert (&rb_c == &rb_cv); // cv references to copied const obj
|
||||||
|
assert (&ra != &rb_c); // copies hold different objects
|
||||||
|
|
||||||
|
++ra;
|
||||||
|
int incremented = AnyCast<int>(a);
|
||||||
|
assert (incremented == 138); // increment by reference changes value
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AnyCast<char &>(a);
|
||||||
|
failmsg ("AnyCast to incorrect reference type");
|
||||||
|
}
|
||||||
|
catch (BadCastException&) { }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AnyCast<const char &>(b),
|
||||||
|
failmsg ("AnyCast to incorrect const reference type");
|
||||||
|
}
|
||||||
|
catch (BadCastException&) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testBadCast()
|
||||||
|
{
|
||||||
|
std::string text = "test message";
|
||||||
|
Any value = text;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AnyCast<const char *>(value);
|
||||||
|
fail ("must throw");
|
||||||
|
}
|
||||||
|
catch (BadCastException&) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testSwap()
|
||||||
|
{
|
||||||
|
std::string text = "test message";
|
||||||
|
Any original = text, swapped;
|
||||||
|
std::string* originalPtr = AnyCast<std::string>(&original);
|
||||||
|
Any* swapResult = &original.swap(swapped);
|
||||||
|
|
||||||
|
assert (original.empty());
|
||||||
|
assert (!swapped.empty());
|
||||||
|
assert (swapped.type() == typeid(std::string));
|
||||||
|
assert (text == AnyCast<std::string>(swapped));
|
||||||
|
assert (0 != originalPtr);
|
||||||
|
assert (originalPtr == AnyCast<std::string>(&swapped));
|
||||||
|
assert (swapResult == &original);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnyTest::testEmptyCopy()
|
||||||
|
{
|
||||||
|
const Any null;
|
||||||
|
Any copied = null, assigned;
|
||||||
|
assigned = null;
|
||||||
|
|
||||||
|
assert (null.empty());
|
||||||
|
assert (copied.empty());
|
||||||
|
assert (assigned.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AnyTest::testInt()
|
void AnyTest::testInt()
|
||||||
{
|
{
|
||||||
Any e;
|
Any e;
|
||||||
@@ -119,8 +269,13 @@ void AnyTest::testVector()
|
|||||||
Any a = tmp;
|
Any a = tmp;
|
||||||
assert (a.type() == typeid(std::vector<int>));
|
assert (a.type() == typeid(std::vector<int>));
|
||||||
std::vector<int> tmp2 = AnyCast<std::vector<int> >(a);
|
std::vector<int> tmp2 = AnyCast<std::vector<int> >(a);
|
||||||
|
assert (tmp2.size() == 3);
|
||||||
const std::vector<int>& vecCRef = RefAnyCast<std::vector<int> >(a);
|
const std::vector<int>& vecCRef = RefAnyCast<std::vector<int> >(a);
|
||||||
std::vector<int>& vecRef = RefAnyCast<std::vector<int> >(a);
|
std::vector<int>& vecRef = RefAnyCast<std::vector<int> >(a);
|
||||||
|
|
||||||
|
assert (vecRef[0] == 1);
|
||||||
|
assert (vecRef[1] == 2);
|
||||||
|
assert (vecRef[2] == 3);
|
||||||
vecRef[0] = 0;
|
vecRef[0] = 0;
|
||||||
assert (vecRef[0] == vecCRef[0]);
|
assert (vecRef[0] == vecCRef[0]);
|
||||||
}
|
}
|
||||||
@@ -140,6 +295,15 @@ CppUnit::Test* AnyTest::suite()
|
|||||||
{
|
{
|
||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("AnyTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("AnyTest");
|
||||||
|
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testConvertingCtor);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testDefaultCtor);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testCopyCtor);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testCopyAssign);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testConvertingAssign);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testBadCast);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testSwap);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testEmptyCopy);
|
||||||
|
CppUnit_addTest(pSuite, AnyTest, testCastToReference);
|
||||||
CppUnit_addTest(pSuite, AnyTest, testInt);
|
CppUnit_addTest(pSuite, AnyTest, testInt);
|
||||||
CppUnit_addTest(pSuite, AnyTest, testComplexType);
|
CppUnit_addTest(pSuite, AnyTest, testComplexType);
|
||||||
CppUnit_addTest(pSuite, AnyTest, testVector);
|
CppUnit_addTest(pSuite, AnyTest, testVector);
|
||||||
|
|||||||
@@ -45,6 +45,16 @@ public:
|
|||||||
AnyTest(const std::string& name);
|
AnyTest(const std::string& name);
|
||||||
~AnyTest();
|
~AnyTest();
|
||||||
|
|
||||||
|
void testConvertingCtor();
|
||||||
|
void testDefaultCtor();
|
||||||
|
void testCopyCtor();
|
||||||
|
void testCopyAssign();
|
||||||
|
void testConvertingAssign();
|
||||||
|
void testBadCast();
|
||||||
|
void testSwap();
|
||||||
|
void testEmptyCopy();
|
||||||
|
void testCastToReference();
|
||||||
|
|
||||||
void testInt();
|
void testInt();
|
||||||
void testComplexType();
|
void testComplexType();
|
||||||
void testVector();
|
void testVector();
|
||||||
|
|||||||
Reference in New Issue
Block a user