LUMIERA.clone/tests/library/dependency-factory-test.cpp
Ichthyostega 974c670d41 fix **** in doxygen comments
to make them stand out more prominently, some entity comments
where started with a line of starts. Unfortunately, doxygen
(and javadoc) only recogise comments which are started exactly
with /**

This caused quite some comments to be ignored by doxygen.
Credits to Hendrik Boom for spotting this problem!

A workaround is to end the line of stars with *//**
2013-10-24 23:06:36 +02:00

262 lines
7.6 KiB
C++

/*
DependencyFactory(Test) - verify modes of creating singletons and dependencies
Copyright (C) Lumiera.org
2013, 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/depend.hpp"
#include "lib/test/depend-4test.hpp"
#include "test-target-obj.hpp"
#include <cstdlib>
namespace lib {
namespace test{
using ::Test;
using util::isSameObject;
namespace {
const uint MAX_ID = 1000;
struct Sub
: TestTargetObj
{
static uint created;
uint instanceID_;
Sub()
: TestTargetObj(created++)
,instanceID_(rand() % MAX_ID)
{ }
virtual operator string() const
{
return showType(*this)
+ TestTargetObj::operator string();
}
};
uint Sub::created = 0;
struct SubSub
: Sub
{
/** marker typedef for Depend4Test,
* allowing to pick the correct Depend<ServiceInterface>
* to apply the instrumentation with the test mock. */
typedef Sub ServiceInterface;
};
struct SubSubSub
: SubSub
{ };
}
/***************************************************************************//**
* @test verify the various modes of creating dependencies.
* - standard case is singleton creation
* - configuration of a specific subclass for the singleton
* - use of a custom factory function
* - injection of a mock implementation for unit tests
*
* @see lib::Dependency
* @see Singleton_test
*/
class DependencyFactory_test : public Test
{
virtual void
run (Arg)
{
verify_defaultSingletonCreation();
verify_SubclassCreation();
verify_FactoryDefinition_is_sticky();
verify_customFactory();
verify_temporaryReplacement();
verify_automaticReplacement();
}
void
verify_defaultSingletonCreation()
{
Depend<Sub> accessor1;
Depend<Sub> accessor2;
Sub & o1 = accessor1();
Sub & o2 = accessor2();
CHECK (isSameObject (o1, o2));
}
void
verify_SubclassCreation()
{
Depend<SubSub> specialAccessor(buildSingleton<SubSubSub>());
Depend<Sub> genericAccessor;
SubSub& oSub = specialAccessor();
Sub& o = genericAccessor();
CHECK (!isSameObject (oSub, o));
CHECK ( INSTANCEOF (SubSubSub, &oSub));
CHECK (!INSTANCEOF (SubSubSub, &o));
}
void
verify_FactoryDefinition_is_sticky()
{
Depend<SubSub> otherSpecialAccessor;
SubSub& oSub = otherSpecialAccessor();
CHECK ( INSTANCEOF (SubSubSub, &oSub));
Depend<SubSub> yetAnotherSpecialAccessor;
SubSub& yetAnotherInstance = yetAnotherSpecialAccessor();
CHECK ( INSTANCEOF (SubSubSub, &yetAnotherInstance));
}
void
verify_customFactory()
{
Depend<SubSubSub> customisedAccessor(&customFactoryFunction);
Depend<SubSub> otherSpecialAccessor;
SubSub& oSub = otherSpecialAccessor();
SubSubSub& oSubS = customisedAccessor();
CHECK (!isSameObject (oSub, oSubS));
CHECK ( INSTANCEOF (SubSubSub, &oSub));
CHECK ( INSTANCEOF (SubSubSub, &oSubS));
CHECK (oSub.instanceID_ != oSubS.instanceID_);
CHECK (MAX_ID + 10 == oSubS.instanceID_);
}
static void*
customFactoryFunction (void)
{
static SubSubSub specialInstance;
// NOTE: the factory function is responsible
// for managing the instance's lifecycle
specialInstance.instanceID_ = MAX_ID + 10;
return &specialInstance;
}
void
verify_temporaryReplacement()
{
typedef Depend<Sub> GenericAccessor;
GenericAccessor genericAccessor;
Sub& original = genericAccessor();
uint oID = original.instanceID_;
SubSubSub mockObject;
Sub* shaddowedOriginal = GenericAccessor::injectReplacement (&mockObject);
Sub& replacement = genericAccessor();
CHECK ( isSameObject (replacement, mockObject));
CHECK (!isSameObject (original, replacement));
CHECK ( isSameObject (original, *shaddowedOriginal));
Depend<SubSub> special;
Depend<SubSubSub> custom;
CHECK(!isSameObject (replacement, special() ));
CHECK(!isSameObject (replacement, custom() ));
GenericAccessor::injectReplacement (shaddowedOriginal);
Sub& nextFetch = genericAccessor();
CHECK (isSameObject (original, nextFetch));
CHECK (oID == nextFetch.instanceID_);
}
void
verify_automaticReplacement()
{
Depend<Sub> genericAccessor;
Sub& original = genericAccessor();
uint oID = original.instanceID_;
{
Depend4Test<SubSub> withinThisScope;
Sub& replacement = genericAccessor();
uint repID = replacement.instanceID_;
CHECK (!INSTANCEOF (SubSub, &original));
CHECK ( INSTANCEOF (SubSub, &replacement));
CHECK (!INSTANCEOF (SubSubSub, &replacement));
CHECK (!isSameObject (original, replacement));
Depend<Sub> anotherAccessor;
Sub& otherAccess = anotherAccessor();
CHECK (isSameObject (replacement, otherAccess));
CHECK (repID == otherAccess.instanceID_);
CHECK (repID == replacement.instanceID_);
CHECK ( oID == original.instanceID_);
// verify the instrumentation indeed targeted the generic accessor,
// and *not* an accessor of the sub type, i.e Depend<SubSub>
Depend<SubSub> genericSubTypeAccessor;
SubSub& subTypeAccess = genericSubTypeAccessor();
CHECK ( INSTANCEOF (SubSub, &subTypeAccess));
CHECK (!isSameObject (replacement, subTypeAccess));
CHECK (!isSameObject (original, subTypeAccess));
CHECK (repID != subTypeAccess.instanceID_);
CHECK ( oID != subTypeAccess.instanceID_);
}
Sub& nextFetch = genericAccessor();
CHECK (isSameObject (original, nextFetch));
CHECK (oID == nextFetch.instanceID_);
}
};
LAUNCHER (DependencyFactory_test, "unit common");
}} // namespace lib::test