Imported Upstream version 1.37
[platform/upstream/connman.git] / tools / session-utils.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2011-2014  BMW Car IT GmbH.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27
28 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
29
30 #include <gdbus.h>
31
32 #include "../src/shared/util.h"
33 #include "session-test.h"
34
35 #define ENABLE_WRAPPER 1
36 #define PROPERTY_CHANGED                "PropertyChanged"
37
38 void util_quit_loop(struct test_fix *fix)
39 {
40         g_main_loop_quit(fix->main_loop);
41 }
42
43 static gboolean func_cb(gpointer data)
44 {
45         struct cb_data *cbd = data;
46         util_test_func_t cb = cbd->cb;
47         struct test_fix *fix = cbd->user_data;
48
49         (*cb)(fix);
50
51         return FALSE;
52 }
53
54 static void destroy_cb(gpointer data)
55 {
56         struct cb_data *cbd = data;
57         util_test_func_t cb = cbd->data;
58         struct test_fix *fix = cbd->user_data;
59
60         if (cb)
61                 (*cb)(fix);
62
63         g_free(cbd);
64 }
65
66 void util_call(struct test_fix *fix, util_test_func_t func,
67                 util_test_func_t destroy)
68 {
69         struct cb_data *cbd = cb_data_new(func, fix);
70         GSource *source;
71
72         cbd->data = destroy;
73
74         source = g_timeout_source_new(0);
75         g_source_set_callback(source, func_cb, cbd, destroy_cb);
76         g_source_attach(source, g_main_loop_get_context(fix->main_loop));
77         g_source_unref(source);
78 }
79
80 void util_idle_call(struct test_fix *fix, util_test_func_t func,
81                         util_test_func_t destroy)
82 {
83         struct cb_data *cbd = cb_data_new(func, fix);
84         GSource *source;
85
86         cbd->data = destroy;
87
88         source = g_idle_source_new();
89         g_source_set_callback(source, func_cb, cbd, destroy_cb);
90         g_source_attach(source, g_main_loop_get_context(fix->main_loop));
91         g_source_unref(source);
92 }
93
94 static void connman_died(DBusConnection *connection, void *user_data)
95 {
96         g_assert(FALSE);
97 }
98
99 static void manager_changed(struct test_fix *fix, DBusMessageIter *entry)
100 {
101         DBusMessageIter iter;
102         const char *key;
103         const char *value;
104         int type;
105
106         dbus_message_iter_get_basic(entry, &key);
107
108         LOG("key %s", key);
109
110         dbus_message_iter_next(entry);
111
112         dbus_message_iter_recurse(entry, &iter);
113
114         type = dbus_message_iter_get_arg_type(&iter);
115
116         if (type != DBUS_TYPE_STRING)
117                 return;
118
119         dbus_message_iter_get_basic(&iter, &value);
120
121         if (g_str_equal(key, "State")) {
122                 LOG("State %s", value);
123
124                 if (fix->manager.state)
125                         g_free(fix->manager.state);
126
127                 fix->manager.state = g_strdup(value);
128         }
129
130         if (fix->manager_changed)
131                 fix->manager_changed(fix);
132 }
133
134 static gboolean handle_manager_changed(DBusConnection *connection,
135                                 DBusMessage *message,
136                                 void *user_data)
137 {
138         struct test_fix *fix = user_data;
139
140         DBusMessageIter iter;
141
142         if (dbus_message_iter_init(message, &iter))
143                 manager_changed(fix, &iter);
144
145         return TRUE;
146 }
147
148 static struct test_fix *create_fix(void)
149 {
150         struct test_fix *fix;
151         DBusMessage *msg;
152
153         fix = g_new0(struct test_fix, 1);
154
155         fix->main_loop = g_main_loop_new(NULL, FALSE);
156         fix->main_connection = g_dbus_setup_private(DBUS_BUS_SYSTEM,
157                                                         NULL, NULL);
158         fix->watch = g_dbus_add_service_watch(fix->main_connection,
159                                                 CONNMAN_SERVICE,
160                                                 NULL,
161                                                 connman_died,
162                                                 NULL, NULL);
163         fix->manager_watch = g_dbus_add_signal_watch(fix->main_connection,
164                                                 CONNMAN_SERVICE, NULL,
165                                                 CONNMAN_MANAGER_INTERFACE,
166                                                 PROPERTY_CHANGED,
167                                                 handle_manager_changed,
168                                                 fix, NULL);
169
170         msg = manager_get_properties(fix->main_connection);
171         manager_parse_properties(msg, &fix->manager);
172         dbus_message_unref(msg);
173
174         return fix;
175 }
176
177 static void cleanup_fix(struct test_fix *fix)
178 {
179         g_dbus_remove_watch(fix->main_connection, fix->watch);
180         g_dbus_remove_watch(fix->main_connection, fix->manager_watch);
181         dbus_connection_close(fix->main_connection);
182         dbus_connection_unref(fix->main_connection);
183
184         g_main_loop_unref(fix->main_loop);
185
186         g_free(fix);
187 }
188
189 struct test_data_cb {
190         util_test_func_t func;
191         util_test_func_t setup;
192         util_test_func_t teardown;
193 };
194
195 static void run_test_cb(gpointer fixture, gconstpointer data)
196 {
197         const struct test_data_cb *cbd = data;
198         struct test_fix *fix;
199
200         fix = create_fix();
201
202         util_call(fix, cbd->setup, NULL);
203         g_main_loop_run(fix->main_loop);
204
205 #if ENABLE_WRAPPER
206         if (g_test_trap_fork(60 * 1000 * 1000, 0)) {
207                 util_call(fix, cbd->func, NULL);
208                 g_main_loop_run(fix->main_loop);
209                 exit(0);
210         }
211
212         g_test_trap_assert_passed();
213 #else
214         util_call(fix, cbd->func, NULL);
215         g_main_loop_run(fix->main_loop);
216 #endif
217
218         util_call(fix, cbd->teardown, NULL);
219         g_main_loop_run(fix->main_loop);
220
221         cleanup_fix(fix);
222 }
223
224 static void cleanup_test_cb(gpointer fixture, gconstpointer data)
225 {
226         struct test_data_cb *cbd = (void *)data;
227
228         g_free(cbd);
229 }
230
231 void util_test_add(const char *test_name, util_test_func_t test_func,
232                 util_test_func_t setup, util_test_func_t teardown)
233 {
234         struct test_data_cb *cbd = g_new0(struct test_data_cb, 1);
235
236         cbd->func = test_func;
237         cbd->setup = setup;
238         cbd->teardown = teardown;
239
240         g_test_add_vtable(test_name, 0, cbd, NULL, run_test_cb, cleanup_test_cb);
241 }
242
243 void util_session_create(struct test_fix *fix, unsigned int max_sessions)
244 {
245         unsigned int i;
246
247         fix->max_sessions = max_sessions;
248         fix->session = g_try_new0(struct test_session, max_sessions);
249
250         for (i = 0; i < max_sessions; i++) {
251                 fix->session[i].fix = fix;
252                 fix->session[i].info = g_try_new0(struct test_session_info, 1);
253                 fix->session[i].connection = g_dbus_setup_private(
254                                                 DBUS_BUS_SYSTEM, NULL, NULL);
255         }
256 }
257
258 void util_session_destroy(struct test_fix *fix)
259 {
260         unsigned int i;
261
262         for (i = 0; i < fix->max_sessions; i++) {
263                 dbus_connection_close(fix->session[i].connection);
264                 g_free(fix->session[i].info);
265         }
266
267         g_free(fix->session);
268 }
269
270 void util_session_init(struct test_session *session)
271 {
272         DBusMessage *msg;
273         DBusMessageIter iter;
274         const char *path;
275         int err;
276
277         err = session_notify_register(session, session->notify_path);
278         g_assert(err == 0);
279
280         msg = manager_create_session(session->connection,
281                                         session->info,
282                                         session->notify_path);
283         g_assert(msg);
284         dbus_message_iter_init(msg, &iter);
285
286         dbus_message_iter_get_basic(&iter, &path);
287         session->session_path = g_strdup(path);
288
289         dbus_message_unref(msg);
290 }
291
292 void util_session_cleanup(struct test_session *session)
293 {
294         DBusMessage *msg;
295         int err;
296
297         msg = manager_destroy_session(session->connection,
298                                         session->session_path);
299         g_assert(msg);
300         dbus_message_unref(msg);
301
302         err = session_notify_unregister(session,
303                                         session->notify_path);
304         g_assert(err == 0);
305
306         g_free(session->info->bearer);
307         g_free(session->info->name);
308         g_free(session->info->interface);
309         g_slist_foreach(session->info->allowed_bearers,
310                         bearer_info_cleanup, NULL);
311         g_slist_free(session->info->allowed_bearers);
312         g_free(session->info->allowed_interface);
313         g_free(session->info->context_identifier);
314
315         session->notify = NULL;
316         g_free(session->notify_path);
317         g_free(session->session_path);
318 }