lumiera_/tests/library/allocation-cluster-test.cpp
Ichthyostega ada5cefaaf re-arrange tests according to layer structure
the buildsystem will now pick up and link
all test cases according to the layer, e.g.
backend tests will automatically be linked
against the backend + library solely.
2013-01-07 05:43:01 +01:00

239 lines
6.6 KiB
C++

/*
AllocationCluster(Test) - verify bulk (de)allocating a family of objects
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 "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/util-foreach.hpp"
#include "lib/allocation-cluster.hpp"
#include "lib/scoped-holder.hpp"
#include <vector>
#include <limits>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
using lib::test::showSizeof;
using util::for_each;
using util::isnil;
using ::Test;
using std::numeric_limits;
using std::vector;
namespace lib {
namespace test {
namespace { // a family of test dummy classes
uint NUM_CLUSTERS = 5;
uint NUM_OBJECTS = 500;
uint NUM_FAMILIES = 5;
long checksum = 0; // validate proper pairing of ctor/dtor calls
bool randomFailures = false;
template<uint i>
class Dummy
{
char content[i];
public:
Dummy (char id=1)
{
content[0] = id;
checksum += id;
}
Dummy (char i1, char i2, char i3=0)
{
char id = i1 + i2 + i3;
content[0] = id;
checksum += id;
if (randomFailures && 0 == (rand() % 20))
throw id;
}
~Dummy()
{
checksum -= content[0];
}
char getID() { return content[0]; }
};
typedef ScopedHolder<AllocationCluster> PCluster;
typedef vector<PCluster> ClusterList;
inline char
truncChar (uint x)
{
return x % numeric_limits<char>::max();
}
template<uint i>
void
place_object (AllocationCluster& clu, uint id)
{
clu.create<Dummy<i> > (id);
}
typedef void (Invoker)(AllocationCluster&, uint);
Invoker* invoke[20] = { &place_object<1>
, &place_object<2>
, &place_object<3>
, &place_object<5>
, &place_object<10>
, &place_object<13>
, &place_object<14>
, &place_object<15>
, &place_object<16>
, &place_object<17>
, &place_object<18>
, &place_object<19>
, &place_object<20>
, &place_object<25>
, &place_object<30>
, &place_object<35>
, &place_object<40>
, &place_object<50>
, &place_object<100>
, &place_object<200>
};
void
fillIt (PCluster& clu)
{
clu.create();
if (20<NUM_FAMILIES)
NUM_FAMILIES = 20;
for (uint i=0; i<NUM_OBJECTS; ++i)
{
char id = truncChar(i);
(*(invoke[rand() % NUM_FAMILIES])) (*clu,id);
}
}
}
/*************************************************************************
* @test verify the proper workings of our custom allocation scheme
* managing families of interconnected objects for the segments
* of the low-level model.
*/
class AllocationCluster_test : public Test
{
virtual void
run (Arg arg)
{
if (0 < arg.size()) NUM_CLUSTERS = lexical_cast<uint> (arg[0]);
if (1 < arg.size()) NUM_OBJECTS = lexical_cast<uint> (arg[1]);
if (2 < arg.size()) NUM_FAMILIES = lexical_cast<uint> (arg[2]);
simpleUsage();
checkAllocation();
checkErrorHandling();
}
void
simpleUsage()
{
AllocationCluster clu;
char c1(123), c2(56), c3(3), c4(4), c5(5);
Dummy<44>& ref1 = clu.create<Dummy<44> > ();
Dummy<37>& ref2 = clu.create<Dummy<37> > (c1);
Dummy<37>& ref3 = clu.create<Dummy<37> > (c2);
Dummy<1234>& rX = clu.create<Dummy<1234> > (c3,c4,c5);
CHECK (&ref1);
CHECK (&ref2);
CHECK (&ref3);
CHECK (&rX);
TRACE (test, "%s", showSizeof(rX).c_str());
CHECK (123==ref2.getID());
CHECK (3+4+5==rX.getID());
// shows that the returned references actually
// point at the objects we created. Just use them
// and let them go. When clu goes out of scope,
// all created object's dtors will be invoked.
CHECK (4 == clu.size());
CHECK (1 == clu.count<Dummy<44> >());
CHECK (2 == clu.count<Dummy<37> >());
CHECK (1 == clu.count<Dummy<1234> >());
}
void
checkAllocation()
{
CHECK (0==checksum);
{
ClusterList clusters (NUM_CLUSTERS);
for_each (clusters, fillIt);
CHECK (0!=checksum);
}
CHECK (0==checksum);
}
void
checkErrorHandling()
{
CHECK (0==checksum);
{
randomFailures = true;
AllocationCluster clu;
for (uint i=0; i<NUM_OBJECTS; ++i)
try
{
char i1 = truncChar(i);
char i2 = truncChar(rand() % 5);
clu.create<Dummy<1> > (i1,i2);
}
catch (char id)
{
checksum -= id; // exception thrown from within constructor,
} // thus dtor won't be called. Repair the checksum!
}
randomFailures = false;
CHECK (0==checksum);
}
};
LAUNCHER (AllocationCluster_test, "unit common");
}} // namespace lib::test