/* AllocationCluster(Test) - verify bulk (de)allocating a family of objects Copyright (C) Lumiera.org 2008, Hermann Vosseler 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 #include #include 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 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 PCluster; typedef vector ClusterList; inline char truncChar (uint x) { return x % numeric_limits::max(); } template void place_object (AllocationCluster& clu, uint id) { clu.create > (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 (arg[0]); if (1 < arg.size()) NUM_OBJECTS = lexical_cast (arg[1]); if (2 < arg.size()) NUM_FAMILIES = lexical_cast (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<37>& ref2 = clu.create > (c1); Dummy<37>& ref3 = clu.create > (c2); Dummy<1234>& rX = clu.create > (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. } 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 > (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