CKM:Add compilation flag for MDPP
[platform/core/test/security-tests.git] / tests / common / dbus_access_impl.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 /*
17  * @file       dbus_access_impl.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <dbus_access_impl.h>
23
24 #include <tests_common.h>
25
26 namespace {
27 void popArgument(DBusMessageIter *iter, int expected, void *value = NULL) {
28     int type = dbus_message_iter_get_arg_type(iter);
29     RUNNER_ASSERT_MSG(type == expected,
30                          "Argument type is: " << type << ". Expected: " << expected);
31
32     if (value != NULL)
33         dbus_message_iter_get_basic(iter, value);
34     dbus_message_iter_next (iter);
35 }
36 } // namespace anonymous
37
38 DBusAccess::Impl::Impl(const char* object)
39   : m_conn(NULL)
40   , m_msg(NULL)
41   , m_pending(NULL)
42   , m_handled(false)
43 {
44     dbus_error_init(&m_err);
45
46     m_signal_type         = "signal";
47     m_signal_interface    = "org.freedesktop.systemd1.Manager";
48     m_signal_path         = "/org/freedesktop/systemd1";
49     m_dbus_client_name    = "tests.dbus.client";
50     m_signal_member       = "JobRemoved";
51     m_dbus_systemd_object = object;
52
53     m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_err);
54     RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
55         "Error in dbus_bus_get: " << m_err.message);
56     dbus_connection_set_exit_on_disconnect(m_conn, FALSE);
57
58     dbus_bus_request_name(m_conn, m_dbus_client_name.c_str(),
59         DBUS_NAME_FLAG_REPLACE_EXISTING , &m_err);
60     RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
61         "Error in dbus_bus_request_name: " << m_err.message);
62 }
63
64 DBusAccess::Impl::~Impl() {
65     dbus_connection_close(m_conn);
66     if (m_conn)
67         dbus_connection_unref(m_conn);
68     dbus_error_free(&m_err);
69     if (m_msg)
70         dbus_message_unref(m_msg);
71     if (m_pending)
72         dbus_pending_call_unref(m_pending);
73 }
74
75 void DBusAccess::Impl::newMethodCall(const char* method) {
76     const std::string dbus_systemd_name = "org.freedesktop.systemd1";
77     const std::string dbus_systemd_interface = "org.freedesktop.systemd1.Unit";
78
79     m_msg = dbus_message_new_method_call(dbus_systemd_name.c_str(),
80                                          m_dbus_systemd_object.c_str(),
81                                          dbus_systemd_interface.c_str(),
82                                          method);
83     RUNNER_ASSERT_MSG(NULL != m_msg,
84         "Error in dbus_message_new_method_call");
85 }
86
87 void DBusAccess::Impl::setMode(const char* mode) {
88     DBusMessageIter iter;
89     const char *dbus_systemd_srv_unit_mode = mode;
90
91     dbus_message_iter_init_append(m_msg, &iter);
92     int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
93         &dbus_systemd_srv_unit_mode);
94     RUNNER_ASSERT_MSG(ret != 0,
95         "Error in dbus_message_iter_append_basic");
96 }
97
98 void DBusAccess::Impl::sendMsgWithReply() {
99     int ret = dbus_connection_send_with_reply(m_conn, m_msg, &m_pending, -1);
100     RUNNER_ASSERT_MSG(ret == 1,
101         "Error in dbus_connection_send_with_reply");
102
103     RUNNER_ASSERT_MSG(NULL != m_pending, "Pending call null");
104
105     dbus_connection_flush(m_conn);
106     dbus_pending_call_block(m_pending);
107     dbus_message_unref(m_msg);
108     m_msg = NULL;
109 }
110
111 void DBusAccess::Impl::getMsgReply() {
112     m_msg = dbus_pending_call_steal_reply(m_pending);
113     RUNNER_ASSERT_MSG(NULL != m_msg,
114         "Error in dbus_pending_call_steal_reply");
115 }
116
117 void DBusAccess::Impl::handleMsgReply() {
118     char *object_path = NULL;
119     DBusMessageIter iter;
120
121     RUNNER_ASSERT_MSG(dbus_message_iter_init(m_msg, &iter) != 0,
122         "Message has no arguments");
123     popArgument(&iter, DBUS_TYPE_OBJECT_PATH, &object_path);
124     m_jobID = std::strrchr(object_path, '/') + 1;
125     dbus_message_unref(m_msg);
126     dbus_pending_call_unref(m_pending);
127     m_msg = NULL;
128     m_pending = NULL;
129 }
130
131 DBusHandlerResult DBusAccess::Impl::signalFilter(DBusConnection *, DBusMessage *message, void *This) {
132     DBusAccess::Impl *a = reinterpret_cast<DBusAccess::Impl *>(This);
133
134     if (dbus_message_is_signal(message, a->m_signal_interface.c_str(), a->m_signal_member.c_str()))
135     {
136         DBusMessageIter iter;
137         dbus_uint32_t id;
138         const char *result;
139
140         dbus_message_iter_init(message, &iter);
141
142         popArgument(&iter, DBUS_TYPE_UINT32, &id);
143         popArgument(&iter, DBUS_TYPE_OBJECT_PATH);
144         popArgument(&iter, DBUS_TYPE_STRING);
145         popArgument(&iter, DBUS_TYPE_STRING, &result);
146
147         if (id == (unsigned int)std::stoi(a->m_jobID)) {
148             RUNNER_ASSERT_MSG(strcmp(result, "done") == 0 || strcmp(result, "canceled") == 0,
149                               "Unexpected result: " << result);
150             a->m_handled = true;
151         }
152     }
153     return (a->m_handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
154 }
155
156 void DBusAccess::Impl::addFilter() {
157     std::string signal_match = "type='" + m_signal_type + "',interface='" + m_signal_interface +
158                                "',member='" + m_signal_member + "',path='" + m_signal_path + "'";
159
160     dbus_bus_add_match(m_conn, signal_match.c_str(), &m_err);
161     RUNNER_ASSERT_MSG(dbus_error_is_set(&m_err) != 1,
162         "Error in dbus_bus_add_match: " << m_err.message);
163
164     // TODO refactor whole class to allow multiple requests and proper filters management
165     dbus_bool_t ret = dbus_connection_add_filter(m_conn, signalFilter, reinterpret_cast<void *>(this), NULL);
166     RUNNER_ASSERT_MSG( TRUE == ret, "dbus_connection_add_filter failed");
167
168     m_handled = false;
169 }
170
171 void DBusAccess::Impl::sendCommand(bool handleReply) {
172     sendMsgWithReply();
173     getMsgReply();
174     if (handleReply)
175         handleMsgReply();
176 }
177
178 void DBusAccess::Impl::waitForJobEnd() {
179     // TODO add custom timeout
180     while(dbus_connection_read_write_dispatch(m_conn, 1000)) {
181          if(m_handled)
182              break;
183      }
184 }