make ctor-tracking test::Dummy more widely usable

This commit is contained in:
Fischlurch 2011-11-25 22:05:12 +01:00
parent 55a77bdd73
commit 2fce2b1c8d
7 changed files with 182 additions and 164 deletions

View file

@ -22,6 +22,7 @@
#include "lib/test/test-helper.hpp"
#include "lib/test/testdummy.hpp"
#include <boost/format.hpp>
@ -55,7 +56,12 @@ namespace test{
garbage[--p] = alpha[rand() % MAXAL];
return garbage;
}
/** storage for testdummy flags */
long Dummy::_local_checksum = 0;
bool Dummy::_throw_in_ctor = false;
}} // namespace lib::test

View file

@ -0,0 +1,99 @@
/*
TESTDUMMY.hpp - yet another test dummy for tracking ctor/dtor calls
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include <boost/noncopyable.hpp>
#include <algorithm>
namespace lib {
namespace test{
class Dummy
: boost::noncopyable
{
int val_;
/** to verify ctor/dtor calls */
static long _local_checksum;
static bool _throw_in_ctor;
public:
Dummy ()
: val_(1 + (rand() % 100000000))
{ init(); }
Dummy (int v)
: val_(v)
{ init(); }
~Dummy()
{
checksum() -= val_;
}
long add (int i) { return val_+i; }
int getVal() const { return val_; }
void
setVal (int newVal)
{
checksum() += newVal - val_;
val_ = newVal;
}
friend void
swap (Dummy& dum1, Dummy& dum2) ///< checksum neutral
{
std::swap(dum1.val_, dum2.val_);
}
static long&
checksum()
{
return _local_checksum;
}
static void
activateCtorFailure(bool indeed =true)
{
_throw_in_ctor = indeed;
}
private:
void
init()
{
checksum() += val_;
if (_throw_in_ctor)
throw val_;
}
};
}} // namespace lib::test

View file

@ -28,7 +28,7 @@
#include "lib/error.hpp"
#include "lib/scoped-holder.hpp"
#include "testdummy.hpp"
#include "lib/test/testdummy.hpp"
#include <boost/noncopyable.hpp>
#include <iostream>
@ -85,20 +85,20 @@ namespace test{
void
checkAllocation()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
HO holder;
CHECK (!holder);
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
create_contained_object (holder);
CHECK (holder);
CHECK (false!=holder);
CHECK (holder!=false);
CHECK (0!=checksum);
CHECK (0 != Dummy::checksum());
CHECK ( &(*holder));
CHECK (holder->add(2) == checksum+2);
CHECK (holder->add(2) == 2 + Dummy::checksum());
Dummy *rawP = holder.get();
CHECK (rawP);
@ -111,7 +111,7 @@ namespace test{
TRACE (test, "size(object) = %lu", sizeof(*holder));
TRACE (test, "size(holder) = %lu", sizeof(holder));
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
@ -119,11 +119,11 @@ namespace test{
void
checkErrorHandling()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
HO holder;
throw_in_ctor = true;
Dummy::activateCtorFailure();
try
{
create_contained_object (holder);
@ -131,15 +131,15 @@ namespace test{
}
catch (int val)
{
CHECK (0!=checksum);
checksum -= val;
CHECK (0==checksum);
CHECK (0 != Dummy::checksum());
Dummy::checksum() -= val;
CHECK (0 == Dummy::checksum());
}
CHECK (!holder); /* because the exception happens in ctor
object doesn't count as "created" */
throw_in_ctor = false;
Dummy::activateCtorFailure(false);
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
@ -147,7 +147,7 @@ namespace test{
void
checkCopyProtocol()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
HO holder;
HO holder2 (holder);
@ -158,38 +158,38 @@ namespace test{
CHECK (!holder);
create_contained_object (holder);
CHECK (holder);
long currSum = checksum;
long currSum = Dummy::checksum();
void* adr = holder.get();
VERIFY_ERROR(LOGIC, holder2 = holder );
CHECK (holder);
CHECK (!holder2);
CHECK (holder.get()==adr);
CHECK (checksum==currSum);
CHECK (Dummy::checksum()==currSum);
VERIFY_ERROR(LOGIC, holder = holder2 );
CHECK (holder);
CHECK (!holder2);
CHECK (holder.get()==adr);
CHECK (checksum==currSum);
CHECK (Dummy::checksum()==currSum);
create_contained_object (holder2);
CHECK (holder2);
CHECK (checksum != currSum);
currSum = checksum;
CHECK (Dummy::checksum() != currSum);
currSum = Dummy::checksum();
VERIFY_ERROR(LOGIC, holder = holder2 );
CHECK (holder);
CHECK (holder2);
CHECK (holder.get()==adr);
CHECK (checksum==currSum);
CHECK (Dummy::checksum()==currSum);
VERIFY_ERROR(LOGIC, HO holder3 (holder2) );
CHECK (holder);
CHECK (holder2);
CHECK (checksum==currSum);
CHECK (Dummy::checksum()==currSum);
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
@ -202,7 +202,7 @@ namespace test{
{
typedef std::map<int,HO> MapHO;
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
MapHO maph;
CHECK (isnil (maph));
@ -212,8 +212,8 @@ namespace test{
HO & contained = maph[i];
CHECK (!contained);
} // 100 holder objects created by sideeffect
CHECK (0==checksum); // ..... without creating any contained object!
// ..... without creating any contained object!
CHECK (0 == Dummy::checksum());
CHECK (!isnil (maph));
CHECK (100==maph.size());
@ -224,14 +224,14 @@ namespace test{
CHECK (0 < maph[i]->add(12));
}
CHECK (100==maph.size());
CHECK (0!=checksum);
CHECK (0 != Dummy::checksum());
long value55 = maph[55]->add(0);
long currSum = checksum;
long currSum = Dummy::checksum();
CHECK (1 == maph.erase(55));
CHECK (checksum == currSum - value55); // proves object#55's dtor has been invoked
CHECK (Dummy::checksum() == currSum - value55); // proves object#55's dtor has been invoked
CHECK (maph.size() == 99);
maph[55]; // create new empty holder by sideeffect...
@ -239,7 +239,7 @@ namespace test{
CHECK (!maph[55]);
CHECK (maph.size() == 100);
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}

View file

@ -27,7 +27,7 @@
#include "lib/scoped-holder.hpp"
#include "lib/scoped-holder-transfer.hpp"
#include "testdummy.hpp"
#include "lib/test/testdummy.hpp"
#include <iostream>
#include <vector>
@ -125,17 +125,17 @@ namespace test {
void
buildVector()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
typedef typename Table<HO>::Type Vect;
Vect table(50);
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
for (uint i=0; i<10; ++i)
create_contained_object (table[i]);
CHECK (0 < checksum);
CHECK (0 < Dummy::checksum());
CHECK ( table[9]);
CHECK (!table[10]);
@ -145,7 +145,7 @@ namespace test {
CHECK (rawP == &(*table[5]));
CHECK (rawP->add(-555) == table[5]->add(-555));
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
@ -153,29 +153,29 @@ namespace test {
void
growVector()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
typedef typename Table<HO>::Type Vect;
Vect table;
table.reserve(2);
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
cout << ".\n..install one element at index[0]\n";
table.push_back(HO());
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
create_contained_object (table[0]); // switches into "managed" state
CHECK (0 < checksum);
int theSum = checksum;
CHECK (0 < Dummy::checksum());
int theSum = Dummy::checksum();
cout << ".\n..*** resize table to 16 elements\n";
for (uint i=0; i<15; ++i)
table.push_back(HO());
CHECK (theSum==checksum);
CHECK (theSum == Dummy::checksum());
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
@ -183,37 +183,37 @@ namespace test {
void
checkErrorHandling()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
typedef typename Table<HO>::Type Vect;
Vect table(5);
table.reserve(5);
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
create_contained_object (table[2]);
create_contained_object (table[4]);
CHECK (0 < checksum);
int theSum = checksum;
CHECK (0 < Dummy::checksum());
int theSum = Dummy::checksum();
cout << ".\n.throw some exceptions...\n";
throw_in_ctor = true;
Dummy::activateCtorFailure();
try
{
create_contained_object (table[3]);
NOTREACHED ();
NOTREACHED ("ctor should throw");
}
catch (int val)
{
CHECK (theSum < checksum);
checksum -= val;
CHECK (theSum==checksum);
CHECK (theSum < Dummy::checksum());
Dummy::checksum() -= val;
CHECK (theSum == Dummy::checksum());
}
CHECK ( table[2]);
CHECK (!table[3]); // not created because of exception
CHECK ( table[4]);
throw_in_ctor = false;
Dummy::activateCtorFailure(false);
throw_in_transfer=true; // can do this only when using ScopedHolder
try
{
@ -223,10 +223,10 @@ namespace test {
{
CHECK ( table.size() < 10);
}
CHECK (theSum == checksum);
CHECK (theSum == Dummy::checksum());
throw_in_transfer=false;
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
};

View file

@ -27,7 +27,7 @@
#include "lib/util.hpp"
#include "lib/scoped-ptrvect.hpp"
#include "testdummy.hpp"
#include "lib/test/testdummy.hpp"
namespace lib {
@ -63,16 +63,16 @@ namespace test{
void
simpleUsage()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
VectD holder;
CHECK (isnil (holder));
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
Dummy* ptr = new Dummy();
Dummy& ref = holder.manage (ptr);
CHECK (!isnil (holder));
CHECK (0!=checksum);
CHECK (0 != Dummy::checksum());
CHECK (&ref==ptr);
holder.manage (new Dummy);
@ -80,7 +80,7 @@ namespace test{
CHECK (3 == holder.size());
holder.clear();
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
CHECK (isnil (holder));
holder.manage (new Dummy);
@ -93,16 +93,16 @@ namespace test{
holder.manage (new Dummy);
holder.manage (new Dummy);
CHECK (9 == holder.size());
CHECK (0 < checksum);
CHECK (0 < Dummy::checksum());
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
void
iterating()
{
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
VectD holder;
for (int i=0; i<16; ++i)
@ -142,7 +142,7 @@ namespace test{
VERIFY_ERROR (ITER_EXHAUST, ++cii );
}
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
@ -151,10 +151,10 @@ namespace test{
{
int id2, id3;
Dummy* extracted(0);
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
{
VectD holder;
CHECK (0 == checksum);
CHECK (0 == Dummy::checksum());
CHECK (isnil (holder));
holder.manage (new Dummy);
@ -163,7 +163,7 @@ namespace test{
holder.manage (new Dummy);
holder.manage (new Dummy);
CHECK (5 == holder.size());
CHECK (0 < checksum);
CHECK (0 < Dummy::checksum());
id2 = holder[2].getVal();
id3 = holder[3].getVal();
@ -173,14 +173,14 @@ namespace test{
CHECK (id3 == holder[2].getVal());
CHECK (4 == holder.size());
}
CHECK (0 < checksum); // not all dummies are dead
CHECK (id2 == checksum); // #2 is alive!
CHECK (0 < Dummy::checksum()); // not all dummies are dead
CHECK (id2 == Dummy::checksum()); // #2 is alive!
extracted->setVal(id2+id3);
CHECK (id2+id3 == checksum);
CHECK (id2+id3 == Dummy::checksum());
delete extracted;
CHECK (0 == checksum);
CHECK (0 == Dummy::checksum());
}
};

View file

@ -1,87 +0,0 @@
/*
TESTDUMMY.hpp - yet another test dummy for tracking ctor/dtor calls
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include <boost/noncopyable.hpp>
#include <algorithm>
namespace lib {
namespace test{
namespace { // yet another test dummy
long checksum = 0;
bool throw_in_ctor = false;
class Dummy
: boost::noncopyable
{
int val_;
public:
Dummy ()
: val_(1 + (rand() % 100000000))
{ init(); }
Dummy (int v)
: val_(v)
{ init(); }
~Dummy()
{
checksum -= val_;
}
long add (int i) { return val_+i; }
int getVal() const { return val_; }
void
setVal (int newVal)
{
checksum += newVal - val_;
val_ = newVal;
}
friend void
swap (Dummy& dum1, Dummy& dum2) ///< checksum neutral
{
std::swap(dum1.val_, dum2.val_);
}
private:
void
init()
{
checksum += val_;
if (throw_in_ctor)
throw val_;
}
};
} // anonymous test dummy
}} // namespace lib::test

View file

@ -25,7 +25,7 @@
#include "lib/test/run.hpp"
#include "lib/scoped-holder-transfer.hpp"
#include "testdummy.hpp"
#include "lib/test/testdummy.hpp"
#include <iostream>
#include <vector>
@ -130,27 +130,27 @@ namespace test {
cout << "\n..setup table space for 2 elements\n";
TransDummyVector table;
table.reserve(2);
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
cout << "\n..install one element at index[0]\n";
table.push_back(TransDummy());
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
table[0].setup(); // switches into "managed" state
CHECK (0 < checksum);
int theSum = checksum;
CHECK (0 < Dummy::checksum());
int theSum = Dummy::checksum();
cout << "\n..*** resize table to 5 elements\n";
table.resize(5);
CHECK (theSum==checksum);
CHECK (theSum==Dummy::checksum());
cout << "\n..install another element\n";
table[3].setup(375);
CHECK (theSum+375==checksum);
CHECK (theSum+375==Dummy::checksum());
cout << "\n..kill all elements....\n";
table.clear();
CHECK (0==checksum);
CHECK (0 == Dummy::checksum());
}
};