You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2022/05/17 17:04:14 UTC
[celix] 01/05: Adds initial gtest for additional dm cmp states
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch pnoltes/feature/update_component_and_pattern_documentation
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 35b3ab71a5605e0125902cb83f0bb8ee963ab069
Author: Pepijn Noltes <pn...@apache.org>
AuthorDate: Tue May 17 11:42:24 2022 +0200
Adds initial gtest for additional dm cmp states
---
.../gtest/src/DependencyManagerTestSuite.cc | 116 +++++++++++++++++++++
libs/framework/src/dm_component_impl.c | 28 ++---
2 files changed, 132 insertions(+), 12 deletions(-)
diff --git a/libs/framework/gtest/src/DependencyManagerTestSuite.cc b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
index a07cbde9..a31b2db4 100644
--- a/libs/framework/gtest/src/DependencyManagerTestSuite.cc
+++ b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
@@ -486,6 +486,122 @@ TEST_F(DependencyManagerTestSuite, RequiredDepsAreInjectedDuringStartStop) {
celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
}
+TEST_F(DependencyManagerTestSuite, IntermediaStatesDuringInitDeinitStartingAndStopping) {
+ class LifecycleComponent {
+ public:
+ enum class InMethod {
+ NO_METHOD,
+ INIT,
+ DEINIT,
+ START,
+ STOP
+ };
+
+ void init() {
+ std::cout << "in init callback\n";
+ std::unique_lock<std::mutex> lck{mutex};
+ inMethod = InMethod::INIT;
+ cond.notify_all();
+ cond.wait_for(lck, std::chrono::seconds{1});
+ inMethod = InMethod::NO_METHOD;
+ }
+
+ void deinit() {
+ std::cout << "in deinit callback\n";
+ std::unique_lock<std::mutex> lck{mutex};
+ inMethod = InMethod::DEINIT;
+ cond.notify_all();
+ cond.wait_for(lck, std::chrono::seconds{1});
+ inMethod = InMethod::NO_METHOD;
+ }
+
+ void start() {
+ std::cout << "in start callback\n";
+ std::unique_lock<std::mutex> lck{mutex};
+ inMethod = InMethod::START;
+ cond.notify_all();
+ cond.wait_for(lck, std::chrono::seconds{1});
+ inMethod = InMethod::NO_METHOD;
+ }
+
+ void stop() {
+ std::cout << "in stop callback\n";
+ std::unique_lock<std::mutex> lck{mutex};
+ inMethod = InMethod::STOP;
+ cond.notify_all();
+ cond.wait_for(lck, std::chrono::seconds{1});
+ inMethod = InMethod::NO_METHOD;
+ }
+
+ void waitFor(InMethod s) {
+ std::unique_lock<std::mutex> lck{mutex};
+ cond.wait_for(lck, std::chrono::seconds{1}, [&]{return inMethod == s;});
+ }
+
+ void cont() {
+ std::lock_guard<std::mutex> lck{mutex};
+ cond.notify_all();
+ }
+
+ private:
+ std::mutex mutex{};
+ std::condition_variable cond{};
+ InMethod inMethod = InMethod::NO_METHOD;
+ };
+
+ celix::dm::DependencyManager dm{ctx};
+ auto lifecycleCmp = std::make_shared<LifecycleComponent>();
+ auto& cmp = dm.createComponent<LifecycleComponent>(lifecycleCmp)
+ .setCallbacks(&LifecycleComponent::init, &LifecycleComponent::start, &LifecycleComponent::stop, &LifecycleComponent::deinit);
+ cmp.createServiceDependency<TestService>()
+ .setRequired(false);
+ cmp.build();
+
+ using celix::dm::ComponentState;
+ lifecycleCmp->waitFor(LifecycleComponent::InMethod::INIT);
+ EXPECT_EQ(cmp.getState(), ComponentState::INITIALIZING);
+ lifecycleCmp->cont();
+
+ lifecycleCmp->waitFor(LifecycleComponent::InMethod::START);
+ EXPECT_EQ(cmp.getState(), ComponentState::STARTING);
+ lifecycleCmp->cont();
+
+ lifecycleCmp->waitFor(LifecycleComponent::InMethod::START);
+ EXPECT_EQ(cmp.getState(), ComponentState::STARTING);
+ lifecycleCmp->cont();
+
+ //Adding service should lead to a suspend/resume (stop/start)
+ TestService svc;
+ std::string svcName = celix::typeName<TestService>();
+ celix_service_registration_options opts{};
+ opts.svc = &svc;
+ opts.serviceName = svcName.c_str();
+ long svcId = celix_bundleContext_registerServiceWithOptions(dm.bundleContext(), &opts);
+ EXPECT_GE(svcId, 0);
+
+ lifecycleCmp->waitFor(LifecycleComponent::InMethod::STOP);
+ EXPECT_EQ(cmp.getState(), ComponentState::SUSPENDING);
+ lifecycleCmp->cont();
+
+ //svc will be injected
+
+ lifecycleCmp->waitFor(LifecycleComponent::InMethod::START);
+ EXPECT_EQ(cmp.getState(), ComponentState::RESUMING);
+ lifecycleCmp->cont();
+
+ //Adding a required svc should lead to INSTANTIATED_AND_WAITING_FOR_REQUIRED
+ cmp.createServiceDependency<TestService>()
+ .setFilter("(non-existing=*)")
+ .setRequired(true)
+ .build();
+
+ lifecycleCmp->waitFor(LifecycleComponent::InMethod::STOP);
+ EXPECT_EQ(cmp.getState(), ComponentState::STOPPING);
+ lifecycleCmp->cont();
+
+ celix_bundleContext_unregisterService(dm.bundleContext(), svcId);
+}
+
TEST_F(DependencyManagerTestSuite, DepsAreInjectedAsSharedPointers) {
class LifecycleComponent {
public:
diff --git a/libs/framework/src/dm_component_impl.c b/libs/framework/src/dm_component_impl.c
index c4544f75..ca213435 100644
--- a/libs/framework/src/dm_component_impl.c
+++ b/libs/framework/src/dm_component_impl.c
@@ -290,7 +290,11 @@ celix_dm_component_state_t component_currentState(celix_dm_component_t *cmp) {
}
celix_dm_component_state_t celix_dmComponent_currentState(celix_dm_component_t *cmp) {
- return cmp->state;
+ celix_dm_component_state_t state;
+ celixThreadMutex_lock(&cmp->mutex);
+ state = cmp->state;
+ celixThreadMutex_unlock(&cmp->mutex);
+ return state;
}
void* component_getImplementation(celix_dm_component_t *cmp) {
@@ -1088,26 +1092,26 @@ bool celix_dmComponent_isActive(celix_dm_component_t *component) {
const char* celix_dmComponent_stateToString(celix_dm_component_state_t state) {
switch(state) {
case CELIX_DM_CMP_STATE_WAITING_FOR_REQUIRED:
- return "CELIX_DM_CMP_STATE_WAITING_FOR_REQUIRED";
+ return "WAITING_FOR_REQUIRED";
case CELIX_DM_CMP_STATE_INITIALIZING:
- return "CELIX_DM_CMP_STATE_INITIALIZING";
+ return "INITIALIZING";
case CELIX_DM_CMP_STATE_DEINITIALIZING:
- return "CELIX_DM_CMP_STATE_DEINITIALIZING";
+ return "DEINITIALIZING";
case CELIX_DM_CMP_STATE_INITIALIZED_AND_WAITING_FOR_REQUIRED:
- return "CELIX_DM_CMP_STATE_INITIALIZED_AND_WAITING_FOR_REQUIRED";
+ return "INITIALIZED_AND_WAITING_FOR_REQUIRED";
case CELIX_DM_CMP_STATE_STARTING:
- return "CELIX_DM_CMP_STATE_STARTING";
+ return "STARTING";
case CELIX_DM_CMP_STATE_STOPPING:
- return "CELIX_DM_CMP_STATE_STOPPING";
+ return "STOPPING";
case CELIX_DM_CMP_STATE_TRACKING_OPTIONAL:
- return "CELIX_DM_CMP_STATE_TRACKING_OPTIONAL";
+ return "TRACKING_OPTIONAL";
case CELIX_DM_CMP_STATE_SUSPENDING:
- return "CELIX_DM_CMP_STATE_SUSPENDING";
+ return "SUSPENDING";
case CELIX_DM_CMP_STATE_SUSPENDED:
- return "CELIX_DM_CMP_STATE_SUSPENDED";
+ return "SUSPENDED";
case CELIX_DM_CMP_STATE_RESUMING:
- return "CELIX_DM_CMP_STATE_RESUMING";
+ return "RESUMING";
default: //only CELIX_DM_CMP_STATE_INACTIVE left
- return "CELIX_DM_CMP_STATE_INACTIVE";
+ return "INACTIVE";
}
}