diff --git a/tests/common/scopedholdertest.cpp b/tests/common/scopedholdertest.cpp index 50ed8f360..2337d60df 100644 --- a/tests/common/scopedholdertest.cpp +++ b/tests/common/scopedholdertest.cpp @@ -120,7 +120,7 @@ namespace lib { { HO holder; - magic = true; + throw_in_ctor = true; try { create_contained_object (holder); @@ -134,7 +134,7 @@ namespace lib { } ASSERT (!holder); /* because the exception happens in ctor object doesn't count as "created" */ - magic = false; + throw_in_ctor = false; } ASSERT (0==checksum); } diff --git a/tests/common/scopedholdertransfertest.cpp b/tests/common/scopedholdertransfertest.cpp index b933ad253..7507cfbdd 100644 --- a/tests/common/scopedholdertransfertest.cpp +++ b/tests/common/scopedholdertransfertest.cpp @@ -39,22 +39,63 @@ namespace lib { using ::Test; using util::isnil; - using std::map; + using std::vector; using std::cout; + namespace { // extending the Dummy for our special purpose.... + + bool throw_in_transfer = false; + + class FixedDummy + : public Dummy + { + public: + FixedDummy() + { + TRACE (test, "CTOR FixedDummy() --> this=%x val=%d", this, getVal()); + } + + ~FixedDummy() + { + TRACE (test, "DTOR ~FixedDummy() this=%x val=%d", this, getVal()); + } + + friend void + transfer_control (FixedDummy& from, FixedDummy& to) + { + TRACE (test, "TRANSFER target=%x <-- source=%x (%d,%d)", &to,&from, to.getVal(),from.getVal()); + + if (throw_in_transfer) + throw to.getVal(); + + to.setVal (from.getVal()); + from.setVal(0); + } + + }; + + + typedef ScopedHolder HolderD; + typedef ScopedPtrHolder PtrHolderD; + + template + struct Table + { + typedef Allocator_TransferNoncopyable Allo; + typedef typename std::vector Type; + + }; + } - typedef ScopedHolder HolderD; - typedef ScopedPtrHolder PtrHolderD; /********************************************************************************** - * @test ScopedHolder and ScopedPtrHolder are initially empty and copyable. - * After taking ownership, they prohibit copy operations, manage the - * lifecycle of the contained object and provide smart-ptr like access. - * A series of identical tests is conducted both with the ScopedPtrHolder - * (the contained objects are heap allocated but managed by the holder) - * and with the ScopedHolder (objects placed inline) + * @test growing a vector containing noncopyable objects wrapped into ScopedHolder + * instances. This requires the use of a custom allocator, invoking a + * \c transfer_control() function to be provided for the concrete + * noncopyable class type, being invoked when the vector + * needs to reallocate. */ class ScopedHolderTransfer_test : public Test { @@ -74,8 +115,8 @@ namespace lib { checkErrorHandling(); } - void create_contained_object (HolderD& holder) { holder.create(); } - void create_contained_object (PtrHolderD& holder) { holder.reset(new Dummy()); } + void create_contained_object (HolderD& holder) { holder.create(); } + void create_contained_object (PtrHolderD& holder) { holder.reset(new FixedDummy()); } template @@ -84,30 +125,23 @@ namespace lib { { ASSERT (0==checksum); { - UNIMPLEMENTED ("create constant sized vector holding noncopyables"); - HO holder; - ASSERT (!holder); + typedef typename Table::Type Vect; + + Vect table(50); ASSERT (0==checksum); - create_contained_object (holder); - ASSERT (holder); - ASSERT (false!=holder); - ASSERT (holder!=false); + for (uint i=0; i<10; ++i) + create_contained_object (table[i]); - ASSERT (0!=checksum); - ASSERT ( &(*holder)); - ASSERT (holder->add(2) == checksum+2); + ASSERT (0 < checksum); + ASSERT ( table[9]); + ASSERT (!table[10]); - Dummy *rawP = holder.get(); + Dummy *rawP = table[5].get(); ASSERT (rawP); - ASSERT (holder); - ASSERT (rawP == &(*holder)); - ASSERT (rawP->add(-5) == holder->add(-5)); - - TRACE (test, "holder at %x", &holder); - TRACE (test, "object at %x", holder.get() ); - TRACE (test, "size(object) = %d", sizeof(*holder)); - TRACE (test, "size(holder) = %d", sizeof(holder)); + ASSERT (table[5]); + ASSERT (rawP == &(*table[5])); + ASSERT (rawP->add(-555) == table[5]->add(-555)); } ASSERT (0==checksum); } @@ -119,7 +153,25 @@ namespace lib { { ASSERT (0==checksum); { - UNIMPLEMENTED ("check growing a vector holding noncopyables"); + typedef typename Table::Type Vect; + + Vect table; + table.reserve(2); + ASSERT (0==checksum); + + cout << "\n..install one element at index[0]\n"; + table.push_back(HO()); + ASSERT (0==checksum); + + create_contained_object (table[0]); // switches into "managed" state + ASSERT (0 < checksum); + int theSum = checksum; + + cout << "\n..*** resize table to 16 elements\n"; + for (uint i=0; i<15; ++i) + table.push_back(HO()); + + ASSERT (theSum==checksum); } ASSERT (0==checksum); } @@ -129,26 +181,48 @@ namespace lib { void checkErrorHandling() { - UNIMPLEMENTED ("throw an error while growing"); ASSERT (0==checksum); { - HO holder; + typedef typename Table::Type Vect; - magic = true; + Vect table(5); + table.reserve(5); + ASSERT (0==checksum); + + create_contained_object (table[2]); + create_contained_object (table[4]); + ASSERT (0 < checksum); + int theSum = checksum; + + cout << "\n.throw some exceptions...\n"; + throw_in_ctor = true; try { - create_contained_object (holder); + create_contained_object (table[3]); NOTREACHED ; } catch (int val) { - ASSERT (0!=checksum); + ASSERT (theSum < checksum); checksum -= val; - ASSERT (0==checksum); + ASSERT (theSum==checksum); } - ASSERT (!holder); /* because the exception happens in ctor - object doesn't count as "created" */ - magic = false; + ASSERT ( table[2]); + ASSERT (!table[3]); // not created because of exception + ASSERT ( table[4]); + + throw_in_ctor = false; + throw_in_transfer=true; // can do this only when using ScopedHolder + try + { + table.resize(10); + } + catch (int val) + { + ASSERT ( table.size() < 10); + } + ASSERT (theSum == checksum); + throw_in_transfer=false; } ASSERT (0==checksum); } diff --git a/tests/common/testdummy.hpp b/tests/common/testdummy.hpp index 31db265b3..7bfffb4bc 100644 --- a/tests/common/testdummy.hpp +++ b/tests/common/testdummy.hpp @@ -31,7 +31,7 @@ namespace lib { namespace { // yet another test dummy long checksum = 0; - bool magic = false; + bool throw_in_ctor = false; class Dummy : boost::noncopyable @@ -43,7 +43,7 @@ namespace lib { : val_(1 + (rand() % 100000000)) { checksum += val_; - if (magic) + if (throw_in_ctor) throw val_; }