9536ccbc6df6358ef1104e0c0dfb1abe795c6625
[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     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
162
163     BOOST_CHECK_EQUAL(getArrayStringLength(keys, EXPECTED_DBUSES_STARTED.size() + 1u),
164                       EXPECTED_DBUSES_STARTED.size());
165     BOOST_CHECK_EQUAL(getArrayStringLength(values, EXPECTED_DBUSES_STARTED.size() + 1u),
166                       EXPECTED_DBUSES_STARTED.size());
167
168     std::map<std::string, std::string> zones;
169     convertDictToMap(keys, values, zones);
170     BOOST_CHECK(zones == EXPECTED_DBUSES_STARTED);
171     vsm_array_string_free(keys);
172     vsm_array_string_free(values);
173     vsm_client_free(client);
174 }
175
176 BOOST_AUTO_TEST_CASE(GetZoneIdsTest)
177 {
178     VsmClient client = vsm_client_create();
179     VsmStatus status = vsm_connect(client);
180     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
181     VsmArrayString values;
182     status = vsm_get_zone_ids(client, &values);
183     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
184     BOOST_CHECK_EQUAL(getArrayStringLength(values, EXPECTED_DBUSES_STARTED.size() + 1u),
185                       EXPECTED_DBUSES_STARTED.size());
186
187     std::set<std::string> zones;
188     convertArrayToSet(values, zones);
189
190     for (const auto& zone : zones) {
191         BOOST_CHECK(EXPECTED_DBUSES_STARTED.find(zone) != EXPECTED_DBUSES_STARTED.cend());
192     }
193     vsm_array_string_free(values);
194     vsm_client_free(client);
195 }
196
197 BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest)
198 {
199     VsmClient client = vsm_client_create();
200     VsmStatus status = vsm_connect(client);
201     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
202     VsmString zone;
203     status = vsm_get_active_zone_id(client, &zone);
204     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
205
206     BOOST_CHECK_EQUAL(zone, cm.getRunningForegroundZoneId());
207
208     vsm_string_free(zone);
209     vsm_client_free(client);
210 }
211
212 BOOST_AUTO_TEST_CASE(SetActiveZoneTest)
213 {
214     const std::string newActiveZoneId = "ut-zones-manager-console2-dbus";
215
216     BOOST_REQUIRE_NE(newActiveZoneId, cm.getRunningForegroundZoneId());
217
218     VsmClient client = vsm_client_create();
219     VsmStatus status = vsm_connect(client);
220     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
221     status = vsm_set_active_zone(client, newActiveZoneId.c_str());
222     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
223     BOOST_CHECK_EQUAL(newActiveZoneId, cm.getRunningForegroundZoneId());
224     vsm_client_free(client);
225 }
226
227 BOOST_AUTO_TEST_CASE(CreateZoneTest)
228 {
229     const std::string newActiveZoneId = "";
230
231     VsmClient client = vsm_client_create();
232     VsmStatus status = vsm_connect(client);
233     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
234     status = vsm_create_zone(client, newActiveZoneId.c_str(), NULL);
235     BOOST_REQUIRE_EQUAL(VSMCLIENT_CUSTOM_ERROR, status);
236     vsm_client_free(client);
237 }
238
239 BOOST_AUTO_TEST_CASE(StartShutdownZoneTest)
240 {
241     const std::string newActiveZoneId = "ut-zones-manager-console1-dbus";
242
243     VsmClient client = vsm_client_create();
244     VsmStatus status = vsm_connect(client);
245     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
246     status = vsm_shutdown_zone(client, newActiveZoneId.c_str());
247     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
248     status = vsm_start_zone(client, newActiveZoneId.c_str());
249     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
250     vsm_client_free(client);
251 }
252
253 BOOST_AUTO_TEST_CASE(LockUnlockZoneTest)
254 {
255     const std::string newActiveZoneId = "ut-zones-manager-console2-dbus";
256
257     VsmClient client = vsm_client_create();
258     VsmStatus status = vsm_connect(client);
259     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
260     status = vsm_lock_zone(client, newActiveZoneId.c_str());
261     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
262     status = vsm_unlock_zone(client, newActiveZoneId.c_str());
263     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
264     vsm_client_free(client);
265 }
266
267 BOOST_AUTO_TEST_CASE(FileMoveRequestTest)
268 {
269     const std::string path = "/tmp/fake_path";
270     const std::string secondZone = "fake_zone";
271
272     VsmClient client = vsm_client_create();
273     VsmStatus status = vsm_connect_custom(client, EXPECTED_DBUSES_STARTED.begin()->second.c_str());
274     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
275     status = vsm_file_move_request(client, secondZone.c_str(), path.c_str());
276     BOOST_REQUIRE_EQUAL(VSMCLIENT_CUSTOM_ERROR, status);
277     BOOST_REQUIRE_EQUAL(api::zone::FILE_MOVE_DESTINATION_NOT_FOUND,
278                         vsm_get_status_message(client));
279     vsm_client_free(client);
280 }
281
282 BOOST_AUTO_TEST_CASE(NotificationTest)
283 {
284     const std::string MSG_CONTENT = "msg";
285     const std::string MSG_APP = "app";
286
287     struct CallbackData {
288         Latch signalReceivedLatch;
289         std::vector< std::tuple<std::string, std::string, std::string> > receivedSignalMsg;
290     };
291
292     auto callback = [](const char* zone,
293                        const char* application,
294                        const char* message,
295     void* data) {
296         CallbackData& callbackData = *reinterpret_cast<CallbackData*>(data);
297         callbackData.receivedSignalMsg.push_back(std::make_tuple(zone, application, message));
298         callbackData.signalReceivedLatch.set();
299     };
300
301     CallbackData callbackData;
302     std::map<std::string, VsmClient> clients;
303     for (const auto& it : EXPECTED_DBUSES_STARTED) {
304         VsmClient client = vsm_client_create();
305         VsmStatus status = vsm_connect_custom(client, it.second.c_str());
306         BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
307         clients[it.first] = client;
308     }
309     for (auto& client : clients) {
310         VsmStatus status = vsm_add_notification_callback(client.second,
311                                                          callback,
312                                                          &callbackData,
313                                                          NULL);
314         BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
315     }
316     for (auto& client : clients) {
317         VsmStatus status = vsm_notify_active_zone(client.second,
318                                                        MSG_APP.c_str(),
319                                                        MSG_CONTENT.c_str());
320         BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
321     }
322
323     BOOST_CHECK(callbackData.signalReceivedLatch.waitForN(clients.size() - 1u, EVENT_TIMEOUT));
324     BOOST_CHECK(callbackData.signalReceivedLatch.empty());
325
326     for (const auto& msg : callbackData.receivedSignalMsg) {
327         BOOST_CHECK(clients.count(std::get<0>(msg)) > 0);
328         BOOST_CHECK_EQUAL(std::get<1>(msg), MSG_APP);
329         BOOST_CHECK_EQUAL(std::get<2>(msg), MSG_CONTENT);
330     }
331
332     for (auto& client : clients) {
333         vsm_client_free(client.second);
334     }
335 }
336
337 BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest1)
338 {
339     VsmClient client = vsm_client_create();
340     VsmString zone;
341     VsmStatus status = vsm_lookup_zone_by_pid(client, 1, &zone);
342     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
343
344     BOOST_CHECK_EQUAL(zone, std::string("host"));
345
346     vsm_string_free(zone);
347     vsm_client_free(client);
348 }
349
350 BOOST_AUTO_TEST_CASE(GetZoneIdByPidTest2)
351 {
352     std::set<std::string> ids;
353
354     VsmClient client = vsm_client_create();
355     for (int n = 0; n < 100000; ++n) {
356         VsmString zone;
357         VsmStatus status = vsm_lookup_zone_by_pid(client, n, &zone);
358         if (status == VSMCLIENT_SUCCESS) {
359             ids.insert(zone);
360             vsm_string_free(zone);
361         } else {
362             BOOST_WARN_MESSAGE(status == VSMCLIENT_INVALID_ARGUMENT, vsm_get_status_message(client));
363         }
364     }
365     vsm_client_free(client);
366
367     BOOST_CHECK(ids.count("host") == 1);
368
369     for (const auto& dbus : EXPECTED_DBUSES_STARTED) {
370         BOOST_CHECK(ids.count(dbus.first) == 1);
371     }
372 }
373
374 BOOST_AUTO_TEST_CASE(GrantRevokeTest)
375 {
376     const std::string zoneId = "ut-zones-manager-console2-dbus";
377     const std::string dev = "tty3";
378
379     VsmClient client = vsm_client_create();
380     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_connect(client));
381
382     BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_grant_device(client, zoneId.c_str(), dev.c_str(), 0));
383     BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_revoke_device(client, zoneId.c_str(), dev.c_str()));
384
385     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_lock_zone(client, zoneId.c_str()));
386     BOOST_CHECK_EQUAL(VSMCLIENT_SUCCESS, vsm_grant_device(client, zoneId.c_str(), dev.c_str(), 0));
387     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_unlock_zone(client, zoneId.c_str()));
388
389     BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, vsm_shutdown_zone(client, zoneId.c_str()));
390     BOOST_CHECK_EQUAL(VSMCLIENT_CUSTOM_ERROR, vsm_grant_device(client, zoneId.c_str(), dev.c_str(), 0));
391     BOOST_CHECK_EQUAL(VSMCLIENT_CUSTOM_ERROR, vsm_revoke_device(client, zoneId.c_str(), dev.c_str()));
392
393     vsm_client_free(client);
394 }
395
396 BOOST_AUTO_TEST_SUITE_END()