${PROJECT_SOURCE_DIR}/tests/common/tests_common.cpp
${PROJECT_SOURCE_DIR}/tests/common/access_provider.cpp
${PROJECT_SOURCE_DIR}/tests/common/smack_access.cpp
- ${PROJECT_SOURCE_DIR}/tests/common/dbus_access.cpp
${PROJECT_SOURCE_DIR}/tests/common/dbus_connection.cpp
${PROJECT_SOURCE_DIR}/tests/common/dbus_message_in.cpp
${PROJECT_SOURCE_DIR}/tests/common/dbus_message_out.cpp
+ ${PROJECT_SOURCE_DIR}/tests/common/service_manager.cpp
${PROJECT_SOURCE_DIR}/tests/common/memory.cpp
${PROJECT_SOURCE_DIR}/tests/common/db_sqlite.cpp
${PROJECT_SOURCE_DIR}/tests/common/fs_label_manager.cpp
+++ /dev/null
-/*
- * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file dbus_access.cpp
- * @author Zbigniew Jasinski <z.jasinski@samsung.com>
- * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
- * @version 1.1
- * @brief Implementation of SystemD control class over dbus API
- */
-
-#include <dpl/log/log.h>
-#include <tests_common.h>
-
-#include <cstring>
-#include <sstream>
-#include <unistd.h>
-
-#include "dbus_access.h"
-
-DBusAccess::DBusAccess(const char *service_name)
- : m_conn(nullptr)
- , m_msg(nullptr)
- , m_pending(nullptr)
- , m_dbus_client_name("tests.dbus.client")
- , m_service_name(service_name)
- , m_dbus_systemd_destination("org.freedesktop.systemd1")
- , m_dbus_systemd_path("/org/freedesktop/systemd1")
- , m_dbus_systemd_manager_interface("org.freedesktop.systemd1.Manager")
- , m_dbus_systemd_properties_interface("org.freedesktop.DBus.Properties")
- , m_dbus_systemd_service_interface("org.freedesktop.systemd1.Service")
- , m_reloadingToken("Reloading")
-{
- dbus_error_init(&m_err);
- connectToDBus();
-}
-
-void DBusAccess::connect() {
- m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_err);
- RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
- "Error in dbus_bus_get: " << m_err.message);
- dbus_connection_set_exit_on_disconnect(m_conn, FALSE);
-}
-
-void DBusAccess::addBusMatch(const char *member) {
- std::ostringstream rule;
- rule << "type='signal',"
- << "sender='" << m_dbus_systemd_destination << "',"
- << "interface='" << m_dbus_systemd_manager_interface << "',"
- << "member='" << member << "',"
- << "path='" << m_dbus_systemd_path << "'";
-
- dbus_bus_add_match(m_conn, rule.str().c_str(), &m_err);
- RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
- "Error in dbus_bus_add_match: " << m_err.message);
-}
-
-void DBusAccess::subscribeSignals() {
- newMethodCall("Subscribe");
- sendMsgWithReply();
- getMsgReply();
- finalizeMsgReply();
-}
-
-void DBusAccess::reloadDbusManager() {
- newMethodCall("Reload");
- sendMsgWithReply();
- getMsgReply();
- finalizeMsgReply();
- m_runningJobs.insert(m_reloadingToken);
-}
-
-void DBusAccess::requestName() {
- dbus_bus_request_name(m_conn, m_dbus_client_name.c_str(),
- DBUS_NAME_FLAG_REPLACE_EXISTING , &m_err);
- RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
- "Error in dbus_bus_request_name: " << m_err.message);
-}
-
-void DBusAccess::getUnitPath() {
- newMethodCall("GetUnit");
- appendToMsg(m_service_name.c_str());
- sendMsgWithReply();
- getMsgReply();
- m_unitPath = handleObjectPathMsgReply();
-}
-
-void DBusAccess::newMethodCall(const char *method) {
- m_msg = dbus_message_new_method_call(m_dbus_systemd_destination.c_str(),
- m_dbus_systemd_path.c_str(),
- m_dbus_systemd_manager_interface.c_str(),
- method);
- RUNNER_ASSERT_MSG(nullptr != m_msg,
- "Error in dbus_message_new_method_call");
-}
-
-void DBusAccess::appendToMsg(const char *argument) {
- DBusMessageIter iter;
-
- dbus_message_iter_init_append(m_msg, &iter);
- int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
- &argument);
- RUNNER_ASSERT_MSG(ret != 0,
- "Error in dbus_message_iter_append_basic");
-}
-
-void DBusAccess::appendToMsg(const char *const *argument) {
- DBusMessageIter iter;
- DBusMessageIter subIter;
- int ret;
-
- dbus_message_iter_init_append(m_msg, &iter);
- ret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING,
- &subIter);
- RUNNER_ASSERT_MSG(ret != 0,
- "Error in dbus_message_iter_open_container");
- for (auto str = argument; *str; str++) {
- int ret = dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, str);
- RUNNER_ASSERT_MSG(ret != 0,
- "Error in dbus_message_iter_append_basic");
- }
- ret = dbus_message_iter_close_container(&iter, &subIter);
- RUNNER_ASSERT_MSG(ret != 0,
- "Error in dbus_message_iter_close_container");
-}
-
-void DBusAccess::appendToMsg(bool argument) {
- DBusMessageIter iter;
-
- dbus_message_iter_init_append(m_msg, &iter);
- int b = argument ? 1 : 0;
- int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN,
- &b);
- RUNNER_ASSERT_MSG(ret != 0,
- "Error in dbus_message_iter_append_basic");
-}
-
-void DBusAccess::sendMsgWithReply() {
- int ret = dbus_connection_send_with_reply(m_conn, m_msg, &m_pending, -1);
- RUNNER_ASSERT_MSG(ret == 1,
- "Error in dbus_connection_send_with_reply");
-
- RUNNER_ASSERT_MSG(nullptr != m_pending, "Pending call null");
-
- dbus_connection_flush(m_conn);
- dbus_pending_call_block(m_pending);
-
- dbus_message_unref(m_msg);
- m_msg = nullptr;
-}
-
-void DBusAccess::getMsgReply() {
- m_msg = dbus_pending_call_steal_reply(m_pending);
- RUNNER_ASSERT_MSG(nullptr != m_msg,
- "Error in dbus_pending_call_steal_reply");
-}
-
-std::string DBusAccess::handleObjectPathMsgReply() {
- DBusMessageIter iter;
-
- RUNNER_ASSERT_MSG(dbus_message_iter_init(m_msg, &iter) != 0,
- "Message has no arguments");
- if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("Object path type expected");
- }
- char *tmp;
- dbus_message_iter_get_basic(&iter, &tmp);
- std::string ret(tmp);
-
- finalizeMsgReply();
- return ret;
-}
-
-uint32_t DBusAccess::handleVariantUIntMsgReply() {
- DBusMessageIter iter, iter2;
-
- RUNNER_ASSERT_MSG(dbus_message_iter_init(m_msg, &iter) != 0,
- "Message has no arguments");
- if (DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("Variant type expected");
- }
-
- dbus_message_iter_recurse(&iter, &iter2);
- if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&iter2)) {
- RUNNER_FAIL_MSG("uint32 type expected");
- }
-
- uint32_t ret;
- dbus_message_iter_get_basic(&iter2, &ret);
-
- finalizeMsgReply();
- return ret;
-}
-
-void DBusAccess::finalizeMsgReply() {
- dbus_message_unref(m_msg);
- dbus_pending_call_unref(m_pending);
- m_msg = nullptr;
- m_pending = nullptr;
-}
-
-void DBusAccess::connectToDBus() {
- connect();
- addBusMatch("JobRemoved");
- addBusMatch("JobNew");
- addBusMatch("Reloading");
- dbus_connection_flush(m_conn);
- dbus_connection_add_filter(m_conn,
- messageHandler,
- reinterpret_cast<void*>(this),
- [](void*)->void {});
- subscribeSignals();
- requestName();
- getUnitPath();
-}
-
-void DBusAccess::sendToService(const char *method) {
- newMethodCall(method);
- appendToMsg(m_service_name.c_str());
- appendToMsg("fail");
- sendMsgWithReply();
- getMsgReply();
- m_runningJobs.insert(handleObjectPathMsgReply());
-}
-
-void DBusAccess::sendMaskToService() {
- const char *mask[] = {m_service_name.c_str(), nullptr};
- newMethodCall("MaskUnitFiles");
- appendToMsg(mask);
- appendToMsg(true);
- appendToMsg(true);
- sendMsgWithReply();
- getMsgReply();
- finalizeMsgReply();
-}
-
-void DBusAccess::sendUnmaskToService() {
- const char *mask[] = {m_service_name.c_str(), nullptr};
- newMethodCall("UnmaskUnitFiles");
- appendToMsg(mask);
- appendToMsg(true);
- sendMsgWithReply();
- getMsgReply();
- finalizeMsgReply();
-}
-
-uint32_t DBusAccess::getUIntProperty(const char *interface, const char *property)
-{
- m_msg = dbus_message_new_method_call(m_dbus_systemd_destination.c_str(),
- m_unitPath.c_str(),
- m_dbus_systemd_properties_interface.c_str(),
- "Get");
-
- appendToMsg(interface);
- appendToMsg(property);
- sendMsgWithReply();
- getMsgReply();
- return handleVariantUIntMsgReply();
-}
-
-void DBusAccess::sendResetFailedToService() {
- newMethodCall("ResetFailedUnit");
- appendToMsg(m_service_name.c_str());
- sendMsgWithReply();
- getMsgReply();
- finalizeMsgReply();
-}
-
-DBusHandlerResult DBusAccess::messageHandler(DBusConnection *conn, DBusMessage *msg, void *t) {
- (void) conn;
- DBusAccess* self = reinterpret_cast<DBusAccess*>(t);
-
- if (self->isSignal(msg, "JobRemoved"))
- self->signalJobRemovedHandler(msg);
- else if (self->isSignal(msg, "JobNew"))
- self->signalJobNewHandler(msg);
- else if (self->isSignal(msg, "Reloading"))
- self->signalReloadingHandler(msg);
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-bool DBusAccess::isSignal(DBusMessage *msg, const char *signal) {
- return dbus_message_is_signal(msg, m_dbus_systemd_manager_interface.c_str(), signal);
-}
-
-void DBusAccess::signalJobRemovedHandler(DBusMessage *msg) {
- DBusMessageIter iter;
- RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
- "Message has no arguments");
-
- if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("uint32 type expected");
- }
- uint32_t id;
- dbus_message_iter_get_basic(&iter, &id);
-
- dbus_message_iter_next (&iter);
- if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("Object path type expected");
- }
- char *path;
- dbus_message_iter_get_basic(&iter, &path);
-
- dbus_message_iter_next (&iter);
- if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("String type expected");
- }
- char *unit;
- dbus_message_iter_get_basic(&iter, &unit);
-
- dbus_message_iter_next (&iter);
- if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("String type expected");
- }
- char *result;
- dbus_message_iter_get_basic(&iter, &result);
-
- if(m_service_name == unit) {
- RUNNER_ASSERT_MSG(strcmp(result, "done") == 0 || strcmp(result, "canceled") == 0,
- "RemoveJob signal delivered bad news. Job wasn't completed successfully: "
- << "expected job results = {done, canceled}, "
- << "received job result = " << result << ", "
- << "for job with id = " << id << ", "
- << "and path = " << path);
- m_runningJobs.erase(path);
- }
-}
-
-void DBusAccess::signalJobNewHandler(DBusMessage *msg) {
- DBusMessageIter iter;
- RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
- "Message has no arguments");
-
- if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("uint32 type expected");
- }
- uint32_t id;
- dbus_message_iter_get_basic(&iter, &id);
-
- dbus_message_iter_next (&iter);
- if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("Object path type expected");
- }
- char *path;
- dbus_message_iter_get_basic(&iter, &path);
-
- dbus_message_iter_next (&iter);
- if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("String type expected");
- }
- char *unit;
- dbus_message_iter_get_basic(&iter, &unit);
-
- if(m_service_name == unit)
- m_runningJobs.insert(path);
-}
-
-void DBusAccess::signalReloadingHandler(DBusMessage *msg) {
- DBusMessageIter iter;
- RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
- "Message has no arguments");
-
- if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&iter)) {
- RUNNER_FAIL_MSG("boolean type expected");
- }
- bool active;
- dbus_message_iter_get_basic(&iter, &active);
-
- if (active)
- m_runningJobs.insert(m_reloadingToken);
- else
- m_runningJobs.erase(m_reloadingToken);
-}
-
-void DBusAccess::waitForRunningJobsFinish() {
- while (!m_runningJobs.empty())
- dbus_connection_read_write_dispatch(m_conn, -1);
-}
-
-void DBusAccess::startService() {
- sendToService("StartUnit");
- waitForRunningJobsFinish();
- sendResetFailedToService();
-}
-
-void DBusAccess::stopService() {
- sendToService("StopUnit");
- waitForRunningJobsFinish();
- sendResetFailedToService();
-}
-
-void DBusAccess::restartService() {
- sendToService("RestartUnit");
- waitForRunningJobsFinish();
- sendResetFailedToService();
-}
-
-pid_t DBusAccess::getServicePid() {
- return static_cast<pid_t>(getUIntProperty(m_dbus_systemd_service_interface.c_str(), "MainPID"));
-}
-
-void DBusAccess::maskService() {
- sendMaskToService();
- reloadDbusManager();
- waitForRunningJobsFinish();
- sendResetFailedToService();
-}
-
-void DBusAccess::unmaskService() {
- sendUnmaskToService();
- reloadDbusManager();
- waitForRunningJobsFinish();
- sendResetFailedToService();
-}
-
-DBusAccess::~DBusAccess() {
- dbus_connection_close(m_conn);
- if (m_conn)
- dbus_connection_unref(m_conn);
- dbus_error_free(&m_err);
- if (m_msg)
- dbus_message_unref(m_msg);
- if (m_pending)
- dbus_pending_call_unref(m_pending);
-}
+++ /dev/null
-/*
- * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file dbus_access.h
- * @author Zbigniew Jasinski <z.jasinski@samsung.com>
- * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
- * @version 1.1
- * @brief System service control class using dbus interface to communicate with systemd
- */
-
-#ifndef _DBUS_ACCESS_H_
-#define _DBUS_ACCESS_H_
-
-#include <dbus/dbus.h>
-
-#include <set>
-#include <string>
-
-class DBusAccess {
-public:
- DBusAccess() = delete;
- DBusAccess(const char *service_name);
-
- void startService();
- void stopService();
- void restartService();
- pid_t getServicePid();
- void maskService();
- void unmaskService();
-
- virtual ~DBusAccess();
-private:
- void connect();
- void addBusMatch(const char *member);
- void subscribeSignals();
- void reloadDbusManager();
- void requestName();
- void getUnitPath();
- void newMethodCall(const char *method);
- void appendToMsg(const char *argument);
- void appendToMsg(const char *const *argument);
- void appendToMsg(bool argument);
- void sendMsgWithReply();
- void getMsgReply();
- std::string handleObjectPathMsgReply();
- uint32_t handleVariantUIntMsgReply();
- void finalizeMsgReply();
-
- void connectToDBus();
- void sendToService(const char *method);
- void sendMaskToService();
- void sendUnmaskToService();
- uint32_t getUIntProperty(const char *interface, const char *property);
- void sendResetFailedToService();
-
- static DBusHandlerResult messageHandler(DBusConnection *conn, DBusMessage *msg, void *t);
- bool isSignal(DBusMessage *msg, const char *signal);
- void signalJobRemovedHandler(DBusMessage *msg);
- void signalJobNewHandler(DBusMessage *msg);
- void signalReloadingHandler(DBusMessage *msg);
- void waitForRunningJobsFinish();
-
- DBusConnection *m_conn;
- DBusMessage *m_msg;
- DBusError m_err;
- DBusPendingCall *m_pending;
-
- const std::string m_dbus_client_name;
- const std::string m_service_name;
- std::string m_unitPath;
-
- const std::string m_dbus_systemd_destination;
- const std::string m_dbus_systemd_path;
- const std::string m_dbus_systemd_manager_interface;
- const std::string m_dbus_systemd_properties_interface;
- const std::string m_dbus_systemd_service_interface;
-
- std::set<std::string> m_runningJobs;
- const std::string m_reloadingToken;
-};
-
-#endif // _DBUS_ACCESS_H_
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file service_manager.cpp
+ * @author Zbigniew Jasinski <z.jasinski@samsung.com>
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.1
+ * @brief Implementation of systemd control class over dbus API
+ */
+
+#include <dpl/log/log.h>
+#include <tests_common.h>
+
+#include <cstring>
+#include <sstream>
+#include <unistd.h>
+
+#include <service_manager.h>
+
+ServiceManager::ServiceManager(const char *service_name)
+ : m_conn(nullptr)
+ , m_msg(nullptr)
+ , m_pending(nullptr)
+ , m_dbus_client_name("tests.dbus.client")
+ , m_service_name(service_name)
+ , m_dbus_systemd_destination("org.freedesktop.systemd1")
+ , m_dbus_systemd_path("/org/freedesktop/systemd1")
+ , m_dbus_systemd_manager_interface("org.freedesktop.systemd1.Manager")
+ , m_dbus_systemd_properties_interface("org.freedesktop.DBus.Properties")
+ , m_dbus_systemd_service_interface("org.freedesktop.systemd1.Service")
+ , m_reloadingToken("Reloading")
+{
+ dbus_error_init(&m_err);
+ connectToDBus();
+}
+
+void ServiceManager::connect() {
+ m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_err);
+ RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
+ "Error in dbus_bus_get: " << m_err.message);
+ dbus_connection_set_exit_on_disconnect(m_conn, FALSE);
+}
+
+void ServiceManager::addBusMatch(const char *member) {
+ std::ostringstream rule;
+ rule << "type='signal',"
+ << "sender='" << m_dbus_systemd_destination << "',"
+ << "interface='" << m_dbus_systemd_manager_interface << "',"
+ << "member='" << member << "',"
+ << "path='" << m_dbus_systemd_path << "'";
+
+ dbus_bus_add_match(m_conn, rule.str().c_str(), &m_err);
+ RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
+ "Error in dbus_bus_add_match: " << m_err.message);
+}
+
+void ServiceManager::subscribeSignals() {
+ newMethodCall("Subscribe");
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+}
+
+void ServiceManager::reloadDbusManager() {
+ newMethodCall("Reload");
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+ m_runningJobs.insert(m_reloadingToken);
+}
+
+void ServiceManager::requestName() {
+ dbus_bus_request_name(m_conn, m_dbus_client_name.c_str(),
+ DBUS_NAME_FLAG_REPLACE_EXISTING , &m_err);
+ RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
+ "Error in dbus_bus_request_name: " << m_err.message);
+}
+
+void ServiceManager::getUnitPath() {
+ newMethodCall("GetUnit");
+ appendToMsg(m_service_name.c_str());
+ sendMsgWithReply();
+ getMsgReply();
+ m_unitPath = handleObjectPathMsgReply();
+}
+
+void ServiceManager::newMethodCall(const char *method) {
+ m_msg = dbus_message_new_method_call(m_dbus_systemd_destination.c_str(),
+ m_dbus_systemd_path.c_str(),
+ m_dbus_systemd_manager_interface.c_str(),
+ method);
+ RUNNER_ASSERT_MSG(nullptr != m_msg,
+ "Error in dbus_message_new_method_call");
+}
+
+void ServiceManager::appendToMsg(const char *argument) {
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append(m_msg, &iter);
+ int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+ &argument);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_append_basic");
+}
+
+void ServiceManager::appendToMsg(const char *const *argument) {
+ DBusMessageIter iter;
+ DBusMessageIter subIter;
+ int ret;
+
+ dbus_message_iter_init_append(m_msg, &iter);
+ ret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING,
+ &subIter);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_open_container");
+ for (auto str = argument; *str; str++) {
+ int ret = dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, str);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_append_basic");
+ }
+ ret = dbus_message_iter_close_container(&iter, &subIter);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_close_container");
+}
+
+void ServiceManager::appendToMsg(bool argument) {
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append(m_msg, &iter);
+ int b = argument ? 1 : 0;
+ int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN,
+ &b);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_append_basic");
+}
+
+void ServiceManager::sendMsgWithReply() {
+ int ret = dbus_connection_send_with_reply(m_conn, m_msg, &m_pending, -1);
+ RUNNER_ASSERT_MSG(ret == 1,
+ "Error in dbus_connection_send_with_reply");
+
+ RUNNER_ASSERT_MSG(nullptr != m_pending, "Pending call null");
+
+ dbus_connection_flush(m_conn);
+ dbus_pending_call_block(m_pending);
+
+ dbus_message_unref(m_msg);
+ m_msg = nullptr;
+}
+
+void ServiceManager::getMsgReply() {
+ m_msg = dbus_pending_call_steal_reply(m_pending);
+ RUNNER_ASSERT_MSG(nullptr != m_msg,
+ "Error in dbus_pending_call_steal_reply");
+}
+
+std::string ServiceManager::handleObjectPathMsgReply() {
+ DBusMessageIter iter;
+
+ RUNNER_ASSERT_MSG(dbus_message_iter_init(m_msg, &iter) != 0,
+ "Message has no arguments");
+ if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("Object path type expected");
+ }
+ char *tmp;
+ dbus_message_iter_get_basic(&iter, &tmp);
+ std::string ret(tmp);
+
+ finalizeMsgReply();
+ return ret;
+}
+
+uint32_t ServiceManager::handleVariantUIntMsgReply() {
+ DBusMessageIter iter, iter2;
+
+ RUNNER_ASSERT_MSG(dbus_message_iter_init(m_msg, &iter) != 0,
+ "Message has no arguments");
+ if (DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("Variant type expected");
+ }
+
+ dbus_message_iter_recurse(&iter, &iter2);
+ if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&iter2)) {
+ RUNNER_FAIL_MSG("uint32 type expected");
+ }
+
+ uint32_t ret;
+ dbus_message_iter_get_basic(&iter2, &ret);
+
+ finalizeMsgReply();
+ return ret;
+}
+
+void ServiceManager::finalizeMsgReply() {
+ dbus_message_unref(m_msg);
+ dbus_pending_call_unref(m_pending);
+ m_msg = nullptr;
+ m_pending = nullptr;
+}
+
+void ServiceManager::connectToDBus() {
+ connect();
+ addBusMatch("JobRemoved");
+ addBusMatch("JobNew");
+ addBusMatch("Reloading");
+ dbus_connection_flush(m_conn);
+ dbus_connection_add_filter(m_conn,
+ messageHandler,
+ reinterpret_cast<void*>(this),
+ [](void*)->void {});
+ subscribeSignals();
+ requestName();
+ getUnitPath();
+}
+
+void ServiceManager::sendToService(const char *method) {
+ newMethodCall(method);
+ appendToMsg(m_service_name.c_str());
+ appendToMsg("fail");
+ sendMsgWithReply();
+ getMsgReply();
+ m_runningJobs.insert(handleObjectPathMsgReply());
+}
+
+void ServiceManager::sendMaskToService() {
+ const char *mask[] = {m_service_name.c_str(), nullptr};
+ newMethodCall("MaskUnitFiles");
+ appendToMsg(mask);
+ appendToMsg(true);
+ appendToMsg(true);
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+}
+
+void ServiceManager::sendUnmaskToService() {
+ const char *mask[] = {m_service_name.c_str(), nullptr};
+ newMethodCall("UnmaskUnitFiles");
+ appendToMsg(mask);
+ appendToMsg(true);
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+}
+
+uint32_t ServiceManager::getUIntProperty(const char *interface, const char *property)
+{
+ m_msg = dbus_message_new_method_call(m_dbus_systemd_destination.c_str(),
+ m_unitPath.c_str(),
+ m_dbus_systemd_properties_interface.c_str(),
+ "Get");
+
+ appendToMsg(interface);
+ appendToMsg(property);
+ sendMsgWithReply();
+ getMsgReply();
+ return handleVariantUIntMsgReply();
+}
+
+void ServiceManager::sendResetFailedToService() {
+ newMethodCall("ResetFailedUnit");
+ appendToMsg(m_service_name.c_str());
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+}
+
+DBusHandlerResult ServiceManager::messageHandler(DBusConnection *conn, DBusMessage *msg, void *t) {
+ (void) conn;
+ ServiceManager* self = reinterpret_cast<ServiceManager*>(t);
+
+ if (self->isSignal(msg, "JobRemoved"))
+ self->signalJobRemovedHandler(msg);
+ else if (self->isSignal(msg, "JobNew"))
+ self->signalJobNewHandler(msg);
+ else if (self->isSignal(msg, "Reloading"))
+ self->signalReloadingHandler(msg);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+bool ServiceManager::isSignal(DBusMessage *msg, const char *signal) {
+ return dbus_message_is_signal(msg, m_dbus_systemd_manager_interface.c_str(), signal);
+}
+
+void ServiceManager::signalJobRemovedHandler(DBusMessage *msg) {
+ DBusMessageIter iter;
+ RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
+ "Message has no arguments");
+
+ if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("uint32 type expected");
+ }
+ uint32_t id;
+ dbus_message_iter_get_basic(&iter, &id);
+
+ dbus_message_iter_next (&iter);
+ if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("Object path type expected");
+ }
+ char *path;
+ dbus_message_iter_get_basic(&iter, &path);
+
+ dbus_message_iter_next (&iter);
+ if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("String type expected");
+ }
+ char *unit;
+ dbus_message_iter_get_basic(&iter, &unit);
+
+ dbus_message_iter_next (&iter);
+ if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("String type expected");
+ }
+ char *result;
+ dbus_message_iter_get_basic(&iter, &result);
+
+ if(m_service_name == unit) {
+ RUNNER_ASSERT_MSG(strcmp(result, "done") == 0 || strcmp(result, "canceled") == 0,
+ "RemoveJob signal delivered bad news. Job wasn't completed successfully: "
+ << "expected job results = {done, canceled}, "
+ << "received job result = " << result << ", "
+ << "for job with id = " << id << ", "
+ << "and path = " << path);
+ m_runningJobs.erase(path);
+ }
+}
+
+void ServiceManager::signalJobNewHandler(DBusMessage *msg) {
+ DBusMessageIter iter;
+ RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
+ "Message has no arguments");
+
+ if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("uint32 type expected");
+ }
+ uint32_t id;
+ dbus_message_iter_get_basic(&iter, &id);
+
+ dbus_message_iter_next (&iter);
+ if (DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("Object path type expected");
+ }
+ char *path;
+ dbus_message_iter_get_basic(&iter, &path);
+
+ dbus_message_iter_next (&iter);
+ if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("String type expected");
+ }
+ char *unit;
+ dbus_message_iter_get_basic(&iter, &unit);
+
+ if(m_service_name == unit)
+ m_runningJobs.insert(path);
+}
+
+void ServiceManager::signalReloadingHandler(DBusMessage *msg) {
+ DBusMessageIter iter;
+ RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
+ "Message has no arguments");
+
+ if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("boolean type expected");
+ }
+ bool active;
+ dbus_message_iter_get_basic(&iter, &active);
+
+ if (active)
+ m_runningJobs.insert(m_reloadingToken);
+ else
+ m_runningJobs.erase(m_reloadingToken);
+}
+
+void ServiceManager::waitForRunningJobsFinish() {
+ while (!m_runningJobs.empty())
+ dbus_connection_read_write_dispatch(m_conn, -1);
+}
+
+void ServiceManager::startService() {
+ sendToService("StartUnit");
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void ServiceManager::stopService() {
+ sendToService("StopUnit");
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void ServiceManager::restartService() {
+ sendToService("RestartUnit");
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+pid_t ServiceManager::getServicePid() {
+ return static_cast<pid_t>(getUIntProperty(m_dbus_systemd_service_interface.c_str(), "MainPID"));
+}
+
+void ServiceManager::maskService() {
+ sendMaskToService();
+ reloadDbusManager();
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void ServiceManager::unmaskService() {
+ sendUnmaskToService();
+ reloadDbusManager();
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+ServiceManager::~ServiceManager() {
+ dbus_connection_close(m_conn);
+ if (m_conn)
+ dbus_connection_unref(m_conn);
+ dbus_error_free(&m_err);
+ if (m_msg)
+ dbus_message_unref(m_msg);
+ if (m_pending)
+ dbus_pending_call_unref(m_pending);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file service_manager.h
+ * @author Zbigniew Jasinski <z.jasinski@samsung.com>
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.1
+ * @brief System service control class using dbus interface to communicate with systemd
+ */
+
+#ifndef COMMON_SERVICE_MANAGER_H
+#define COMMON_SERVICE_MANAGER_H
+
+#include <dbus/dbus.h>
+
+#include <set>
+#include <string>
+
+class ServiceManager {
+public:
+ ServiceManager() = delete;
+ ServiceManager(const char *service_name);
+
+ void startService();
+ void stopService();
+ void restartService();
+ pid_t getServicePid();
+ void maskService();
+ void unmaskService();
+
+ virtual ~ServiceManager();
+private:
+ void connect();
+ void addBusMatch(const char *member);
+ void subscribeSignals();
+ void reloadDbusManager();
+ void requestName();
+ void getUnitPath();
+ void newMethodCall(const char *method);
+ void appendToMsg(const char *argument);
+ void appendToMsg(const char *const *argument);
+ void appendToMsg(bool argument);
+ void sendMsgWithReply();
+ void getMsgReply();
+ std::string handleObjectPathMsgReply();
+ uint32_t handleVariantUIntMsgReply();
+ void finalizeMsgReply();
+
+ void connectToDBus();
+ void sendToService(const char *method);
+ void sendMaskToService();
+ void sendUnmaskToService();
+ uint32_t getUIntProperty(const char *interface, const char *property);
+ void sendResetFailedToService();
+
+ static DBusHandlerResult messageHandler(DBusConnection *conn, DBusMessage *msg, void *t);
+ bool isSignal(DBusMessage *msg, const char *signal);
+ void signalJobRemovedHandler(DBusMessage *msg);
+ void signalJobNewHandler(DBusMessage *msg);
+ void signalReloadingHandler(DBusMessage *msg);
+ void waitForRunningJobsFinish();
+
+ DBusConnection *m_conn;
+ DBusMessage *m_msg;
+ DBusError m_err;
+ DBusPendingCall *m_pending;
+
+ const std::string m_dbus_client_name;
+ const std::string m_service_name;
+ std::string m_unitPath;
+
+ const std::string m_dbus_systemd_destination;
+ const std::string m_dbus_systemd_path;
+ const std::string m_dbus_systemd_manager_interface;
+ const std::string m_dbus_systemd_properties_interface;
+ const std::string m_dbus_systemd_service_interface;
+
+ std::set<std::string> m_runningJobs;
+ const std::string m_reloadingToken;
+};
+
+#endif // COMMON_SERVICE_MANAGER_H
#include <cynara_test_env.h>
#include <tests_common.h>
-#include <dbus_access.h>
+#include <service_manager.h>
#include <memory.h>
#include <sys/types.h>
clear(m_dir);
removeDirIfExists(m_dir);
- DBusAccess dbusAccess("cynara.service");
- dbusAccess.maskService();
- dbusAccess.stopService();
+ ServiceManager serviceManager("cynara.service");
+ serviceManager.maskService();
+ serviceManager.stopService();
m_dbPresent = cynaraDbExists();
if (m_dbPresent) {
copyDir(cynaraDbDir, m_dir);
}
- dbusAccess.unmaskService();
- dbusAccess.startService();
+ serviceManager.unmaskService();
+ serviceManager.startService();
}
void CynaraTestEnv::restore()
{
- DBusAccess dbusAccess("cynara.service");
- dbusAccess.maskService();
- dbusAccess.stopService();
+ ServiceManager serviceManager("cynara.service");
+ serviceManager.maskService();
+ serviceManager.stopService();
clear(cynaraDbDir);
if (m_dbPresent)
else
removeDirIfExists(cynaraDbDir);
- dbusAccess.unmaskService();
- dbusAccess.startService();
+ serviceManager.unmaskService();
+ serviceManager.startService();
clear(m_dir);
removeDirIfExists(m_dir);
#include <ftw.h>
#include <unistd.h>
-#include <dbus_access.h>
+#include <service_manager.h>
int restart_security_server() {
- DBusAccess dbusAccess("security-server.service");
- dbusAccess.restartService();
+ ServiceManager serviceManager("security-server.service");
+ serviceManager.restartService();
return 0;
}