3434#include " Mocks.hpp"
3535#include " TestFixture.hpp"
3636#include " TestInterfaces/Interfaces.hpp"
37- #include " boost/asio/async_result.hpp"
38- #include " boost/asio/packaged_task.hpp"
39- #include " boost/asio/post.hpp"
40- #include " boost/asio/thread_pool.hpp"
37+
4138#include " cppmicroservices/servicecomponent/ComponentConstants.hpp"
4239#include " cppmicroservices/servicecomponent/runtime/ServiceComponentRuntime.hpp"
4340
@@ -80,53 +77,6 @@ namespace test
8077 cppmicroservices::Framework framework;
8178 };
8279
83- class AsyncWorkServiceThreadPool : public cppmicroservices ::async::AsyncWorkService
84- {
85- public:
86- AsyncWorkServiceThreadPool (int nThreads) : cppmicroservices::async::AsyncWorkService()
87- {
88- threadpool = std::make_shared<boost::asio::thread_pool>(nThreads);
89- }
90-
91- ~AsyncWorkServiceThreadPool () override
92- {
93- try
94- {
95- if (threadpool)
96- {
97- try
98- {
99- threadpool->join ();
100- }
101- catch (...)
102- {
103- //
104- }
105- }
106- }
107- catch (...)
108- {
109- //
110- }
111- }
112-
113- void
114- post (std::packaged_task<void ()>&& task) override
115- {
116- using Sig = void ();
117- using Result = boost::asio::async_result<decltype (task), Sig>;
118- using Handler = typename Result::completion_handler_type;
119-
120- Handler handler (std::forward<decltype (task)>(task));
121- Result result (handler);
122-
123- boost::asio::post (threadpool->get_executor (), [handler = std::move (handler)]() mutable { handler (); });
124- }
125-
126- private:
127- std::shared_ptr<boost::asio::thread_pool> threadpool;
128- };
129-
13080 TEST_F (tGenericDSSuite, TestAsyncWorkServiceWithoutUserService)
13181 {
13282 std::shared_ptr<cppmicroservices::scrimpl::SCRLogger> logger
@@ -304,7 +254,7 @@ namespace test
304254
305255 auto reg = ctx.RegisterService <cppmicroservices::async::AsyncWorkService>(param);
306256
307- for (const auto & bundleName : bundlesToInstall)
257+ for (auto const & bundleName : bundlesToInstall)
308258 {
309259 installedBundles.emplace_back (::test::InstallAndStartBundle (ctx, bundleName));
310260 }
@@ -343,7 +293,7 @@ namespace test
343293 auto configInstance = configuration->GetPid ();
344294
345295 cppmicroservices::AnyMap props ({
346- {" uniqueProp" , std::string (" instance1" )}
296+ { " uniqueProp" , std::string (" instance1" ) }
347297 });
348298
349299 auto fut = configuration->Update (props);
@@ -391,7 +341,7 @@ namespace test
391341 auto configInstance = configuration->GetPid ();
392342
393343 cppmicroservices::AnyMap props ({
394- {" uniqueProp" , std::string (" instance1" )}
344+ { " uniqueProp" , std::string (" instance1" ) }
395345 });
396346
397347 auto fut = configuration->Update (props);
@@ -409,14 +359,14 @@ namespace test
409359 auto configInstance = configuration->GetPid ();
410360
411361 cppmicroservices::AnyMap props ({
412- {" uniqueProp" , std::string (" instance1" )}
362+ { " uniqueProp" , std::string (" instance1" ) }
413363 });
414364
415365 auto fut = configuration->SafeUpdate (props);
416366 fut->get ();
417367
418368 cppmicroservices::AnyMap props1 ({
419- {" uniqueProp" , std::string (" instance2" )}
369+ { " uniqueProp" , std::string (" instance2" ) }
420370 });
421371 auto fut1 = configuration->SafeUpdateIfDifferent (props1);
422372 fut1.second ->get ();
@@ -457,7 +407,7 @@ namespace test
457407 auto configInstance = configuration->GetPid ();
458408
459409 cppmicroservices::AnyMap props ({
460- {" uniqueProp" , std::string (" instance1" )}
410+ { " uniqueProp" , std::string (" instance1" ) }
461411 });
462412
463413 auto fut = configuration->SafeUpdate (props);
@@ -471,4 +421,51 @@ namespace test
471421 fut.get ();
472422 }
473423
424+ /* *
425+ * Verify that a service's configuration can be updated from with a 'Modified' callback without
426+ * deadlocking the framework trying to get the lock in configNotifier
427+ */
428+ TEST_F (TestAsyncWorkServiceEndToEnd, testUpdateConfigFromWithinModifiedCallback)
429+ {
430+ auto const & param = std::make_shared<AsyncWorkServiceThreadPool>(10 );
431+ auto context = framework.GetBundleContext ();
432+
433+ // ASYNCWORKSERVICE
434+ auto reg = context.RegisterService <cppmicroservices::async::AsyncWorkService>(param);
435+ US_UNUSED (reg);
436+
437+ // CA
438+ ::test::InstallAndStartConfigAdmin (context);
439+
440+ // CA Service
441+ auto CARef = context.GetServiceReference <cppmicroservices::service::cm::ConfigurationAdmin>();
442+ auto configAdminService = context.GetService <cppmicroservices::service::cm::ConfigurationAdmin>(CARef);
443+ ASSERT_TRUE (configAdminService) << " GetService failed for ConfigurationAdmin" ;
444+
445+ // Start bundle
446+ std::string componentName = " sample::ServiceComponentCA10" ;
447+
448+ auto testBundle = ::test::InstallAndStartBundle (context, " TestBundleDSCA10" );
449+ ::test::InstallAndStartBundle (context, " TestBundleDSCA03" );
450+
451+ auto configObject = configAdminService->GetConfiguration (componentName);
452+
453+ auto props = configObject->GetProperties ();
454+ auto configObject2 = configAdminService->GetConfiguration (" sample::ServiceComponentCA02" );
455+
456+ props[" uniqueProp" ] = std::string (" UNIQUE" );
457+ auto fut = configObject->Update (props);
458+ fut.get ();
459+ fut = configObject2->Update (props);
460+ fut.get ();
461+ props[" configID" ] = std::string (" sample::ServiceComponentCA03" );
462+ fut = configObject->Update (props);
463+ fut.get ();
464+
465+ // GetService to make component active
466+ auto serviceRef = context.GetServiceReference <test::CAInterface>();
467+ auto service = context.GetService <test::CAInterface>(serviceRef);
468+ ASSERT_TRUE (service) << " GetService failed for CAInterface" ;
469+ }
470+
474471}; // namespace test
0 commit comments