From 77cfcdd256ef3f7a1923ed821ff4aad603f20d54 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 30 Oct 2014 16:59:25 +0100 Subject: [PATCH] Start&stop support added to DBusAccess [Verification] Run security-server-tests-password --output=text to make sure existing tests are not broken Change-Id: Ib5b1353c5892fb3685ace4f8f6226ab842c07ec8 --- tests/common/CMakeLists.txt | 1 + tests/common/dbus_access.cpp | 441 ++------------------- tests/common/dbus_access.h | 77 +--- tests/common/dbus_access_impl.cpp | 175 ++++++++ tests/common/dbus_access_impl.h | 67 ++++ tests/cynara-tests/common/cynara_test_env.cpp | 12 +- .../security_server_clean_env.cpp | 5 +- 7 files changed, 308 insertions(+), 470 deletions(-) create mode 100644 tests/common/dbus_access_impl.cpp create mode 100644 tests/common/dbus_access_impl.h diff --git a/tests/common/CMakeLists.txt b/tests/common/CMakeLists.txt index 35d987d..67b1fbe 100644 --- a/tests/common/CMakeLists.txt +++ b/tests/common/CMakeLists.txt @@ -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 diff --git a/tests/common/dbus_access.cpp b/tests/common/dbus_access.cpp index 7d0390f..0ba91f7 100644 --- a/tests/common/dbus_access.cpp +++ b/tests/common/dbus_access.cpp @@ -17,424 +17,71 @@ */ /* * @file dbus_access.cpp - * @author Zbigniew Jasinski - * @author Lukasz Wojciechowski - * @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 -#include +#include +#include -#include -#include -#include +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(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(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(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); } diff --git a/tests/common/dbus_access.h b/tests/common/dbus_access.h index f957a7e..3577f13 100644 --- a/tests/common/dbus_access.h +++ b/tests/common/dbus_access.h @@ -17,80 +17,31 @@ */ /* * @file dbus_access.h - * @author Zbigniew Jasinski - * @author Lukasz Wojciechowski - * @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 - -#include -#include +#include 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 m_runningJobs; - const std::string m_reloadingToken; + std::unique_ptr 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 index 0000000..f828b30 --- /dev/null +++ b/tests/common/dbus_access_impl.cpp @@ -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 + +#include + +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(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(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 index 0000000..8f3610a --- /dev/null +++ b/tests/common/dbus_access_impl.h @@ -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 + +#include + +#include + +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; +}; diff --git a/tests/cynara-tests/common/cynara_test_env.cpp b/tests/cynara-tests/common/cynara_test_env.cpp index ce606c8..711a601 100644 --- a/tests/cynara-tests/common/cynara_test_env.cpp +++ b/tests/cynara-tests/common/cynara_test_env.cpp @@ -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); diff --git a/tests/security-server-tests/security_server_clean_env.cpp b/tests/security-server-tests/security_server_clean_env.cpp index df7a73b..a063281 100644 --- a/tests/security-server-tests/security_server_clean_env.cpp +++ b/tests/security-server-tests/security_server_clean_env.cpp @@ -15,8 +15,9 @@ #include int restart_security_server() { - DBusAccess dbusAccess("security-server.service"); - dbusAccess.restartService(); + DBusAccess dbusAccess("/org/freedesktop/systemd1/unit/security_2dserver_2eservice"); + + dbusAccess.restart(); return 0; } -- 2.7.4