diff --git a/research/try.cpp b/research/try.cpp index fa426d9a0..0eddcf8da 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -182,6 +182,14 @@ class DependInject { using Factory = typename Depend::Factory; public: + template + static void + __assert_compatible() + { + static_assert (std::is_base_of::value, + "Installed implementation class must be compatible to the interface."); + } + static void installFactory (Factory&& otherFac) { @@ -193,6 +201,24 @@ class DependInject Depend::factory = move (otherFac); } + static void + temporarilyInstallAlternateFactory (SRV*& stashInstance, Factory& stashFac, Factory&& newFac) + { + ClassLock guard; + stashFac = move(Depend::factory); + stashInstance = Depend::instance; + Depend::factory = move(newFac); + Depend::instance = nullptr; + } + + static void + restoreOriginalFactory (SRV*& stashInstance, Factory& stashFac) + { + ClassLock guard; + Depend::factory = move(stashFac); + Depend::instance = stashInstance; + } + static void disableFactory() { @@ -225,6 +251,7 @@ class DependInject static void useSingleton() { + __assert_compatible(); static InstanceHolder singleton; installFactory ([&]() { @@ -243,6 +270,7 @@ class DependInject ServiceInstance() : instance_(new IMP{}) { + __assert_compatible(); activateServiceAccess (*instance_); } @@ -251,6 +279,10 @@ class DependInject deactivateServiceAccess(); } + ServiceInstance (ServiceInstance&&) = default; + ServiceInstance (ServiceInstance const&) = delete; + ServiceInstance& operator= (ServiceInstance&&) = delete; + explicit operator bool() const { @@ -272,13 +304,54 @@ class DependInject } }; - template + + template class Local { + std::unique_ptr mock_; + + SRV* origInstance_; + Factory origFactory_; + public: Local() { - + __assert_compatible(); + temporarilyInstallAlternateFactory (origInstance_, origFactory_ + ,[this]() + { + disableFactory(); + mock_.reset(new MOC{}); + return mock_.get(); + }); + } + ~Local() + { + restoreOriginalFactory (origInstance_, origFactory_); + } + + Local (Local&&) = default; + Local (Local const&) = delete; + Local& operator= (Local&&) = delete; + + explicit + operator bool() const + { + return bool(mock_); + } + + MOC& + operator* () const + { + ENSURE (mock_); + return *mock_; + } + + MOC* + operator-> () const + { + ENSURE (mock_); + return mock_.get(); } }; }; @@ -367,6 +440,69 @@ main (int, char**) VERIFY_ERROR (LIFECYCLE, DependInject::ServiceInstance{} ); SHOW_EXPR( checksum ); + { + DependInject::Local mockDum; + DependInject>::Local mockDummy3; + CHECK (!mockDum); + CHECK (!mockDummy3); + SHOW_EXPR( dumm().probe() ); + CHECK ( mockDum); + CHECK (!mockDummy3); + SHOW_EXPR( checksum ); + SHOW_EXPR( mockDum->probe() ); + SHOW_EXPR( checksum ); + mockDum->offset = 20; + SHOW_EXPR( dumm().probe() ); + + VERIFY_ERROR (LIFECYCLE, mockDummy3->probe() ); + SHOW_EXPR( checksum ); + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( checksum ); + CHECK ( mockDummy3); + SHOW_EXPR( mockDummy3->probe() ); + SHOW_EXPR( checksum ); + mockDummy3->offset = 10; + SHOW_EXPR( dep3().probe() ); + mockDum->offset = 50; + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( dumm().probe() ); + SHOW_EXPR( checksum ); + } + SHOW_EXPR( checksum ); + SHOW_EXPR( dumm().probe() ); + VERIFY_ERROR (LIFECYCLE, dep3().probe() ); + SHOW_EXPR( checksum ); + { + DependInject>::ServiceInstance service{}; + SHOW_EXPR( checksum ); + SHOW_EXPR( dep3().probe() ); + service->offset = 5; + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( checksum ); + { + DependInject>::Local mockDummy31; + CHECK (!mockDummy31); + SHOW_EXPR( checksum ); + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( checksum ); + mockDummy31->offset = 10; + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( mockDummy31->probe() ); + SHOW_EXPR( service->probe() ); + CHECK (mockDummy31->offset != service->offset); + service->offset = 35; + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( mockDummy31->probe() ); + SHOW_EXPR( service->probe() ); + SHOW_EXPR( checksum ); + } + SHOW_EXPR( checksum ); + SHOW_EXPR( dep3().probe() ); + SHOW_EXPR( checksum ); + } + SHOW_EXPR( checksum ); + VERIFY_ERROR (LIFECYCLE, dep3().probe() ); + SHOW_EXPR( checksum ); cout << "\n.gulp.\n"; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 01f511e97..bdef674c0 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -26839,21 +26839,38 @@ - - - - - - - + + + - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + +