Remove description param from test result collecting function
[platform/core/test/security-tests.git] / tests / common / service_manager.cpp
1 /*
2  * Copyright (c) 2013-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        service_manager.cpp
18  * @author      Zbigniew Jasinski <z.jasinski@samsung.com>
19  * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
20  * @author      Marcin Niesluchowski <m.niesluchow@samsung.com>
21  * @version     1.1
22  * @brief       Definition of service control class using dbus interface to communicate with systemd
23  */
24
25 #include <service_manager.h>
26
27 #include <dpl/test/test_runner.h>
28
29 #include <sstream>
30 #include <unistd.h>
31 #include <vector>
32
33 namespace {
34
35 const std::string DBUS_CLIENT_NAME("tests.dbus.client");
36 const std::string DBUS_PROPERTIES_INTERFACE("org.freedesktop.DBus.Properties");
37 const std::string SYSTEMD_DESTINATION("org.freedesktop.systemd1");
38 const std::string SYSTEMD_PATH("/org/freedesktop/systemd1");
39 const std::string SYSTEMD_MANAGER_INTERFACE("org.freedesktop.systemd1.Manager");
40 const std::string SYSTEMD_SERVICE_INTERFACE("org.freedesktop.systemd1.Service");
41
42 const std::string MATCH_JOB_REMOVED("JobRemoved");
43 const std::string MATCH_JOB_NEW("JobNew");
44 const std::string MATCH_RELOADING("Reloading");
45
46 }
47
48 ServiceManager::ServiceManager(const std::string &serviceName)
49     : m_connection(DBUS_BUS_SYSTEM, true)
50     , m_serviceName(serviceName)
51 {
52     addBusMatch(MATCH_JOB_REMOVED);
53     addBusMatch(MATCH_JOB_NEW);
54     addBusMatch(MATCH_RELOADING);
55     m_connection.flush();
56     m_connection.addFilter(messageHandler,
57                            reinterpret_cast<void*>(this));
58     subscribeSignals();
59     m_connection.requestName(DBUS_CLIENT_NAME);
60     getUnitPath();
61 }
62
63 void ServiceManager::addBusMatch(const std::string &member)
64 {
65     std::ostringstream rule;
66     rule << "type='signal',"
67          << "sender='" << SYSTEMD_DESTINATION << "',"
68          << "interface='" << SYSTEMD_MANAGER_INTERFACE << "',"
69          << "member='" << member << "',"
70          << "path='" << SYSTEMD_PATH << "'";
71
72     m_connection.addMatch(rule.str());
73 }
74
75 void ServiceManager::subscribeSignals()
76 {
77     DBus::MessageOut messageOut = newMethodCall("Subscribe");
78     m_connection.sendWithReplyAndBlock(messageOut);
79 }
80
81 void ServiceManager::reloadDbusManager()
82 {
83     DBus::MessageOut messageOut = newMethodCall("Reload");
84     m_connection.sendWithReplyAndBlock(messageOut);
85     m_runningJobs.insert(MATCH_RELOADING);
86 }
87
88 void ServiceManager::getUnitPath()
89 {
90     DBus::MessageOut messageOut = newMethodCall("GetUnit");
91     messageOut.append(m_serviceName);
92     DBus::MessageIn messageIn = m_connection.sendWithReplyAndBlock(messageOut);
93     m_unitPath = handleObjectPathMsgReply(messageIn);
94 }
95
96 DBus::MessageOut ServiceManager::newMethodCall(const std::string &method)
97 {
98     return DBus::MessageOut(SYSTEMD_DESTINATION.c_str(),
99                       SYSTEMD_PATH.c_str(),
100                       SYSTEMD_MANAGER_INTERFACE.c_str(),
101                       method.c_str());
102 }
103
104 std::string ServiceManager::handleObjectPathMsgReply(DBus::MessageIn &messageIn)
105 {
106     DBus::MessageIn::Iterator iterator = messageIn.iterInit();
107     iterator.expectArgType(DBUS_TYPE_OBJECT_PATH);
108     return iterator.getArgString();
109 }
110
111 uint32_t ServiceManager::handleVariantUIntMsgReply(DBus::MessageIn &messageIn)
112 {
113     DBus::MessageIn::Iterator iterator = messageIn.iterInit();
114     iterator.expectArgType(DBUS_TYPE_VARIANT);
115     DBus::MessageIn::Iterator iteratorSub = iterator.recurse();
116     iteratorSub.expectArgType(DBUS_TYPE_UINT32);
117     return iteratorSub.getArgUint32();
118 }
119
120 void ServiceManager::sendToService(const std::string &method)
121 {
122     DBus::MessageOut messageOut = newMethodCall(method);
123     messageOut.append(m_serviceName);
124     messageOut.append("fail");
125     DBus::MessageIn messageIn = m_connection.sendWithReplyAndBlock(messageOut);
126     m_runningJobs.insert(handleObjectPathMsgReply(messageIn));
127 }
128
129 void ServiceManager::sendMaskToService()
130 {
131     const std::vector<std::string> mask(1, m_serviceName);
132     DBus::MessageOut messageOut = newMethodCall("MaskUnitFiles");
133     messageOut.append(mask);
134     messageOut.append(true);
135     messageOut.append(true);
136     m_connection.sendWithReplyAndBlock(messageOut);
137 }
138
139 void ServiceManager::sendUnmaskToService()
140 {
141     const std::vector<std::string> mask(1, m_serviceName);
142     DBus::MessageOut messageOut = newMethodCall("UnmaskUnitFiles");
143     messageOut.append(mask);
144     messageOut.append(true);
145     m_connection.sendWithReplyAndBlock(messageOut);
146 }
147
148 uint32_t ServiceManager::getUIntProperty(const std::string &interface, const std::string &property)
149 {
150     DBus::MessageOut messageOut(SYSTEMD_DESTINATION.c_str(),
151                           SYSTEMD_PATH.c_str(),
152                           DBUS_PROPERTIES_INTERFACE.c_str(),
153                           "Get");
154     messageOut.append(interface);
155     messageOut.append(property);
156     DBus::MessageIn messageIn = m_connection.sendWithReplyAndBlock(messageOut);
157     return handleVariantUIntMsgReply(messageIn);
158 }
159
160 void ServiceManager::sendResetFailedToService()
161 {
162     DBus::MessageOut messageOut = newMethodCall("ResetFailedUnit");
163     messageOut.append(m_serviceName);
164     m_connection.sendWithReplyAndBlock(messageOut);
165 }
166
167 DBusHandlerResult ServiceManager::messageHandler(DBusConnection *conn, DBusMessage *msg, void *t)
168 {
169     (void) conn;
170     ServiceManager* self = reinterpret_cast<ServiceManager*>(t);
171
172     DBus::MessageIn messageIn(msg, true);
173     if (messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_JOB_REMOVED))
174         self->signalJobRemovedHandler(messageIn);
175     else if(messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_JOB_NEW))
176         self->signalJobNewHandler(messageIn);
177     else if(messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_RELOADING))
178         self->signalReloadingHandler(messageIn);
179
180     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
181 }
182
183 void ServiceManager::signalJobRemovedHandler(DBus::MessageIn &messageIn)
184 {
185     DBus::MessageIn::Iterator iterator = messageIn.iterInit();
186
187     iterator.expectArgType(DBUS_TYPE_UINT32);
188     uint32_t id = iterator.getArgUint32();
189     iterator.expectNext();
190
191     iterator.expectArgType(DBUS_TYPE_OBJECT_PATH);
192     std::string path = iterator.getArgString();
193     iterator.expectNext();
194
195     iterator.expectArgType(DBUS_TYPE_STRING);
196     std::string unit = iterator.getArgString();
197     iterator.expectNext();
198
199     iterator.expectArgType(DBUS_TYPE_STRING);
200     std::string result = iterator.getArgString();
201
202     if(m_serviceName == unit) {
203         RUNNER_ASSERT_MSG(result == "done" || result == "canceled",
204                           "RemoveJob signal delivered bad news. Job wasn't completed successfully: "
205                               << "expected job results = {done, canceled}, "
206                               << "received job result = " << result << ", "
207                               << "for job with id = " << id << ", "
208                               << "and path = " << path);
209         m_runningJobs.erase(path);
210     }
211 }
212
213 void ServiceManager::signalJobNewHandler(DBus::MessageIn &messageIn)
214 {
215     DBus::MessageIn::Iterator iterator = messageIn.iterInit();
216
217     iterator.expectArgTypeValid();
218     iterator.expectNext();
219
220     iterator.expectArgType(DBUS_TYPE_OBJECT_PATH);
221     std::string path = iterator.getArgString();
222     iterator.expectNext();
223
224     iterator.expectArgType(DBUS_TYPE_STRING);
225     std::string unit = iterator.getArgString();
226
227     if(m_serviceName == unit)
228         m_runningJobs.insert(path);
229 }
230
231 void ServiceManager::signalReloadingHandler(DBus::MessageIn &messageIn)
232 {
233     DBus::MessageIn::Iterator iterator = messageIn.iterInit();
234
235     iterator.expectArgType(DBUS_TYPE_BOOLEAN);
236     bool active = iterator.getArgBool();
237
238     if (active)
239         m_runningJobs.insert(MATCH_RELOADING);
240     else
241         m_runningJobs.erase(MATCH_RELOADING);
242 }
243
244 void ServiceManager::waitForRunningJobsFinish()
245 {
246     while (!m_runningJobs.empty())
247         m_connection.readWriteDispatch();
248 }
249
250 void ServiceManager::startService()
251 {
252     sendToService("StartUnit");
253     waitForRunningJobsFinish();
254     sendResetFailedToService();
255 }
256
257 void ServiceManager::stopService()
258 {
259     sendToService("StopUnit");
260     waitForRunningJobsFinish();
261     sendResetFailedToService();
262 }
263
264 void ServiceManager::restartService()
265 {
266     sendToService("RestartUnit");
267     waitForRunningJobsFinish();
268     sendResetFailedToService();
269 }
270
271 pid_t ServiceManager::getServicePid()
272 {
273     return static_cast<pid_t>(getUIntProperty(SYSTEMD_SERVICE_INTERFACE, "MainPID"));
274 }
275
276 void ServiceManager::maskService()
277 {
278     sendMaskToService();
279     reloadDbusManager();
280     waitForRunningJobsFinish();
281     sendResetFailedToService();
282 }
283
284 void ServiceManager::unmaskService()
285 {
286     sendUnmaskToService();
287     reloadDbusManager();
288     waitForRunningJobsFinish();
289     sendResetFailedToService();
290 }