Change DBusAccess class name to ServiceManager 08/32508/3
authorMarcin Niesluchowski <m.niesluchow@samsung.com>
Thu, 18 Dec 2014 12:07:15 +0000 (13:07 +0100)
committerMarcin Niesluchowski <m.niesluchow@samsung.com>
Tue, 23 Dec 2014 16:59:53 +0000 (17:59 +0100)
Change-Id: I38483087929620e12bcd2b68146b36de7a266d9c

tests/common/CMakeLists.txt
tests/common/dbus_access.cpp [deleted file]
tests/common/dbus_access.h [deleted file]
tests/common/service_manager.cpp [new file with mode: 0644]
tests/common/service_manager.h [new file with mode: 0644]
tests/cynara-tests/common/cynara_test_env.cpp
tests/security-server-tests/security_server_clean_env.cpp

index dcf486f096143d199c92f668a1b8d8244f1d06fb..b32f6ba19c265303428edbba1da43fa9e79ef216 100644 (file)
@@ -14,10 +14,10 @@ SET(COMMON_TARGET_TEST_SOURCES
     ${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
diff --git a/tests/common/dbus_access.cpp b/tests/common/dbus_access.cpp
deleted file mode 100644 (file)
index 7290bbb..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * 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);
-}
diff --git a/tests/common/dbus_access.h b/tests/common/dbus_access.h
deleted file mode 100644 (file)
index c295a29..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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_
diff --git a/tests/common/service_manager.cpp b/tests/common/service_manager.cpp
new file mode 100644 (file)
index 0000000..0240b91
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * 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);
+}
diff --git a/tests/common/service_manager.h b/tests/common/service_manager.h
new file mode 100644 (file)
index 0000000..a5d1908
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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
index ce606c88459c83e4edfa96adea3f939d7a9b4f0d..166b123dcc0805191f7639ba3b70c69f80a4a94d 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <cynara_test_env.h>
 #include <tests_common.h>
-#include <dbus_access.h>
+#include <service_manager.h>
 #include <memory.h>
 
 #include <sys/types.h>
@@ -151,9 +151,9 @@ void CynaraTestEnv::save()
     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) {
@@ -162,15 +162,15 @@ void CynaraTestEnv::save()
         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)
@@ -178,8 +178,8 @@ void CynaraTestEnv::restore()
     else
         removeDirIfExists(cynaraDbDir);
 
-    dbusAccess.unmaskService();
-    dbusAccess.startService();
+    serviceManager.unmaskService();
+    serviceManager.startService();
 
     clear(m_dir);
     removeDirIfExists(m_dir);
index df7a73b4b4021dd40235adbe9a87fe9525f5c321..94833c940ff36d30fd7395642b025abb9401866a 100644 (file)
 #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;
 }