lumiera_/tests/library/del-stash-test.cpp
2025-06-07 23:59:57 +02:00

256 lines
6.4 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
DelStash(Test) - verify a facility to memorise and trigger deleter functions
Copyright (C)
2010, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** 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. See the file COPYING for further details.
* *****************************************************************/
/** @file del-stash-test.cpp
** unit test \ref DelStash_test
*/
#include "lib/test/run.hpp"
#include "lib/del-stash.hpp"
namespace lib {
namespace test{
namespace { // probe victims
ulong MAX_MASS = 200; // number of victims to kill at once
ulong checksum = 0;
template<uint siz>
class Probe
{
uint mySiz_;
char myCrap_[siz];
public:
Probe()
: mySiz_(siz)
{
REQUIRE (siz);
for (uint i=0; i<siz; ++i)
{
char c (rani(256));
checksum += c;
myCrap_[i] = c;
}
}
~Probe()
{
CHECK (siz == mySiz_, "using wrong type information for de-allocation");
for (uint i=0; i<siz; ++i)
checksum -= myCrap_[i];
}
};
template<uint x>
inline Probe<x>*
makeViktim ()
{
return new Probe<x>();
}
template<uint x>
inline void
feedViktim (DelStash& killer)
{
killer.manage (new Probe<x>());
}
}//(End) test data
/************************************************************************//**
* @test create a bunch of objects with varying type and size, memorising
* how to kill them properly. Verify everyone is dead after mass-kill.
* Use a checksum not only to verify the number of objects created and
* destroyed, but also the individual (random) contents of the data
* within the objects, to ensure that the correct destructor
* actually is invoked for each type.
*
* @see lib::DelStash
*/
class DelStash_test : public Test
{
virtual void
run (Arg)
{
seedRand();
checksum = 0;
checkSingleKill();
checkCustomKill();
checkMassKill();
checkAutoKill();
}
void
checkSingleKill ()
{
DelStash killer;
CHECK (0 == killer.size());
killer.manage<short> (NULL);
CHECK (0 == killer.size());
Probe<5> *p = makeViktim<5>();
Probe<7> &r = *makeViktim<7>();
void *v = makeViktim<9>();
CHECK (0 < checksum);
killer.manage (p);
killer.manage (r);
killer.manage (static_cast<Probe<9>*> (v));
CHECK (3 == killer.size());
killer.kill (r);
CHECK (2 == killer.size());
killer.kill (p);
CHECK (1 == killer.size());
killer.kill (p);
CHECK (1 == killer.size()); // spurious kill requests ignored
killer.kill (v);
CHECK (0 == killer.size());
CHECK (0 == checksum);
}
void
feedViktims (DelStash& killer)
{
for (uint i=1; i <= MAX_MASS; ++i)
switch (i% 5) {
case 0: feedViktim<12> (killer); break;
case 1: feedViktim<23> (killer); break;
case 2: feedViktim<34> (killer); break;
case 3: feedViktim<45> (killer); break;
case 4: feedViktim<56> (killer); break;
}
}
void
checkMassKill ()
{
DelStash killer;
CHECK (0 == killer.size());
CHECK (0 == checksum);
CHECK (0 == killer.size());
feedViktims (killer);
CHECK (MAX_MASS == killer.size());
killer.killAll();
CHECK (0 == killer.size());
CHECK (0 == checksum);
}
void
checkAutoKill()
{
{
DelStash killer;
CHECK (0 == killer.size());
CHECK (0 == checksum);
feedViktims (killer);
Probe<444> * individuum = makeViktim<444>();
killer.manage (individuum);
feedViktims (killer);
killer.manage (makeViktim<5555>());
feedViktims (killer);
CHECK (3*MAX_MASS + 2 == killer.size());
killer.kill(individuum);
CHECK (3*MAX_MASS + 1 == killer.size());
CHECK (0 < checksum);
}// killer going out of scope...
CHECK (0 == checksum);
}
/** @test use a custom-provided
* deleter function
*/
void
checkCustomKill ()
{
DelStash killer;
CHECK (0 == killer.size());
/** a very specific setup,
* bound to mess up the checksum,
* unless the random bias is removed
* by the custom deleter function
*/
class Special
: Probe<555>
{
char secret_;
public:
Special()
: Probe<555>()
, secret_('a' + rani('z'-'a' +1))
{
checksum += secret_;
}
static void
selfKill (void *it)
{
Special *self = static_cast<Special*> (it);
checksum -= self->secret_;
delete self;
}
};
void * type_erased = new Special();
CHECK (0 < checksum);
killer.manage (type_erased, &Special::selfKill);
CHECK (1 == killer.size());
killer.kill(type_erased);
CHECK (0 == killer.size());
CHECK (0 == checksum);
}
};
/** Register this test class... */
LAUNCHER (DelStash_test, "unit common");
}} // namespace lib::test