Start&stop support added to DBusAccess
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 30 Oct 2014 15:59:25 +0000 (16:59 +0100)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Wed, 18 Feb 2015 08:57:36 +0000 (09:57 +0100)
[Verification] Run security-server-tests-password --output=text
to make sure existing tests are not broken

Change-Id: Ib5b1353c5892fb3685ace4f8f6226ab842c07ec8

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

index 35d987d..67b1fbe 100644 (file)
@@ -18,6 +18,7 @@ SET(COMMON_TARGET_TEST_SOURCES
     ${PROJECT_SOURCE_DIR}/tests/common/memory.cpp
     ${PROJECT_SOURCE_DIR}/tests/common/db_sqlite.cpp
     ${PROJECT_SOURCE_DIR}/tests/common/fs_label_manager.cpp
+    ${PROJECT_SOURCE_DIR}/tests/common/dbus_access_impl.cpp
     )
 
 #system and local includes
index 7d0390f..0ba91f7 100644 (file)
  */
 /*
  * @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
+ * @author      Zbigniew Jasinski (z.jasinski@samsung.com)
+ * @version     1.0
+ * @brief       Functios used in security-tests package for restarting Security Server through
+ *              SystemD DBuS interface.
  */
 
-#include <dpl/log/log.h>
-#include <tests_common.h>
+#include <dbus_access.h>
+#include <dbus_access_impl.h>
 
-#include <cstring>
-#include <sstream>
-#include <unistd.h>
+namespace {
+const char* const RESTART = "Restart";
+const char* const STOP = "Stop";
+const char* const START = "Start";
+const char* const RESET_FAILED = "ResetFailed";
 
-#include "dbus_access.h"
+const char* const MODE_FAIL = "fail";
 
-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");
-    }
+} // anonymous namespace
 
-    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)
+DBusAccess::DBusAccess(const char* const object)
 {
-    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;
+    m_impl.reset(new DBusAccess::Impl(object));
 }
 
-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);
+DBusAccess::~DBusAccess()
+{
 }
 
-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);
+void DBusAccess::restart() {
+    /*
+     * Example:
+     * dbus-send --system --dest=org.freedesktop.systemd1 --print-reply
+     *  /org/freedesktop/systemd1/unit/central_2dkey_2dmanager_2eservice
+     *  org.freedesktop.systemd1.Unit.Restart string:fail
+     */
+    m_impl->newMethodCall(RESTART);
+    m_impl->setMode(MODE_FAIL);
+    m_impl->sendCommand();
 
-    if (active)
-        m_runningJobs.insert(m_reloadingToken);
-    else
-        m_runningJobs.erase(m_reloadingToken);
-}
+    m_impl->waitForJobEnd();
 
-void DBusAccess::waitForRunningJobsFinish() {
-    while (!m_runningJobs.empty())
-        dbus_connection_read_write_dispatch(m_conn, -1);
+    sendResetFailed();
 }
 
-void DBusAccess::startService() {
-    sendToService("StartUnit");
-    waitForRunningJobsFinish();
-    sendResetFailedToService();
-}
+void DBusAccess::start() {
+    m_impl->newMethodCall(START);
+    m_impl->setMode(MODE_FAIL);
+    m_impl->sendCommand();
 
-void DBusAccess::stopService() {
-    sendToService("StopUnit");
-    waitForRunningJobsFinish();
-    sendResetFailedToService();
-}
+    m_impl->waitForJobEnd();
 
-void DBusAccess::restartService() {
-    sendToService("RestartUnit");
-    waitForRunningJobsFinish();
-    sendResetFailedToService();
+    sendResetFailed();
 }
 
-pid_t DBusAccess::getServicePid() {
-    return static_cast<pid_t>(getUIntProperty(m_dbus_systemd_service_interface.c_str(), "MainPID"));
-}
+void DBusAccess::stop() {
+    m_impl->newMethodCall(STOP);
+    m_impl->setMode(MODE_FAIL);
+    m_impl->sendCommand();
 
-void DBusAccess::maskService() {
-    sendMaskToService();
-    reloadDbusManager();
-    waitForRunningJobsFinish();
-    sendResetFailedToService();
-}
+    m_impl->waitForJobEnd();
 
-void DBusAccess::unmaskService() {
-    sendUnmaskToService();
-    reloadDbusManager();
-    waitForRunningJobsFinish();
-    sendResetFailedToService();
+    sendResetFailed();
 }
 
-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);
+void DBusAccess::sendResetFailed() {
+    m_impl->newMethodCall(RESET_FAILED);
+    m_impl->sendCommand(false);
 }
index f957a7e..3577f13 100644 (file)
  */
 /*
  * @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
+ * @author      Zbigniew Jasinski (z.jasinski@samsung.com)
+ * @version     1.0
+ * @brief       Functions used in security-tests package for restarting Security Server through
+ *              SystemD DBuS interface.
  */
 #ifndef _DBUS_ACCESS_H_
 #define _DBUS_ACCESS_H_
 
-#include <dbus/dbus.h>
-
-#include <set>
-#include <string>
+#include <memory>
 
 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();
+    class Impl;
 
-    void connectToDBus();
-    void sendToService(const char *method);
-    void sendMaskToService();
-    void sendUnmaskToService();
-    uint32_t getUIntProperty(const char *interface, const char *property);
-    void sendResetFailedToService();
+    DBusAccess(const char* const object);
+    ~DBusAccess();
 
-    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();
+    void restart();
+    void start();
+    void stop();
 
-    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;
+private:
+    void sendResetFailed();
 
-    std::set<std::string> m_runningJobs;
-    const std::string m_reloadingToken;
+    std::unique_ptr<DBusAccess::Impl> m_impl;
 };
 
 #endif // _DBUS_ACCESS_H_
diff --git a/tests/common/dbus_access_impl.cpp b/tests/common/dbus_access_impl.cpp
new file mode 100644 (file)
index 0000000..f828b30
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  Copyright (c) 2000 - 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_impl.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <dbus_access_impl.h>
+
+#include <tests_common.h>
+
+DBusAccess::Impl::Impl(const char* object)
+  : m_conn(NULL)
+  , m_msg(NULL)
+  , m_pending(NULL)
+  , m_handled(false)
+{
+    dbus_error_init(&m_err);
+
+    m_signal_type         = "signal";
+    m_signal_interface    = "org.freedesktop.systemd1.Manager";
+    m_signal_path         = "/org/freedesktop/systemd1";
+    m_dbus_client_name    = "tests.dbus.client";
+    m_signal_member       = "JobRemoved";
+    m_dbus_systemd_object = object;
+
+    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);
+
+    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);
+}
+
+DBusAccess::Impl::~Impl() {
+    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);
+}
+
+void DBusAccess::Impl::newMethodCall(const char* method) {
+    const std::string dbus_systemd_name = "org.freedesktop.systemd1";
+    const std::string dbus_systemd_interface = "org.freedesktop.systemd1.Unit";
+
+    m_msg = dbus_message_new_method_call(dbus_systemd_name.c_str(),
+                                         m_dbus_systemd_object.c_str(),
+                                         dbus_systemd_interface.c_str(),
+                                         method);
+    RUNNER_ASSERT_MSG(NULL != m_msg,
+        "Error in dbus_message_new_method_call");
+}
+
+void DBusAccess::Impl::setMode(const char* mode) {
+    DBusMessageIter iter;
+    const char *dbus_systemd_srv_unit_mode = mode;
+
+    dbus_message_iter_init_append(m_msg, &iter);
+    int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
+        &dbus_systemd_srv_unit_mode);
+    RUNNER_ASSERT_MSG(ret != 0,
+        "Error in dbus_message_iter_append_basic");
+}
+
+void DBusAccess::Impl::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(NULL != m_pending, "Pending call null");
+
+    dbus_connection_flush(m_conn);
+    dbus_pending_call_block(m_pending);
+    dbus_message_unref(m_msg);
+    m_msg = NULL;
+}
+
+void DBusAccess::Impl::getMsgReply() {
+    m_msg = dbus_pending_call_steal_reply(m_pending);
+    RUNNER_ASSERT_MSG(NULL != m_msg,
+        "Error in dbus_pending_call_steal_reply");
+}
+
+void DBusAccess::Impl::handleMsgReply() {
+    char *object_path = NULL;
+    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)) {
+        dbus_message_iter_get_basic(&iter, &object_path);
+        m_jobID = std::strrchr(object_path, '/') + 1;
+    } else {
+        RUNNER_ASSERT_MSG(false, "No job path in msg");
+    }
+    dbus_message_unref(m_msg);
+    dbus_pending_call_unref(m_pending);
+    m_msg = NULL;
+    m_pending = NULL;
+}
+
+DBusHandlerResult DBusAccess::Impl::signalFilter(DBusConnection *, DBusMessage *message, void *This) {
+    DBusMessageIter iter;
+    dbus_uint32_t id;
+    DBusAccess::Impl *a = reinterpret_cast<DBusAccess::Impl *>(This);
+
+    if (dbus_message_is_signal(message, a->m_signal_interface.c_str(), a->m_signal_member.c_str()))
+    {
+        RUNNER_ASSERT_MSG(dbus_message_iter_init(message, &iter) != 0,
+            "No messages in reply");
+
+        RUNNER_ASSERT_MSG(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32,
+            "Argument is not integer");
+
+        dbus_message_iter_get_basic(&iter, &id);
+
+        if (id == (unsigned int)std::stoi(a->m_jobID)) {
+            while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
+                if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
+                    char *str = NULL;
+                    dbus_message_iter_get_basic(&iter, &str);
+                    if (!strncmp(str, "done", strlen("done")))
+                        a->m_handled = true;
+                }
+                dbus_message_iter_next(&iter);
+            }
+        }
+    }
+    return (a->m_handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+}
+
+void DBusAccess::Impl::waitForJobEnd() {
+    std::string signal_match = "type='" + m_signal_type + "',interface='" + m_signal_interface +
+                               "',member='" + m_signal_member + "',path='" + m_signal_path + "'";
+
+    dbus_bus_add_match(m_conn, signal_match.c_str(), &m_err);
+    RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
+        "Error in dbus_bus_add_match: " << m_err.message);
+
+    dbus_connection_add_filter(m_conn, signalFilter, reinterpret_cast<void *>(this), NULL);
+
+    while(dbus_connection_read_write_dispatch(m_conn, 1000)) {
+        if(m_handled)
+            break;
+    }
+    m_handled = false;
+}
+
+void DBusAccess::Impl::sendCommand(bool handleReply) {
+    sendMsgWithReply();
+    getMsgReply();
+    if (handleReply)
+        handleMsgReply();
+}
diff --git a/tests/common/dbus_access_impl.h b/tests/common/dbus_access_impl.h
new file mode 100644 (file)
index 0000000..8f3610a
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2000 - 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_impl.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <string>
+
+#include <dbus/dbus.h>
+
+#include <dbus_access.h>
+
+class DBusAccess::Impl
+{
+public:
+    explicit Impl(const char* object);
+    ~Impl();
+
+    void newMethodCall(const char* method);
+    void setMode(const char* mode);
+    void sendCommand(bool handleReply = true);
+    void waitForJobEnd();
+    // Systemd will not allow to many commands on single unit. This will reset command counter
+    void sendResetFailed();
+
+private:
+    void connect();
+    void requestName();
+    void sendMsgWithReply();
+    void getMsgReply();
+    void handleMsgReply();
+
+    static DBusHandlerResult signalFilter(DBusConnection *, DBusMessage *message, void *);
+
+    DBusConnection *m_conn;
+    DBusMessage *m_msg;
+    DBusError m_err;
+    DBusPendingCall *m_pending;
+    std::string m_jobID;
+
+    std::string m_signal_type;
+    std::string m_signal_interface;
+    std::string m_signal_member;
+    std::string m_signal_path;
+
+    std::string m_dbus_client_name;
+    std::string m_dbus_systemd_object;
+
+    bool m_handled;
+};
index ce606c8..711a601 100644 (file)
@@ -152,8 +152,7 @@ void CynaraTestEnv::save()
     removeDirIfExists(m_dir);
 
     DBusAccess dbusAccess("cynara.service");
-    dbusAccess.maskService();
-    dbusAccess.stopService();
+    dbusAccess.stop();
 
     m_dbPresent = cynaraDbExists();
     if (m_dbPresent) {
@@ -162,15 +161,13 @@ void CynaraTestEnv::save()
         copyDir(cynaraDbDir, m_dir);
     }
 
-    dbusAccess.unmaskService();
-    dbusAccess.startService();
+    dbusAccess.start();
 }
 
 void CynaraTestEnv::restore()
 {
     DBusAccess dbusAccess("cynara.service");
-    dbusAccess.maskService();
-    dbusAccess.stopService();
+    dbusAccess.stop();
 
     clear(cynaraDbDir);
     if (m_dbPresent)
@@ -178,8 +175,7 @@ void CynaraTestEnv::restore()
     else
         removeDirIfExists(cynaraDbDir);
 
-    dbusAccess.unmaskService();
-    dbusAccess.startService();
+    dbusAccess.start();
 
     clear(m_dir);
     removeDirIfExists(m_dir);
index df7a73b..a063281 100644 (file)
@@ -15,8 +15,9 @@
 #include <dbus_access.h>
 
 int restart_security_server() {
-    DBusAccess dbusAccess("security-server.service");
-    dbusAccess.restartService();
+    DBusAccess dbusAccess("/org/freedesktop/systemd1/unit/security_2dserver_2eservice");
+
+    dbusAccess.restart();
 
     return 0;
 }