DA: Skip initializing failed_bssids list when eapol failure case
[platform/upstream/connman.git] / tools / session-test.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2011  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 <stdio.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <sys/types.h>
30
31 #include <gdbus.h>
32
33 #include "session-test.h"
34
35 #define POLICYDIR STORAGEDIR "/session_policy_local"
36
37 enum test_session_state {
38         TEST_SESSION_STATE_0 = 0,
39         TEST_SESSION_STATE_1 = 1,
40         TEST_SESSION_STATE_2 = 2,
41         TEST_SESSION_STATE_3 = 3,
42 };
43
44 static enum test_session_state get_session_state(struct test_session *session)
45 {
46         return GPOINTER_TO_UINT(session->fix->user_data);
47 }
48
49 static void set_session_state(struct test_session *session,
50                                 enum test_session_state state)
51 {
52         session->fix->user_data = GUINT_TO_POINTER(state);
53 }
54
55 static struct test_session *get_session(struct test_session *session,
56                                         unsigned int index)
57 {
58         return &session->fix->session[index];
59 }
60
61 static void test_session_create_no_notify(struct test_fix *fix)
62 {
63         DBusMessage *msg;
64
65         util_session_create(fix, 1);
66
67         msg = manager_create_session(fix->session->connection,
68                                         fix->session->info, "/foo");
69         g_assert(msg);
70         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
71
72         dbus_message_unref(msg);
73
74         util_idle_call(fix, util_quit_loop, util_session_destroy);
75 }
76
77 static void test_session_destroy_no_notify(struct test_fix *fix)
78 {
79         DBusMessage *msg;
80
81         util_session_create(fix, 1);
82
83         msg = manager_destroy_session(fix->session->connection, "/foo");
84         g_assert(!msg);
85
86         util_idle_call(fix, util_quit_loop, util_session_destroy);
87 }
88
89 static void test_session_create_notify(struct test_session *session)
90 {
91         LOG("session %p", session);
92
93         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
94 }
95
96 static void test_session_create(struct test_fix *fix)
97 {
98         struct test_session *session;
99         DBusMessage *msg;
100         int err;
101
102         util_session_create(fix, 1);
103         session = fix->session;
104
105         session->notify_path = "/foo";
106         session->notify = test_session_create_notify;
107
108         err = session_notify_register(session, session->notify_path);
109         g_assert(err == 0);
110
111         msg = manager_create_session(session->connection,
112                                         session->info,
113                                         session->notify_path);
114         g_assert(msg);
115         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
116
117         dbus_message_unref(msg);
118 }
119
120 static void test_session_create_destroy(struct test_fix *fix)
121 {
122         struct test_session *session;
123
124         util_session_create(fix, 1);
125         session = fix->session;
126
127         session->notify_path = g_strdup("/foo");
128
129         util_session_init(fix->session);
130         util_session_cleanup(fix->session);
131
132         util_idle_call(fix, util_quit_loop, util_session_destroy);
133 }
134
135 static void test_session_create_dup_notification(struct test_fix *fix)
136 {
137         struct test_session *session0, *session1;
138         DBusMessage *msg;
139
140         util_session_create(fix, 2);
141         session0 = &fix->session[0];
142         session1 = &fix->session[1];
143
144         session0->notify_path = g_strdup("/foo");
145         session1->notify_path = session0->notify_path;
146
147         util_session_init(session0);
148
149         msg = manager_create_session(session1->connection,
150                                         session1->info,
151                                         session1->notify_path);
152         g_assert(msg);
153
154         util_session_cleanup(session0);
155
156         util_idle_call(fix, util_quit_loop, util_session_destroy);
157 }
158
159 static void test_session_create_many_notify(struct test_session *session)
160 {
161         unsigned int nr;
162
163         LOG("session %p", session);
164
165         nr = GPOINTER_TO_UINT(session->fix->user_data);
166         nr--;
167         session->fix->user_data = GUINT_TO_POINTER(nr);
168
169         if (nr > 0)
170                 return;
171
172         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
173 }
174
175 static void test_session_create_many(struct test_fix *fix)
176 {
177         struct test_session *session;
178         unsigned int i, max;
179
180         max = 100;
181
182         fix->user_data = GUINT_TO_POINTER(max);
183
184         util_session_create(fix, max);
185
186         for (i = 0; i < max; i++) {
187                 session = &fix->session[i];
188
189                 session->notify_path = g_strdup_printf("/foo/%d", i);
190                 session->notify = test_session_create_many_notify;
191
192                 util_session_init(session);
193         }
194 }
195
196 static void set_session_mode(struct test_fix *fix,
197                                         bool enable)
198 {
199         DBusMessage *msg;
200
201         msg = manager_set_session_mode(fix->main_connection, enable);
202         g_assert(msg);
203         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
204
205         dbus_message_unref(msg);
206 }
207
208 static void test_session_connect_notify(struct test_session *session)
209 {
210         LOG("session %p state %d", session, session->info->state);
211
212         if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
213                 return;
214
215         util_session_cleanup(session);
216
217         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
218 }
219
220 static void test_session_connect(struct test_fix *fix)
221 {
222         struct test_session *session;
223         DBusMessage *msg;
224
225         util_session_create(fix, 1);
226         session = fix->session;
227
228         session->notify_path = g_strdup("/foo");
229         session->notify =  test_session_connect_notify;
230         util_session_init(session);
231
232         msg = session_connect(session->connection, session);
233         g_assert(msg);
234         g_assert(dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR);
235
236         dbus_message_unref(msg);
237 }
238
239 static void test_session_disconnect_notify(struct test_session *session)
240 {
241         LOG("session %p state %d", session, session->info->state);
242
243         if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
244                 return;
245
246         util_session_cleanup(session);
247
248         util_idle_call(session->fix, util_quit_loop, util_session_destroy);
249 }
250
251 static void test_session_disconnect(struct test_fix *fix)
252 {
253         struct test_session *session;
254         DBusMessage *msg;
255
256         util_session_create(fix, 1);
257         session = fix->session;
258
259         session->notify_path = g_strdup("/foo");
260         session->notify =  test_session_disconnect_notify;
261         util_session_init(session);
262
263         msg = session_disconnect(session->connection, session);
264         g_assert(msg);
265         dbus_message_unref(msg);
266 }
267
268 static void test_session_connect_disconnect_notify(struct test_session *session)
269 {
270         enum test_session_state state = get_session_state(session);
271         enum test_session_state next_state = state;
272         DBusMessage *msg;
273
274         LOG("state %d session %p %s state %d", state, session,
275                 session->notify_path, session->info->state);
276
277         switch (state) {
278         case TEST_SESSION_STATE_0:
279                 if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
280                         next_state = TEST_SESSION_STATE_1;
281                 if (session->info->state == CONNMAN_SESSION_STATE_CONNECTED) {
282                         LOG("state was already connected, continuing");
283                         next_state = TEST_SESSION_STATE_2;
284                 }
285                 break;
286         case TEST_SESSION_STATE_1:
287                 if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
288                         next_state = TEST_SESSION_STATE_2;
289                 break;
290         case TEST_SESSION_STATE_2:
291                 if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
292                         next_state = TEST_SESSION_STATE_3;
293         default:
294                 break;
295         }
296
297         if (state == next_state)
298                 return;
299
300         set_session_state(session, next_state);
301
302         LOG("next_state %d", next_state);
303
304         switch (next_state) {
305         case TEST_SESSION_STATE_1:
306                 msg = session_connect(session->connection, session);
307                 g_assert(msg);
308                 dbus_message_unref(msg);
309                 return;
310         case TEST_SESSION_STATE_2:
311                 msg = session_disconnect(session->connection, session);
312                 g_assert(msg);
313                 dbus_message_unref(msg);
314                 return;
315         case TEST_SESSION_STATE_3:
316                 util_session_cleanup(session);
317                 util_idle_call(session->fix, util_quit_loop,
318                                 util_session_destroy);
319                 return;
320         default:
321                 return;
322         }
323 }
324
325 static void test_session_connect_disconnect(struct test_fix *fix)
326 {
327         struct test_session *session;
328
329         /*
330          * +-------------------+
331          * |       START       |
332          * +-------------------+
333          *   |
334          *   | connect foo
335          *   v
336          * +-------------------+
337          * |   FOO-CONNECTED   |
338          * +-------------------+
339          *  |
340          *  | disconnect foo
341          *  v
342          * +-------------------+
343          * |        END        |
344          * +-------------------+
345          */
346
347         util_session_create(fix, 1);
348         session = fix->session;
349
350         session->notify_path = g_strdup("/foo");
351         session->notify =  test_session_connect_disconnect_notify;
352
353         util_session_init(session);
354
355         set_session_state(session, TEST_SESSION_STATE_0);
356 }
357
358 static void test_session_connect_free_ride_notify(struct test_session *session)
359 {
360         struct test_session *session0 = get_session(session, 0);
361         struct test_session *session1 = get_session(session, 1);
362         enum test_session_state state = get_session_state(session);
363         enum test_session_state next_state = state;
364         DBusMessage *msg;
365
366         LOG("state %d session %p %s state %d", state, session,
367                 session->notify_path, session->info->state);
368
369         switch (state) {
370         case TEST_SESSION_STATE_0:
371                 if (session0->info->state == CONNMAN_SESSION_STATE_DISCONNECTED
372                                 && session1->info->state ==
373                                         CONNMAN_SESSION_STATE_DISCONNECTED) {
374                         next_state = TEST_SESSION_STATE_1;
375                 }
376                 if (session0->info->state == CONNMAN_SESSION_STATE_CONNECTED &&
377                                 session1->info->state ==
378                                 CONNMAN_SESSION_STATE_CONNECTED) {
379                         LOG("state was already connected, continuing");
380                         next_state = TEST_SESSION_STATE_2;
381                 }
382
383                 break;
384         case TEST_SESSION_STATE_1:
385                 if (session0->info->state >= CONNMAN_SESSION_STATE_CONNECTED &&
386                                 session1->info->state >=
387                                         CONNMAN_SESSION_STATE_CONNECTED) {
388                         next_state = TEST_SESSION_STATE_2;
389                 }
390
391                 break;
392         case TEST_SESSION_STATE_2:
393                 if (session0->info->state == CONNMAN_SESSION_STATE_DISCONNECTED
394                                 && (session1->info->state ==
395                                         CONNMAN_SESSION_STATE_DISCONNECTED ||
396                                                 session1->info->state ==
397                                         CONNMAN_SESSION_STATE_CONNECTED) ) {
398                         LOG("session0 /foo is disconnected, session1 /bar "
399                                 "can be either connected or disconnected");
400                         next_state = TEST_SESSION_STATE_3;
401                 }
402
403                 break;
404         case TEST_SESSION_STATE_3:
405
406                 return;
407         }
408
409         if (state == next_state)
410                 return;
411
412         set_session_state(session, next_state);
413
414         LOG("next_state %d", next_state);
415
416         switch (next_state) {
417         case TEST_SESSION_STATE_0:
418
419                 return;
420         case TEST_SESSION_STATE_1:
421                 msg = session_connect(session0->connection, session0);
422                 g_assert(msg);
423                 dbus_message_unref(msg);
424
425                 return;
426
427         case TEST_SESSION_STATE_2:
428                 msg = session_disconnect(session0->connection, session0);
429                 g_assert(msg);
430                 dbus_message_unref(msg);
431
432                 return;
433         case TEST_SESSION_STATE_3:
434                 util_session_cleanup(session0);
435                 util_session_cleanup(session1);
436
437                 util_idle_call(session0->fix, util_quit_loop,
438                                 util_session_destroy);
439
440                 return;
441         }
442 }
443
444 static void test_session_connect_free_ride(struct test_fix *fix)
445 {
446         struct test_session *session0, *session1;
447
448         /*
449          * +-------------------+
450          * |       START       |
451          * +-------------------+
452          *   |
453          *   | connect foo
454          *   v
455          * +-------------------+
456          * |   FOO-CONNECTED   |
457          * +-------------------+
458          *   |
459          *   | free-ride bar
460          *   v
461          * +-------------------+
462          * | FOO-BAR-CONNECTED |
463          * +-------------------+
464          *  |
465          *  | disconnect foo
466          *  v
467          * +-------------------+
468          * |        END        |
469          * +-------------------+
470          */
471
472         util_session_create(fix, 2);
473         session0 = &fix->session[0];
474         session1 = &fix->session[1];
475
476         session0->notify_path = g_strdup("/foo");
477         session1->notify_path = g_strdup("/bar");
478         session0->notify = test_session_connect_free_ride_notify;
479         session1->notify = test_session_connect_free_ride_notify;
480
481         util_session_init(session0);
482         util_session_init(session1);
483
484         set_session_state(session0, TEST_SESSION_STATE_0);
485 }
486
487 static void policy_save(GKeyFile *keyfile, char *pathname)
488 {
489         gchar *data = NULL;
490         gsize length = 0;
491         GError *error = NULL;
492
493         data = g_key_file_to_data(keyfile, &length, NULL);
494
495         if (!g_file_set_contents(pathname, data, length, &error)) {
496                 DBG("Failed to store information: %s", error->message);
497                 g_error_free(error);
498                 g_assert(0);
499         }
500
501         g_free(data);
502 }
503
504 static void policy_allowed_bearers(const char *allowed_bearers)
505 {
506         struct passwd *pwd;
507         uid_t uid;
508         char *pathname;
509         GKeyFile *keyfile;
510
511         LOG("update to '%s'", allowed_bearers);
512
513         uid = getuid();
514         pwd = getpwuid(uid);
515         g_assert(pwd);
516
517         keyfile = g_key_file_new();
518         g_key_file_set_string(keyfile, "policy_foo", "uid", pwd->pw_name);
519         g_key_file_set_string(keyfile, "policy_foo", "AllowedBearers",
520                                 allowed_bearers);
521
522         pathname = g_strdup_printf("%s/foo.policy", POLICYDIR);
523         policy_save(keyfile, pathname);
524
525         g_free(pathname);
526         g_key_file_free(keyfile);
527 }
528
529 static void policy_remove_file(void)
530 {
531         char *pathname;
532
533         pathname = g_strdup_printf("%s/foo.policy", POLICYDIR);
534         unlink(pathname);
535         g_free(pathname);
536 }
537
538 static void test_session_policy_notify(struct test_session *session)
539 {
540         enum test_session_state state = get_session_state(session);
541         enum test_session_state next_state = state;
542         DBusMessage *msg;
543
544         LOG("state %d session %p %s state %d", state, session,
545                 session->notify_path, session->info->state);
546
547         switch (state) {
548         case TEST_SESSION_STATE_0:
549                 if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
550                         next_state = TEST_SESSION_STATE_1;
551                 break;
552         case TEST_SESSION_STATE_1:
553                 if (session->info->state >= CONNMAN_SESSION_STATE_CONNECTED)
554                         next_state = TEST_SESSION_STATE_2;
555                 break;
556         case TEST_SESSION_STATE_2:
557                 if (session->info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
558                         next_state = TEST_SESSION_STATE_3;
559         default:
560                 break;
561         }
562
563         if (state == next_state)
564                 return;
565
566         set_session_state(session, next_state);
567
568         LOG("next_state %d", next_state);
569
570         switch (next_state) {
571         case TEST_SESSION_STATE_1:
572                 policy_allowed_bearers("ethernet");
573
574                 msg = session_connect(session->connection, session);
575                 g_assert(msg);
576                 dbus_message_unref(msg);
577                 return;
578         case TEST_SESSION_STATE_2:
579                 policy_allowed_bearers("");
580                 return;
581         case TEST_SESSION_STATE_3:
582                 policy_remove_file();
583                 util_session_cleanup(session);
584                 util_idle_call(session->fix, util_quit_loop,
585                                 util_session_destroy);
586                 return;
587         default:
588                 return;
589         }
590 }
591
592 static void test_session_policy(struct test_fix *fix)
593 {
594         struct test_session *session;
595
596         /*
597          * +-------------------+
598          * |       START       |
599          * +-------------------+
600          *   |
601          *   | write policy AllowedBearers = ethernet
602          *   v
603          * +-------------------+
604          * |   FOO-CONNECTED   |
605          * +-------------------+
606          *  |
607          *  | write policy AllowedBearers =
608          *  v
609          * +-------------------+
610          * |        END        |
611          * +-------------------+
612          */
613
614         policy_remove_file();
615
616         util_session_create(fix, 1);
617         session = fix->session;
618
619         session->notify_path = g_strdup("/foo");
620         session->notify =  test_session_policy_notify;
621
622         util_session_init(session);
623
624         set_session_state(session, TEST_SESSION_STATE_0);
625 }
626
627 static bool is_online(struct test_fix *fix)
628 {
629         if (g_strcmp0(fix->manager.state, "online") == 0)
630                 return true;
631
632         return false;
633 }
634
635 static void enable_session_mode(struct test_fix *fix)
636 {
637         set_session_mode(fix, true);
638
639         if (!is_online(fix))
640                 util_idle_call(fix, util_quit_loop, NULL);
641 }
642
643 static void manager_state_changed(struct test_fix *fix)
644 {
645         if (!is_online(fix)) {
646                 fix->manager_changed = NULL;
647                 util_idle_call(fix, util_quit_loop, NULL);
648         }
649 }
650
651 static void disable_session_mode(struct test_fix *fix)
652 {
653         set_session_mode(fix, false);
654 }
655
656 static void setup_cb(struct test_fix *fix)
657 {
658         fix->manager_changed = manager_state_changed;
659
660         util_call(fix, enable_session_mode, NULL);
661 }
662
663 static void teardown_cb(struct test_fix *fix)
664 {
665         util_call(fix, disable_session_mode, NULL);
666         util_idle_call(fix, util_quit_loop, NULL);
667 }
668
669 int main(int argc, char *argv[])
670 {
671         g_test_init(&argc, &argv, NULL);
672
673         util_test_add("/manager/session create no notify",
674                 test_session_create_no_notify, setup_cb, teardown_cb);
675         util_test_add("/manager/session destroy no notify",
676                 test_session_destroy_no_notify, setup_cb, teardown_cb);
677         util_test_add("/manager/session create",
678                 test_session_create, setup_cb, teardown_cb);
679         util_test_add("/manager/session create destroy",
680                 test_session_create_destroy, setup_cb, teardown_cb);
681         util_test_add("/manager/session create duplicate notification",
682                 test_session_create_dup_notification, setup_cb, teardown_cb);
683         util_test_add("/manager/session create many",
684                 test_session_create_many, setup_cb, teardown_cb);
685
686         util_test_add("/session/connect",
687                 test_session_connect, setup_cb, teardown_cb);
688         util_test_add("/session/disconnect",
689                 test_session_disconnect, setup_cb, teardown_cb);
690         util_test_add("/session/connect disconnect",
691                 test_session_connect_disconnect, setup_cb, teardown_cb);
692         util_test_add("/session/connect free-ride",
693                 test_session_connect_free_ride, setup_cb, teardown_cb);
694
695         util_test_add("/session/policy",
696                 test_session_policy, setup_cb, teardown_cb);
697
698         return g_test_run();
699 }