diff --git a/src/lib/depend.hpp b/src/lib/depend.hpp index 2ed7e5eac..3d6fd5227 100644 --- a/src/lib/depend.hpp +++ b/src/lib/depend.hpp @@ -39,7 +39,7 @@ This code is heavily inspired by ** factory template for this purpose; the intention is to use on-demand initialisation ** and a standardised lifecycle. In the default configuration, this \c Depend factory ** maintains a singleton instance of type TY. The possibility to install other factory - ** functions allows for subclass creation and various other kinds of service management. + ** functions allows for subclass creation and various other kinds of service management. ** ** ** \par Why Singletons? Inversion-of-Control and Dependency Injection @@ -69,6 +69,7 @@ This code is heavily inspired by ** ** @see Depend ** @see DependencyFactory + ** @see lib::test::Depend4Test ** @see singleton-test.cpp ** @see dependency-factory-test.cpp */ @@ -81,12 +82,6 @@ This code is heavily inspired by #include "lib/sync-classlock.hpp" #include "lib/dependency-factory.hpp" -#include "lib/meta/duck-detector.hpp" ////TODO move in separate header - -#include ////TODO move in separate header -#include ////TODO move in separate header -#include ////TODO move in separate header - namespace lib { @@ -94,7 +89,7 @@ namespace lib { * Access point to singletons and other kinds of dependencies. * Actually this is a Factory object, which is typically placed into a * static field of the Singleton (target) class or some otherwise suitable interface. - * @note uses static fields internally, so all factory instances share pInstance_ + * @note uses static fields internally, so all factory configuration is shared per type * @remark there is an ongoing discussion regarding the viability of the * Double Checked Locking pattern, which requires either the context of a clearly defined * language memory model (as in Java), or needs to be supplemented by memory barriers. @@ -117,7 +112,7 @@ namespace lib { public: - /** Interface to be used by clients to access the service instance. + /** Interface to be used by clients for retrieving the service instance. * Manages the instance creation, lifecycle and access in multithreaded context. * @return instance of class SI. When used in default configuration, * this service instance is a singleton @@ -142,17 +137,17 @@ namespace lib { /** default configuration of the dependency factory - * is to build a singleton instance on demand */ + * is to build a singleton instance on demand */ Depend() { factory.ensureInitialisation (buildSingleton()); } /** - * optionally, the instance creation process can be explicitly configured + * optionally, the instance creation process can be configured explicitly * \em once per type. By default, a singleton instance will be created. * Installing another factory function enables other kinds of dependency injection; - * this configuration must be done prior to any use the dependency factory. + * this configuration must be done \em prior to any use the dependency factory. * @param ctor a constructor function, which will be invoked on first usage. * @note basically a custom constructor function is responsible to manage any * created service instances. Optionally it may install a deleter function @@ -181,7 +176,7 @@ namespace lib { * which, worse still, resides typically in the same memory * location as the new instance. The only way to prevent this * would be to synchronise any \em access (which is expensive) - * Thus it is the client's duty to ensure there is no such + * Thus it is the \em client's duty to ensure there is no such * concurrent access, i.e. all clients of the old instance * should be disabled prior to invoking this function. */ @@ -217,7 +212,8 @@ namespace lib { - // Storage for SingletonFactory's static fields... + + // Storage for static per type instance management... template SI* volatile Depend::instance; @@ -226,81 +222,5 @@ namespace lib { - - namespace { ///< details: inject a mock automatically in place of a singleton - - using boost::enable_if; - using lib::meta::Yes_t; - using lib::meta::No_t; - - /** - * Metafunction: does the Type in question - * give us a clue about what service interface to use? - */ - template - class defines_ServiceInterface - { - META_DETECT_NESTED (ServiceInterface); - - public: - enum{ value = HasNested_ServiceInterface::value - }; - }; - - - /** - * Policy-Trait: determine the access point to install the mock. - * @note either the mock service implementation needs to provide - * explicitly a typedef for the ServiceInterface, or we're - * just creating a separate new instance of the singleton service, - * while shadowing (but not destroying) the original instance. - */ - template - struct ServiceInterface - { - typedef I Type; - }; - - - template - struct ServiceInterface >::type> - { - typedef typename MOCK::ServiceInterface Type; - }; - - }//(End) mock injection details - - - /** - * Scoped object for installing/deinstalling a mocked service automatically. - * Placing a suitably specialised instance of this template into a local scope - * will inject the corresponding mock installation and remove it when the - * control flow leaves this scope. - * @param TYPE the concrete mock implementation type to inject. It needs to - * be default constructible. If TYPE is a subclass of the service interface, - * it needs to expose a typedef \c ServiceInterface - */ - template - struct Depend4Test - : boost::noncopyable - { - typedef typename ServiceInterface::Type Interface; - - boost::scoped_ptr mock_; - Interface* shadowedOriginal_; - - Depend4Test() - : mock_(new TYPE) - , shadowedOriginal_(Depend::injectReplacement (mock_.get())) - { } - - ~Depend4Test() - { - ENSURE (mock_); - Depend::injectReplacement (shadowedOriginal_); - } - }; - - } // namespace lib #endif diff --git a/src/lib/dependency-factory.cpp b/src/lib/dependency-factory.cpp index 6a3824078..763f28b28 100644 --- a/src/lib/dependency-factory.cpp +++ b/src/lib/dependency-factory.cpp @@ -23,6 +23,9 @@ /** @file dependency-factory.cpp ** This compilation unit holds the common backend of all singleton and dependency factories. + ** Especially the code for tracking and clean-up of all service instance is located here. + ** This clean-up is triggered by the invocation of \c ~AutoDestructor() -- at this point + ** a special \c shutdownLock is set, which prevents any further singleton service creation. ** */ @@ -32,9 +35,9 @@ namespace lib { - namespace error = lumiera::error; + namespace { // private implementation details... class AutoDestructor @@ -86,13 +89,19 @@ namespace lib { - /** */ + /** explicitly shut down and destroy a service instance. + * This can be used to re-start a service; by default, all + * services are created on-demand and stay alive until + * application shutdown. But a service deconfigured + * through this function is destroyed right away. + */ void DependencyFactory::deconfigure (void* existingInstance) { AutoDestructor::kill (existingInstance); } + /** hook to install a deleter function to clean up a service object. * The standard constructor function uses this hook to schedule the * destructor invocation on application shutdown; custom constructors diff --git a/src/lib/dependency-factory.hpp b/src/lib/dependency-factory.hpp index d97c9de9f..60df2b860 100644 --- a/src/lib/dependency-factory.hpp +++ b/src/lib/dependency-factory.hpp @@ -38,7 +38,15 @@ namespace lib { /** - * Factory to generate and manage service objects classified by type. + * @internal Factory to generate and manage service objects classified by type. + * An instance of this factory is placed once for each type for use by + * the \c lib::Depend front-end for dependency management. While the latter + * provides the singleton-style initialisation patter, the DependencyFacotry + * maintains a customisable factory function for instance creation. Moreover, + * the embedded helper template DependencyFactory::InstanceHolder actually + * creates and manages the singleton instances in default configuration; + * it is placed into a function-scope static variable; consequently + * the singleton instances are placed into static memory by default. */ class DependencyFactory { @@ -181,6 +189,16 @@ namespace lib { } + /** + * DSL-style marker function for client code + * to configure the usage of a specific subclass. + * Typically this function is used right within the + * Constructor call for lib::Depend; this allows to + * confine the actual service implementation class + * to a single compilation unit, without the need + * for clients of the respective service to know + * the actual concrete implementation class + */ template friend InstanceConstructor buildSingleton() diff --git a/src/lib/test/depend-4test.hpp b/src/lib/test/depend-4test.hpp index d2d1eb159..5178ab56d 100644 --- a/src/lib/test/depend-4test.hpp +++ b/src/lib/test/depend-4test.hpp @@ -1,6 +1,7 @@ /* DEPEND4TEST.hpp - inject test mock singletons and dependencies + Copyright (C) Lumiera.org 2013, Hermann Vosseler @@ -13,20 +14,11 @@ 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. -==================================================================== -This code is heavily inspired by - The Loki Library (loki-lib/trunk/include/loki/Singleton.h) - Copyright (c) 2001 by Andrei Alexandrescu - Loki code accompanies the book: - Alexandrescu, Andrei. "Modern C++ Design: Generic Programming - and Design Patterns Applied". - Copyright (c) 2001. Addison-Wesley. ISBN 0201704315 - */ @@ -35,154 +27,16 @@ This code is heavily inspired by #define LIB_TEST_DEPEND_4TEST_H -#include "lib/sync-classlock.hpp" #include "lib/depend.hpp" +#include "lib/meta/duck-detector.hpp" -#include "lib/meta/duck-detector.hpp" ////TODO move in separate header - -#include ////TODO move in separate header -#include ////TODO move in separate header -#include ////TODO move in separate header +#include +#include +#include namespace lib { - - /** - * Access point to singletons and other kinds of dependencies. - * Actually this is a Factory object, which is typically placed into a static field - * of the Singleton (target) class or some otherwise suitable interface. - * @note uses static fields internally, so all factory instances share pInstance_ - * @remark there is an ongoing discussion regarding the viability of the - * Double Checked Locking pattern, which requires either the context of a clearly defined - * language memory model (as in Java), or needs to be supplemented by memory barriers. - * In our case, this debate boils down to the question: does \c pthread_mutex_lock/unlock - * constitute a memory barrier, such as to force any memory writes happening \em within - * the singleton ctor to be flushed and visible to other threads when releasing the lock? - * To my understanding, the answer is yes. See - * [POSIX](http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap04.html#tag_04_10) - * @param SI the class of the Singleton instance - * @param Create policy defining how to create/destroy the instance - * @param Life policy defining how to manage Singleton Lifecycle - */ - template - class Depend - { - typedef ClassLock SyncLock; - - static SI* volatile instance; - static DependencyFactory factory; - - - public: - /** Interface to be used by clients to access the service instance. - * Manages the instance creation, lifecycle and access in multithreaded context. - * @return instance of class SI. When used in default configuration, - * this service instance is a singleton - */ - SI& - operator() () - { - if (!instance) - { - SyncLock guard; - - if (!instance) - instance = static_cast (factory.buildInstance()); - } - ENSURE (instance); - return *instance; - } - - - - typedef DependencyFactory::InstanceConstructor Constructor; - - - /** default configuration of the dependency factory - * is to build a singleton instance on demand */ - Depend() - { - factory.ensureInitialisation (buildSingleton()); - } - - /** - * optionally, the instance creation process can be explicitly configured - * \em once per type. By default, a singleton instance will be created. - * Installing another factory function enables other kinds of dependency injection; - * this configuration must be done prior to any use the dependency factory. - * @param ctor a constructor function, which will be invoked on first usage. - * @note basically a custom constructor function is responsible to manage any - * created service instances. Optionally it may install a deleter function - * via \c DependencyFactory::scheduleDestruction(void*,KillFun) - * @remark typically the \c Depend factory will be placed into a static variable, - * embedded into another type or interface. In this case, actual storage for - * this static variable needs to be allocated within some translation unit. - * And this is the point where this ctor will be invoked, in the static - * initialisation phase of the respective translation unit (*.cpp) - */ - Depend (Constructor ctor) - { - factory.installConstructorFunction (ctor); - } - - // standard copy operations applicable - - - - /* === Management / Test support interface === */ - - /** disable and destroy the actual service instance explicitly. - * Next access will re-invoke the factory to create a new instance. - * @warning this is a very dangerous operation. Concurrent accesses - * might get NULL or even a reference to the old instance, - * which, worse still, resides typically in the same memory - * location as the new instance. The only way to prevent this - * would be to synchronise any \em access (which is expensive) - * Thus it is the client's duty to ensure there is no such - * concurrent access, i.e. all clients of the old instance - * should be disabled prior to invoking this function. - */ - static void - shutdown() - { - SyncLock guard; - - factory.deconfigure (instance); - instance = NULL; - } - - /** temporarily replace the service instance. - * The purpose of this operation is to support unit testing. - * @param mock reference to an existing service instance (mock). - * @return reference to the currently active service instance. - * @warning not threadsafe. Same considerations as for \c shutdown() apply - * @remark the replacement is not actively managed by the DependencyFactory, - * it remains in ownership of the calling client (unit test). Typically - * this test will keep the returned original service reference and - * care for restoring the original state when done. - * @see Depend4Test scoped object for automated test mock injection - */ - static SI* - injectReplacement (SI* mock) - { - SyncLock guard; - SI* currentInstance = instance; - instance = mock; - return currentInstance; - } - }; - - - - // Storage for SingletonFactory's static fields... - template - SI* volatile Depend::instance; - - template - DependencyFactory Depend::factory; - - - +namespace test{ namespace { ///< details: inject a mock automatically in place of a singleton @@ -228,6 +82,9 @@ namespace lib { }//(End) mock injection details + + + /** * Scoped object for installing/deinstalling a mocked service automatically. * Placing a suitably specialised instance of this template into a local scope @@ -259,5 +116,5 @@ namespace lib { }; -} // namespace lib +}} // namespace lib::test #endif diff --git a/tests/core/backend/media-access-mock-test.cpp b/tests/core/backend/media-access-mock-test.cpp index d79525396..674bbe494 100644 --- a/tests/core/backend/media-access-mock-test.cpp +++ b/tests/core/backend/media-access-mock-test.cpp @@ -23,6 +23,7 @@ #include "backend/media-access-facade.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" #include "lib/test/run.hpp" #include "lib/time/diagnostics.hpp" @@ -30,7 +31,7 @@ #include -using lib::test::Use4Test; +using lib::test::Depend4Test; using lib::Literal; using std::string; using std::cout; @@ -53,7 +54,7 @@ namespace test { virtual void run(Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; queryScenario ("test-1"); queryScenario ("test-2"); diff --git a/tests/core/backend/media-access-mock.hpp b/tests/core/backend/media-access-mock.hpp index 3c2fdb354..c44e61b3c 100644 --- a/tests/core/backend/media-access-mock.hpp +++ b/tests/core/backend/media-access-mock.hpp @@ -26,7 +26,6 @@ #include "backend/media-access-facade.hpp" -#include "lib/test/mock-injector.hpp" diff --git a/tests/core/proc/asset/create-asset-test.cpp b/tests/core/proc/asset/create-asset-test.cpp index 07b68d428..b4967313c 100644 --- a/tests/core/proc/asset/create-asset-test.cpp +++ b/tests/core/proc/asset/create-asset-test.cpp @@ -31,8 +31,9 @@ #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" -using lib::test::Use4Test; +using lib::test::Depend4Test; using util::isnil; using std::string; @@ -52,7 +53,7 @@ namespace test { { virtual void run(Arg arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; createMedia(); factoryVariants(); diff --git a/tests/core/proc/asset/dependent-assets-test.cpp b/tests/core/proc/asset/dependent-assets-test.cpp index d50ab6d98..8cde4bf97 100644 --- a/tests/core/proc/asset/dependent-assets-test.cpp +++ b/tests/core/proc/asset/dependent-assets-test.cpp @@ -25,11 +25,12 @@ #include "proc/asset/testasset.hpp" #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" #include "lib/util.hpp" -using lib::test::Use4Test; +using lib::test::Depend4Test; using util::contains; using util::isnil; @@ -194,7 +195,7 @@ namespace test { */ void checkRealAssetDependencyRegistration () { - Use4Test within_this_scope; + Depend4Test within_this_scope; // -----Media and Clip-------------------------------- typedef P PM; diff --git a/tests/core/proc/asset/identityofassetstest.cpp b/tests/core/proc/asset/identityofassetstest.cpp index 27e70c69c..1d583a9e1 100644 --- a/tests/core/proc/asset/identityofassetstest.cpp +++ b/tests/core/proc/asset/identityofassetstest.cpp @@ -31,8 +31,9 @@ #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" -using lib::test::Use4Test; +using lib::test::Depend4Test; using util::isnil; using std::string; @@ -71,7 +72,7 @@ namespace test { */ void createDuplicate() { - Use4Test within_this_scope; + Depend4Test within_this_scope; PM mm1 = asset::Media::create ("test-1.mov", VIDEO); diff --git a/tests/core/proc/asset/makecliptest.cpp b/tests/core/proc/asset/makecliptest.cpp index 609df4c9e..8dddd3d13 100644 --- a/tests/core/proc/asset/makecliptest.cpp +++ b/tests/core/proc/asset/makecliptest.cpp @@ -31,8 +31,9 @@ #include "proc/mobject/session/clip.hpp" #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" -using lib::test::Use4Test; +using lib::test::Depend4Test; using util::contains; using util::isnil; using std::string; @@ -43,7 +44,6 @@ namespace proc { namespace asset{ namespace test { -//using mobject::NOBUG_FLAG(mobject_mem); @@ -59,7 +59,7 @@ namespace test { virtual void run (Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; PM mm = asset::Media::create("test-1", VIDEO); diff --git a/tests/core/proc/asset/orderingofassetstest.cpp b/tests/core/proc/asset/orderingofassetstest.cpp index 62cdede05..702e40b56 100644 --- a/tests/core/proc/asset/orderingofassetstest.cpp +++ b/tests/core/proc/asset/orderingofassetstest.cpp @@ -30,8 +30,9 @@ #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" -using lib::test::Use4Test; +using lib::test::Depend4Test; using util::isnil; using std::string; @@ -60,7 +61,7 @@ namespace test { { virtual void run(Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; Asset::Ident key1("test-1", Category(AUDIO), "ichthyo", 5); diff --git a/tests/core/proc/mobject/builder/buildertooltest.cpp b/tests/core/proc/mobject/builder/buildertooltest.cpp index 988b76bc4..97d6a0e30 100644 --- a/tests/core/proc/mobject/builder/buildertooltest.cpp +++ b/tests/core/proc/mobject/builder/buildertooltest.cpp @@ -30,6 +30,7 @@ #include "proc/mobject/session/clip.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" #include "lib/util.hpp" #include @@ -47,7 +48,7 @@ namespace test { using session::Clip; using session::AbstractMO; - using lib::test::Use4Test; + using lib::test::Depend4Test; using namespace mobject::test; @@ -112,7 +113,7 @@ namespace test { virtual void run(Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; TestTool t1; diff --git a/tests/core/proc/mobject/mobject-interface-test.cpp b/tests/core/proc/mobject/mobject-interface-test.cpp index 3f0d5a8fe..85db4d6ca 100644 --- a/tests/core/proc/mobject/mobject-interface-test.cpp +++ b/tests/core/proc/mobject/mobject-interface-test.cpp @@ -36,7 +36,7 @@ //#include "proc/mobject/explicitplacement.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "backend/media-access-mock.hpp" -//#include "lib/test/test-helper.hpp" +#include "lib/test/depend-4test.hpp" #include "lib/time/timevalue.hpp" #include @@ -54,7 +54,7 @@ namespace test { using std::endl; using lib::Symbol; - using lib::test::Use4Test; + using lib::test::Depend4Test; using lib::time::Duration; using lib::time::FSecs; using lib::time::Time; @@ -84,7 +84,7 @@ namespace test { virtual void run (Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; PMO testClip1 = asset::Media::create("test-1", asset::VIDEO)->createClip(); diff --git a/tests/core/proc/mobject/mobject-ref-test.cpp b/tests/core/proc/mobject/mobject-ref-test.cpp index 1b9ae39e8..4c01859f8 100644 --- a/tests/core/proc/mobject/mobject-ref-test.cpp +++ b/tests/core/proc/mobject/mobject-ref-test.cpp @@ -33,13 +33,14 @@ #include "proc/mobject/explicitplacement.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" #include "lib/test/test-helper.hpp" #include "lib/time/timevalue.hpp" #include "lib/util.hpp" #include -using lib::test::Use4Test; +using lib::test::Depend4Test; using lib::test::showSizeof; using lib::time::Duration; using lib::time::FSecs; @@ -104,7 +105,7 @@ namespace test { virtual void run (Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; // create data simulating a "Session" diff --git a/tests/core/proc/mobject/placement-hierarchy-test.cpp b/tests/core/proc/mobject/placement-hierarchy-test.cpp index 6dbcd39a4..4e38405a5 100644 --- a/tests/core/proc/mobject/placement-hierarchy-test.cpp +++ b/tests/core/proc/mobject/placement-hierarchy-test.cpp @@ -23,6 +23,7 @@ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" +#include "lib/test/depend-4test.hpp" #include "backend/media-access-mock.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "proc/mobject/session/clip.hpp" @@ -35,7 +36,7 @@ #include using lib::HashIndexed; -using lib::test::Use4Test; +using lib::test::Depend4Test; using std::tr1::shared_ptr; using std::string; @@ -68,7 +69,7 @@ namespace test { virtual void run (Arg) { - Use4Test within_this_scope; + Depend4Test within_this_scope; typedef Placement PMObj; diff --git a/tests/core/proc/mobject/session/testclip.cpp b/tests/core/proc/mobject/session/testclip.cpp index 216d869f2..79c276aa5 100644 --- a/tests/core/proc/mobject/session/testclip.cpp +++ b/tests/core/proc/mobject/session/testclip.cpp @@ -24,6 +24,7 @@ #include "proc/mobject/session/testclip.hpp" #include "backend/media-access-facade.hpp" #include "backend/media-access-mock.hpp" +#include "lib/test/depend-4test.hpp" #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" #include "lib/depend.hpp" @@ -47,13 +48,12 @@ namespace test { createTestMedia () { // install Mock-Interface to Lumiera backend - MAF::instance.injectSubclass (new MediaAccessMock); - PM media = asset::Media::create("test-2", VIDEO); // query magic filename - MAF::instance.injectSubclass (0); // remove Mock-Interface + lib::test::Depend4Test withinThisScope; - return *media; + return *asset::Media::create("test-2", VIDEO); // query magic filename } + asset::Clip & createTestClipAsset (asset::Media& media) { diff --git a/tests/library/dependency-factory-test.cpp b/tests/library/dependency-factory-test.cpp index c7e140a6e..0c7e0d2ec 100644 --- a/tests/library/dependency-factory-test.cpp +++ b/tests/library/dependency-factory-test.cpp @@ -27,6 +27,7 @@ #include "lib/util.hpp" #include "lib/depend.hpp" +#include "lib/test/depend-4test.hpp" #include "test-target-obj.hpp" #include @@ -54,7 +55,7 @@ namespace test{ ,instanceID_(rand() % MAX_ID) { } - operator string() const + virtual operator string() const { return showType(*this) + TestTargetObj::operator string(); @@ -66,6 +67,9 @@ namespace test{ struct SubSub : Sub { + /** marker typedef for Depend4Test, + * allowing to pick the correct Depend + * to apply the instrumentation with the test mock. */ typedef Sub ServiceInterface; }; @@ -80,7 +84,11 @@ namespace test{ /******************************************************************************* * @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 */