Some synchronizations
[platform/core/security/vasum.git] / tests / unit_tests / client / ut-client.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Mateusz Malicki <m.malicki2@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19
20 /**
21  * @file
22  * @author  Mateusz Malicki (m.malicki2@samsung.com)
23  * @brief   Unit tests of the client C API
24  */
25
26 #include <config.hpp>
27 #include "ut.hpp"
28 #include <vasum-client.h>
29
30 #include "utils/latch.hpp"
31 #include "utils/scoped-dir.hpp"
32 #include "zones-manager.hpp"
33 #include "zone-dbus-definitions.hpp"
34
35 #include <map>
36 #include <string>
37 #include <utility>
38 #include <memory>
39 #include <set>
40 #include <tuple>
41 #include <utility>
42
43 using namespace vasum;
44 using namespace vasum::utils;
45
46 namespace {
47
48 const std::string TEST_DBUS_CONFIG_PATH =
49     VSM_TEST_CONFIG_INSTALL_DIR "/client/ut-client/test-dbus-daemon.conf";
50 const std::string ZONES_PATH = "/tmp/ut-zones"; // the same as in daemon.conf
51
52 struct Loop {
53     Loop()
54     {
55         vsm_start_glib_loop();
56     }
57     ~Loop()
58     {
59         vsm_stop_glib_loop();
60     }
61 };
62
63 struct Fixture {
64     Loop loop;
65     utils::ScopedDir mZonesPathGuard;
66     utils::ScopedDir mRunGuard;
67
68     ZonesManager cm;
69
70     Fixture()
71         : mZonesPathGuard(ZONES_PATH)
72         , mRunGuard("/tmp/ut-run")
73         , cm(TEST_DBUS_CONFIG_PATH)
74     {
75         cm.startAll();
76     }
77 };
78
79 const int EVENT_TIMEOUT = 5000; ///< ms
80 const std::map<std::string, std::string> EXPECTED_DBUSES_STARTED = {
81     {
82         "ut-zones-manager-console1-dbus",
83         "unix:path=/tmp/ut-run/ut-zones-manager-console1-dbus/dbus/system_bus_socket"
84     },
85     {
86         "ut-zones-manager-console2-dbus",
87         "unix:path=/tmp/ut-run/ut-zones-manager-console2-dbus/dbus/system_bus_socket"
88     },
89     {
90         "ut-zones-manager-console3-dbus",
91         "unix:path=/tmp/ut-run/ut-zones-manager-console3-dbus/dbus/system_bus_socket"
92     }
93 };
94
95 void convertDictToMap(VsmArrayString keys,
96                       VsmArrayString values,
97                       std::map<std::string, std::string>& ret)
98 {
99     VsmArrayString iKeys;
100     VsmArrayString iValues;
101     for (iKeys = keys, iValues = values; *iKeys && *iValues; iKeys++, iValues++) {
102         ret.insert(std::make_pair(*iKeys, *iValues));
103     }
104 }
105
106 void convertArrayToSet(VsmArrayString values, std::set<std::string>& ret)
107 {
108     for (VsmArrayString iValues = values; *iValues; iValues++) {
109         ret.insert(*iValues);
110     }
111 }
112
113 int getArrayStringLength(VsmArrayString astring, int max_len = -1)
114 {
115     int i = 0;
116     for (i = 0; astring[i];  i++) {
117         if (i == max_len) {
118             return max_len;
119         }
120     }
121     return i;
122 }
123
124 } // namespace
125
126 // make nice BOOST_*_EQUAL output
127 // (does not work inside anonymous namespace)
128 std::ostream& operator<<(std::ostream& out, VsmStatus status)
129 {
130     switch(status) {
131     case VSMCLIENT_CUSTOM_ERROR: return out << "CUSTOM_ERROR";
132     case VSMCLIENT_IO_ERROR: return out << "IO_ERROR";
133     case VSMCLIENT_OPERATION_FAILED: return out << "OPERATION_FAILED";
134     case VSMCLIENT_INVALID_ARGUMENT: return out << "INVALID_ARGUMENT";
135     case VSMCLIENT_OTHER_ERROR: return out << "OTHER_ERROR";
136     case VSMCLIENT_SUCCESS: return out << "SUCCESS";
137     default: return out << "UNKNOWN(" << (int)status << ")";
138     };
139 }
140
141 BOOST_FIXTURE_TEST_SUITE(ClientSuite, Fixture)
142
143 BOOST_AUTO_TEST_CASE(NotRunningServerTest)
144 {
145     cm.stopAll();
146
147     VsmClient client = vsm_client_create();
148     VsmStatus status = vsm_connect_custom(client,
149                                           EXPECTED_DBUSES_STARTED.begin()->second.c_str());
150     BOOST_CHECK_EQUAL(VSMCLIENT_IO_ERROR, status);
151     vsm_client_free(client);
152 }
153
154 BOOST_AUTO_TEST_CASE(GetZoneDbusesTest)
155 {
156     VsmClient client = vsm_client_create();
157     VsmStatus status = vsm_connect(client);
158     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
159     VsmArrayString keys, values;
160     status = vsm_get_zone_dbuses(client, &keys, &values);
161     //TODO: Clean up if BOOST_REQUIRE_EQUAL fail (remove client). Same in other client tests.
162     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
163
164     BOOST_CHECK_EQUAL(getArrayStringLength(keys, EXPECTED_DBUSES_STARTED.size() + 1u),
165                       EXPECTED_DBUSES_STARTED.size());
166     BOOST_CHECK_EQUAL(getArrayStringLength(values, EXPECTED_DBUSES_STARTED.size() + 1u),
167                       EXPECTED_DBUSES_STARTED.size());
168
169     std::map<std::string, std::string> zones;
170     convertDictToMap(keys, values, zones);
171     BOOST_CHECK(zones == EXPECTED_DBUSES_STARTED);
172     vsm_array_string_free(keys);
173     vsm_array_string_free(values);
174     vsm_client_free(client);
175 }
176
177 BOOST_AUTO_TEST_CASE(GetZoneIdsTest)
178 {
179     VsmClient client = vsm_client_create();
180     VsmStatus status = vsm_connect(client);
181     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
182     VsmArrayString values;
183     status = vsm_get_zone_ids(client, &values);
184     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
185     BOOST_CHECK_EQUAL(getArrayStringLength(values, EXPECTED_DBUSES_STARTED.size() + 1u),
186                       EXPECTED_DBUSES_STARTED.size());
187
188     std::set<std::string> zones;
189     convertArrayToSet(values, zones);
190
191     for (const auto& zone : zones) {
192         BOOST_CHECK(EXPECTED_DBUSES_STARTED.find(zone) != EXPECTED_DBUSES_STARTED.cend());
193     }
194     vsm_array_string_free(values);
195     vsm_client_free(client);
196 }
197
198 BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest)
199 {
200     VsmClient client = vsm_client_create();
201     VsmStatus status = vsm_connect(client);
202     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
203     VsmString zone;
204     status = vsm_get_active_zone_id(client, &zone);
205     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
206
207     BOOST_CHECK_EQUAL(zone, cm.getRunningForegroundZoneId());
208
209     vsm_string_free(zone);
210     vsm_client_free(client);
211 }
212
213 BOOST_AUTO_TEST_CASE(SetActiveZoneTest)
214 {
215     const std::string newActiveZoneId = "ut-zones-manager-console2-dbus";
216
217     BOOST_REQUIRE_NE(newActiveZoneId, cm.getRunningForegroundZoneId());
218
219     VsmClient client = vsm_client_create();
220     VsmStatus status = vsm_connect(client);
221     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
222     status = vsm_set_active_zone(client, newActiveZoneId.c_str());
223     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
224     BOOST_CHECK_EQUAL(newActiveZoneId, cm.getRunningForegroundZoneId());
225     vsm_client_free(client);
226 }
227
228 BOOST_AUTO_TEST_CASE(CreateZoneTest)
229 {
230     const std::string newActiveZoneId = "";
231
232     VsmClient client = vsm_client_create();
233     VsmStatus status = vsm_connect(client);
234     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
235     status = vsm_create_zone(client, newActiveZoneId.c_str(), NULL);
236     BOOST_REQUIRE_EQUAL(VSMCLIENT_CUSTOM_ERROR, status);
237     vsm_client_free(client);
238 }
239
240 BOOST_AUTO_TEST_CASE(StartShutdownZoneTest)
241 {
242     const std::string newActiveZoneId = "ut-zones-manager-console1-dbus";
243
244     VsmClient client = vsm_client_create();
245     VsmStatus status = vsm_connect(client);
246     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
247     status = vsm_shutdown_zone(client, newActiveZoneId.c_str());
248     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
249     status = vsm_start_zone(client, newActiveZoneId.c_str());
250     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
251     vsm_client_free(client);
252 }
253
254 BOOST_AUTO_TEST_CASE(LockUnlockZoneTest)
255 {
256     const std::string newActiveZoneId = "ut-zones-manager-console2-dbus";
257
258     VsmClient client = vsm_client_create();
259     VsmStatus status = vsm_connect(client);
260     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
261     status = vsm_lock_zone(client, newActiveZoneId.c_str());
262     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
263     status = vsm_unlock_zone(client, newActiveZoneId.c_str());
264     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
265     vsm_client_free(client);
266 }
267
268 BOOST_AUTO_TEST_CASE(FileMoveRequestTest)
269 {
270     const std::string path = "/tmp/fake_path";
271     const std::string secondZone = "fake_zone";
272
273     VsmClient client = vsm_client_create();
274     VsmStatus status = vsm_connect_custom(client, EXPECTED_DBUSES_STARTED.begin()->second.c_str());
275     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
276     status = vsm_file_move_request(client, secondZone.c_str(), path.c_str());
277     BOOST_REQUIRE_EQUAL(VSMCLIENT_CUSTOM_ERROR, status);
278     BOOST_REQUIRE_EQUAL(api::zone::FILE_MOVE_DESTINATION_NOT_FOUND,
279                         vsm_get_status_message(client));
280     vsm_client_free(client);
281 }
282
283 BOOST_AUTO_TEST_CASE(NotificationTest)
284 {
285     const std::string MSG_CONTENT = "msg";
286     const std::string MSG_APP = "app";
287
288     struct CallbackData {
289         Latch signalReceivedLatch;
290         std::vector< std::tuple<std::string, std::string, std::string> > receivedSignalMsg;
291     };
292
293     auto callback = [](const char* zone,
294                        const char* application,
295                        const char* message,
296     void* data) {
297         CallbackData& callbackData = *reinterpret_cast<CallbackData*>(data);
298         callbackData.receivedSignalMsg.push_back(std::make_tuple(zone, application, message));
299         callbackData.signalReceivedLatch.set();
300     };
301
302     CallbackData callbackData;
303     std::map<std::string, VsmClient> clients;
304     for (const auto& it : EXPECTED_DBUSES_STARTED) {
305         VsmClient client = vsm_client_create();
306         VsmStatus status = vsm_connect_custom(client, it.second.c_str());
307         BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
308         clients[it.first] = client;
309     }
310     for (auto& client : clients) {
311         VsmStatus status = vsm_add_notification_callback(client.second,
312                                                          callback,
313                                                          &callbackData,
314                                                          NULL);
315         BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
316     }
317     for (auto& client : clients) {
318         VsmStatus status = vsm_notify_active_zone(client.second,
319                                                        MSG_APP.c_str(),
320                                                        MSG_CONTENT.c_str());
321         BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
322     }
323
324     BOOST_CHECK(callbackData.signalReceivedLatch.waitForN(clients.size() - 1u, EVENT_TIMEOUT));
325     BOOST_CHECK(callbackData.signalReceivedLatch.empty());
326
327     for (const auto& msg : callbackData.receivedSignalMsg) {
328         BOOST_CHECK(clients.count(std::get<0>(msg)) > 0);
329         BOOST_CHECK_EQUAL(std::get<1>(msg), MSG_APP);
330         BOOST_CHECK_EQUAL(std::get<2>(msg), MSG_CONTENT);
331     }
332
333     for (auto& client : clients) {
334         vsm_client_free(client.second);
335     }
336 }
337
338 BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest1)
339 {
340     VsmClient client = vsm_client_create();
341     VsmString zone;
342     VsmStatus status = vsm_lookup_zone_by_pid(client, 1, &zone);
343     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
344
345     BOOST_CHECK_EQUAL(zone, std::string("host"));
346
347     vsm_string_free(zone);
348     vsm_client_free(client);
349 }
350
351 BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest2)
352 {
353     std::set<std::string> ids;
354
355     VsmClient client = vsm_client_create();
356     for (int n = 0; n < 100000; ++n) {
357         VsmString zone;
358         VsmStatus status = vsm_lookup_zone_by_pid(client, n, &zone);
359         if (status == VSMCLIENT_SUCCESS) {
360             ids.insert(zone);
361             vsm_string_free(zone);
362         } else {
363             BOOST_WARN_MESSAGE(status == VSMCLIENT_INVALID_ARGUMENT, vsm_get_status_message(client));
364         }
365     }
366     vsm_client_free(client);
367
368     BOOST_CHECK(ids.count("host") == 1);
369
370     for (const auto& dbus : EXPECTED_DBUSES_STARTED) {
371         BOOST_CHECK(ids.count(dbus.first) == 1);
372     }
373 }
374
375 BOOST_AUTO_TEST_CASE(GrantRevokeTest)
376 {
377     const std::string zoneId = "ut-zones-manager-console2-dbus";
378     const std::string dev = "tty3";
379
380     VsmClient client = vsm_client_create();
381     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_connect(client));
382
383     BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_grant_device(client, zoneId.c_str(), dev.c_str(), 0));
384     BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_revoke_device(client, zoneId.c_str(), dev.c_str()));
385
386     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_lock_zone(client, zoneId.c_str()));
387     BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_grant_device(client, zoneId.c_str(), dev.c_str(), 0));
388     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_unlock_zone(client, zoneId.c_str()));
389
390     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_shutdown_zone(client, zoneId.c_str()));
391     BOOST_CHECK_EQUAL(VSMCLIENT_CUSTOM_ERROR, vsm_grant_device(client, zoneId.c_str(), dev.c_str(), 0));
392     BOOST_CHECK_EQUAL(VSMCLIENT_CUSTOM_ERROR, vsm_revoke_device(client, zoneId.c_str(), dev.c_str()));
393
394     vsm_client_free(client);
395 }
396
397 BOOST_AUTO_TEST_SUITE_END()