dundee: Watch for signals only on DUNDEE_SERVICE
[framework/connectivity/connman.git] / unit / test-session.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2011  BWM CarIT GmbH. All rights reserved.
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 <stdio.h>
27
28 #include "gdbus/gdbus.h"
29
30 #include "test-connman.h"
31
32 enum test_session_state {
33         TEST_SESSION_STATE_0 = 0,
34         TEST_SESSION_STATE_1 = 1,
35         TEST_SESSION_STATE_2 = 2,
36         TEST_SESSION_STATE_3 = 3,
37 };
38
39 static enum test_session_state get_session_state(struct test_session *session)
40 {
41         return GPOINTER_TO_UINT(session->fix->user_data);
42 }
43
44 static void set_session_state(struct test_session *session,
45                                 enum test_session_state state)
46 {
47         session->fix->user_data = GUINT_TO_POINTER(state);
48 }
49
50 static struct test_session *get_session(struct test_session *session,
51                                         unsigned int index)
52 {
53         return &session->fix->session[index];
54 }
55
56 static gboolean test_session_create_no_notify(gpointer data)
57 {
58         struct test_fix *fix = data;
59         DBusMessage *msg;
60
61         util_session_create(fix, 1);
62
63         msg = manager_create_session(fix->session->connection,
64                                         fix->session->info, "/foo");
65         g_assert(msg != NULL);
66         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
67
68         dbus_message_unref(msg);
69
70         util_idle_call(fix, util_quit_loop, util_session_destroy);
71
72         return FALSE;
73 }
74
75 static gboolean test_session_destroy_no_notify(gpointer data)
76 {
77         struct test_fix *fix = data;
78         DBusMessage *msg;
79
80         util_session_create(fix, 1);
81
82         msg = manager_destroy_session(fix->session->connection, "/foo");
83         g_assert(msg == NULL);
84
85         util_idle_call(fix, util_quit_loop, util_session_destroy);
86
87         return FALSE;
88 }
89
90 static void test_session_create_notify(struct test_session *session)
91 {
92         LOG("session %p", session);
93
94         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
95 }
96
97 static gboolean test_session_create(gpointer data)
98 {
99         struct test_fix *fix = data;
100         struct test_session *session;
101         DBusMessage *msg;
102         int err;
103
104         util_session_create(fix, 1);
105         session = fix->session;
106
107         session->notify_path = "/foo";
108         session->notify = test_session_create_notify;
109
110         err = session_notify_register(session, session->notify_path);
111         g_assert(err == 0);
112
113         msg = manager_create_session(session->connection,
114                                         session->info,
115                                         session->notify_path);
116         g_assert(msg != NULL);
117         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
118
119         dbus_message_unref(msg);
120
121         return FALSE;
122 }
123
124 static gboolean test_session_create_destroy(gpointer data)
125 {
126         struct test_fix *fix = data;
127         struct test_session *session;
128
129         util_session_create(fix, 1);
130         session = fix->session;
131
132         session->notify_path = g_strdup("/foo");
133
134         util_session_init(fix->session);
135         util_session_cleanup(fix->session);
136
137         util_idle_call(fix, util_quit_loop, util_session_destroy);
138
139         return FALSE;
140 }
141
142 static gboolean test_session_create_already_exists(gpointer data)
143 {
144         struct test_fix *fix = data;
145         struct test_session *session0, *session1;
146         DBusMessage *msg;
147
148         util_session_create(fix, 2);
149         session0 = &fix->session[0];
150         session1 = &fix->session[1];
151
152         session0->notify_path = g_strdup("/foo");
153         session1->notify_path = session0->notify_path;
154
155         util_session_init(session0);
156
157         msg = manager_create_session(session1->connection,
158                                         session1->info,
159                                         session1->notify_path);
160         g_assert(msg == NULL);
161
162         util_session_cleanup(session0);
163
164         util_idle_call(fix, util_quit_loop, util_session_destroy);
165
166         return FALSE;
167 }
168
169 static void test_session_create_many_notify(struct test_session *session)
170 {
171         unsigned int nr;
172
173         LOG("session %p", session);
174
175         nr = GPOINTER_TO_UINT(session->fix->user_data);
176         nr--;
177         session->fix->user_data = GUINT_TO_POINTER(nr);
178
179         if (nr > 0)
180                 return;
181
182         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
183 }
184
185 static gboolean test_session_create_many(gpointer data)
186 {
187         struct test_fix *fix = data;
188         struct test_session *session;
189         unsigned int i, max;
190
191         max = 100;
192
193         fix->user_data = GUINT_TO_POINTER(max);
194
195         util_session_create(fix, max);
196
197         for (i = 0; i < max; i++) {
198                 session = &fix->session[i];
199
200                 session->notify_path = g_strdup_printf("/foo/%d", i);
201                 session->notify = test_session_create_many_notify;
202
203                 util_session_init(session);
204         }
205
206         return FALSE;
207 }
208
209 static void set_session_mode(struct test_fix *fix,
210                                         connman_bool_t enable)
211 {
212         DBusMessage *msg;
213
214         msg = manager_set_session_mode(fix->main_connection, enable);
215         g_assert(msg != NULL);
216         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
217
218         dbus_message_unref(msg);
219 }
220
221 static void test_session_connect_notify(struct test_session *session)
222 {
223         LOG("session %p state %d", session, session->info->state);
224
225         if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
226                 return;
227
228         util_session_cleanup(session);
229
230         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
231 }
232
233 static gboolean test_session_connect(gpointer data)
234 {
235         struct test_fix *fix = data;
236         struct test_session *session;
237         DBusMessage *msg;
238
239         util_session_create(fix, 1);
240         session = fix->session;
241
242         session->notify_path = g_strdup("/foo");
243         session->notify =  test_session_connect_notify;
244         util_session_init(session);
245
246         msg = session_connect(session->connection, session);
247         g_assert(msg != NULL);
248         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
249
250         dbus_message_unref(msg);
251
252         return FALSE;
253 }
254
255 static void test_session_disconnect_notify(struct test_session *session)
256 {
257         LOG("session %p state %d", session, session->info->state);
258
259         if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
260                 return;
261
262         util_session_cleanup(session);
263
264         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
265 }
266
267 static gboolean test_session_disconnect(gpointer data)
268 {
269         struct test_fix *fix = data;
270         struct test_session *session;
271         DBusMessage *msg;
272
273         util_session_create(fix, 1);
274         session = fix->session;
275
276         session->notify_path = g_strdup("/foo");
277         session->notify =  test_session_disconnect_notify;
278         util_session_init(session);
279
280         msg = session_disconnect(session->connection, session);
281         g_assert(msg != NULL);
282         dbus_message_unref(msg);
283
284         return FALSE;
285 }
286
287 static void test_session_connect_disconnect_notify(struct test_session *session)
288 {
289         enum test_session_state state = get_session_state(session);
290         enum test_session_state next_state = state;
291         DBusMessage *msg;
292
293         LOG("state %d session %p %s state %d", state, session,
294                 session->notify_path, session->info->state);
295
296         switch (state) {
297         case TEST_SESSION_STATE_0:
298                 if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
299                         next_state = TEST_SESSION_STATE_1;
300                 break;
301         case TEST_SESSION_STATE_1:
302                 if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
303                         next_state = TEST_SESSION_STATE_2;
304                 break;
305         case TEST_SESSION_STATE_2:
306                 if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
307                         next_state = TEST_SESSION_STATE_3;
308         default:
309                 break;
310         }
311
312         if (state == next_state)
313                 return;
314
315         set_session_state(session, next_state);
316
317         LOG("next_state %d", next_state);
318
319         switch (next_state) {
320         case TEST_SESSION_STATE_1:
321                 msg = session_connect(session->connection, session);
322                 g_assert(msg != NULL);
323                 dbus_message_unref(msg);
324                 return;
325         case TEST_SESSION_STATE_2:
326                 msg = session_disconnect(session->connection, session);
327                 g_assert(msg != NULL);
328                 dbus_message_unref(msg);
329                 return;
330         case TEST_SESSION_STATE_3:
331                 util_session_cleanup(session);
332                 util_idle_call(session->fix, util_quit_loop,
333                                 util_session_destroy);
334                 return;
335         default:
336                 return;
337         }
338 }
339
340 static gboolean test_session_connect_disconnect(gpointer data)
341 {
342         struct test_fix *fix = data;
343         struct test_session *session;
344
345         /*
346          * +-------------------+
347          * |       START       |
348          * +-------------------+
349          *   |
350          *   | connect foo
351          *   v
352          * +-------------------+
353          * |   FOO-CONNECTED   |
354          * +-------------------+
355          *  |
356          *  | disconnect foo
357          *  v
358          * +-------------------+
359          * |        END        |
360          * +-------------------+
361          */
362
363         util_session_create(fix, 1);
364         session = fix->session;
365
366         session->notify_path = g_strdup("/foo");
367         session->notify =  test_session_connect_disconnect_notify;
368
369         util_session_init(session);
370
371         set_session_state(session, TEST_SESSION_STATE_0);
372
373         return FALSE;
374 }
375
376 static void test_session_connect_free_ride_notify(struct test_session *session)
377 {
378         struct test_session *session0 = get_session(session, 0);
379         struct test_session *session1 = get_session(session, 1);
380         enum test_session_state state = get_session_state(session);
381         enum test_session_state next_state = state;
382         DBusMessage *msg;
383
384         LOG("state %d session %p %s state %d", state, session,
385                 session->notify_path, session->info->state);
386
387         switch (state) {
388         case TEST_SESSION_STATE_0:
389                 if (session0->info->state == CONNMAN_SESSION_STATE_DISCONNECTED
390                                 && session1->info->state ==
391                                         CONNMAN_SESSION_STATE_DISCONNECTED) {
392                         next_state = TEST_SESSION_STATE_1;
393                 }
394
395                 break;
396         case TEST_SESSION_STATE_1:
397                 if (session0->info->state >= CONNMAN_SESSION_STATE_CONNECTED &&
398                                 session1->info->state >=
399                                         CONNMAN_SESSION_STATE_CONNECTED) {
400                         next_state = TEST_SESSION_STATE_2;
401                 }
402
403                 break;
404         case TEST_SESSION_STATE_2:
405                 if (session0->info->state == CONNMAN_SESSION_STATE_DISCONNECTED
406                                 && session1->info->state ==
407                                         CONNMAN_SESSION_STATE_DISCONNECTED) {
408                         next_state = TEST_SESSION_STATE_3;
409                 }
410
411                 break;
412         case TEST_SESSION_STATE_3:
413
414                 return;
415         }
416
417         if (state == next_state)
418                 return;
419
420         set_session_state(session, next_state);
421
422         LOG("next_state %d", next_state);
423
424         switch (next_state) {
425         case TEST_SESSION_STATE_0:
426
427                 return;
428         case TEST_SESSION_STATE_1:
429                 msg = session_connect(session0->connection, session0);
430                 g_assert(msg != NULL);
431                 dbus_message_unref(msg);
432
433                 return;
434
435         case TEST_SESSION_STATE_2:
436                 msg = session_disconnect(session0->connection, session0);
437                 g_assert(msg != NULL);
438                 dbus_message_unref(msg);
439
440                 return;
441         case TEST_SESSION_STATE_3:
442                 util_session_cleanup(session0);
443                 util_session_cleanup(session1);
444
445                 util_idle_call(session0->fix, util_quit_loop,
446                                 util_session_destroy);
447
448                 return;
449         }
450 }
451
452 static gboolean test_session_connect_free_ride(gpointer data)
453 {
454         struct test_fix *fix = data;
455         struct test_session *session0, *session1;
456
457         /*
458          * +-------------------+
459          * |       START       |
460          * +-------------------+
461          *   |
462          *   | connect foo
463          *   v
464          * +-------------------+
465          * |   FOO-CONNECTED   |
466          * +-------------------+
467          *   |
468          *   | free-ride bar
469          *   v
470          * +-------------------+
471          * | FOO-BAR-CONNECTED |
472          * +-------------------+
473          *  |
474          *  | disconnect foo
475          *  v
476          * +-------------------+
477          * |        END        |
478          * +-------------------+
479          */
480
481         util_session_create(fix, 2);
482         session0 = &fix->session[0];
483         session1 = &fix->session[1];
484
485         session0->notify_path = g_strdup("/foo");
486         session1->notify_path = g_strdup("/bar");
487         session0->notify = test_session_connect_free_ride_notify;
488         session1->notify = test_session_connect_free_ride_notify;
489
490         util_session_init(session0);
491         util_session_init(session1);
492
493         set_session_state(session0, TEST_SESSION_STATE_0);
494
495         return FALSE;
496 }
497
498 static connman_bool_t is_online(struct test_fix *fix)
499 {
500         if (g_strcmp0(fix->manager.state, "online") == 0)
501                 return TRUE;
502
503         return FALSE;
504 }
505
506 static gboolean enable_session_mode(gpointer data)
507 {
508         struct test_fix *fix = data;
509
510         set_session_mode(fix, TRUE);
511
512         if (is_online(fix) == FALSE)
513                 util_idle_call(fix, util_quit_loop, NULL);
514
515         return FALSE;
516 }
517
518 static gboolean manager_state_changed(gpointer data)
519 {
520         struct test_fix *fix = data;
521
522         if (is_online(fix) == FALSE) {
523                 fix->manager_changed = NULL;
524                 util_idle_call(fix, util_quit_loop, NULL);
525         }
526
527         return FALSE;
528 }
529
530 static gboolean disable_session_mode(gpointer data)
531 {
532         struct test_fix *fix = data;
533
534         set_session_mode(fix, FALSE);
535
536         return FALSE;
537 }
538
539 static void setup_cb(struct test_fix *fix, gconstpointer data)
540 {
541         fix->manager_changed = manager_state_changed;
542
543         util_setup(fix, data);
544         util_call(fix, enable_session_mode, NULL);
545
546         g_main_loop_run(fix->main_loop);
547
548         fix->manager_changed = NULL;
549 }
550
551 static void teardown_cb(struct test_fix *fix, gconstpointer data)
552 {
553         util_call(fix, disable_session_mode, NULL);
554         util_idle_call(fix, util_quit_loop, NULL);
555
556         g_main_loop_run(fix->main_loop);
557
558         util_teardown(fix, data);
559 }
560
561 int main(int argc, char *argv[])
562 {
563         g_test_init(&argc, &argv, NULL);
564
565         util_test_add("/manager/session create no notify",
566                 test_session_create_no_notify, setup_cb, teardown_cb);
567         util_test_add("/manager/session destroy no notify",
568                 test_session_destroy_no_notify, setup_cb, teardown_cb);
569         util_test_add("/manager/session create",
570                 test_session_create, setup_cb, teardown_cb);
571         util_test_add("/manager/session create destroy",
572                 test_session_create_destroy, setup_cb, teardown_cb);
573         util_test_add("/manager/session create already exists",
574                 test_session_create_already_exists, setup_cb, teardown_cb);
575         util_test_add("/manager/session create many",
576                 test_session_create_many, setup_cb, teardown_cb);
577
578         util_test_add("/session/connect",
579                 test_session_connect, setup_cb, teardown_cb);
580         util_test_add("/session/disconnect",
581                 test_session_disconnect, setup_cb, teardown_cb);
582         util_test_add("/session/connect disconnect",
583                 test_session_connect_disconnect, setup_cb, teardown_cb);
584         util_test_add("/session/connect free-ride",
585                 test_session_connect_free_ride, setup_cb, teardown_cb);
586
587         return g_test_run();
588 }