peer to peer dbus support added
[platform/upstream/libgsignon-glib.git] / tests / check_signon.c
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of libsignon-glib
4  *
5  * Copyright (C) 2009-2011 Nokia Corporation.
6  * Copyright (C) 2011-2012 Canonical Ltd.
7  * Copyright (C) 2012 Intel Corporation.
8  *
9  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
10  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * version 2.1 as published by the Free Software Foundation.
15  *
16  * This library is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24  * 02110-1301 USA
25  */
26
27 /**
28  * @example check_signon.c
29  * Shows how to initialize the framework.
30  */
31
32 #define SIGNON_DISABLE_DEPRECATION_WARNINGS
33
34 #include "libsignon-glib/signon-internals.h"
35 #include "libsignon-glib/signon-auth-service.h"
36 #include "libsignon-glib/signon-auth-session.h"
37 #include "libsignon-glib/signon-identity.h"
38 #include "libsignon-glib/signon-errors.h"
39
40 #include <glib.h>
41 #include <check.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 static const gchar *ssotest_mechanisms[] =
48     { "mech1", "mech2", "mech3", "BLOB", NULL };
49 static GMainLoop *main_loop = NULL;
50 static SignonIdentity *identity = NULL;
51 static SignonAuthService *auth_service = NULL;
52
53 #define SIGNOND_IDLE_TIMEOUT (5 + 2)
54
55 static void
56 end_test ()
57 {
58     if (auth_service)
59     {
60         g_object_unref (auth_service);
61         auth_service = NULL;
62     }
63
64     if (identity)
65     {
66         g_object_unref (identity);
67         identity = NULL;
68     }
69
70     if (main_loop)
71     {
72         g_main_loop_quit (main_loop);
73         g_main_loop_unref (main_loop);
74         main_loop = NULL;
75     }
76 }
77
78 START_TEST(test_init)
79 {
80     g_type_init ();
81
82     g_debug("%s", G_STRFUNC);
83     auth_service = signon_auth_service_new ();
84     main_loop = g_main_loop_new (NULL, FALSE);
85
86     fail_unless (SIGNON_IS_AUTH_SERVICE (auth_service),
87                  "Failed to initialize the AuthService.");
88     end_test ();
89 }
90 END_TEST
91
92 static void
93 signon_query_methods_cb (SignonAuthService *auth_service, gchar **methods,
94                          GError *error, gpointer user_data)
95 {
96     if (error)
97     {
98         g_warning ("%s: %s", G_STRFUNC, error->message);
99         g_main_loop_quit (main_loop);
100         fail();
101     }
102
103     gboolean has_ssotest = FALSE;
104
105     fail_unless (g_strcmp0 (user_data, "Hello") == 0, "Got wrong string");
106     fail_unless (methods != NULL, "The methods does not exist");
107
108     while (*methods)
109     {
110         if (g_strcmp0 (*methods, "ssotest") == 0)
111         {
112             has_ssotest = TRUE;
113             break;
114         }
115         methods++;
116     }
117     fail_unless (has_ssotest, "ssotest method does not exist");
118
119     g_main_loop_quit (main_loop);
120 }
121
122 START_TEST(test_query_methods)
123 {
124     g_type_init ();
125
126     g_debug("%s", G_STRFUNC);
127     if(!main_loop)
128         main_loop = g_main_loop_new (NULL, FALSE);
129
130     auth_service = signon_auth_service_new ();
131
132     fail_unless (SIGNON_IS_AUTH_SERVICE (auth_service),
133                  "Failed to initialize the AuthService.");
134
135     signon_auth_service_query_methods (auth_service, (SignonQueryMethodsCb)signon_query_methods_cb, "Hello");
136     g_main_loop_run (main_loop);
137     end_test ();
138 }
139 END_TEST
140
141 static void
142 signon_query_mechanisms_cb (SignonAuthService *auth_service, gchar *method,
143         gchar **mechanisms, GError *error, gpointer user_data)
144 {
145     if (error)
146     {
147         g_warning ("%s: %s", G_STRFUNC, error->message);
148         g_main_loop_quit (main_loop);
149         fail();
150     }
151
152     gboolean has_mech1 = FALSE;
153     gboolean has_mech2 = FALSE;
154     gboolean has_mech3 = FALSE;
155
156     fail_unless (strcmp (user_data, "Hello") == 0, "Got wrong string");
157     fail_unless (mechanisms != NULL, "The mechanisms does not exist");
158
159     while (*mechanisms)
160     {
161         if (g_strcmp0 (*mechanisms, "mech1") == 0)
162             has_mech1 = TRUE;
163
164         if (g_strcmp0 (*mechanisms, "mech2") == 0)
165             has_mech2 = TRUE;
166
167         if (g_strcmp0 (*mechanisms, "mech3") == 0)
168             has_mech3 = TRUE;
169
170         mechanisms++;
171     }
172
173     fail_unless (has_mech1, "mech1 mechanism does not exist");
174     fail_unless (has_mech2, "mech2 mechanism does not exist");
175     fail_unless (has_mech3, "mech3 mechanism does not exist");
176
177     g_main_loop_quit (main_loop);
178 }
179
180 static void
181 signon_query_mechanisms_cb_fail (SignonAuthService *auth_service,
182                                  gchar *method,
183                                  gchar **mechanisms,
184                                  GError *error, gpointer user_data)
185 {
186     fail_unless (error != NULL);
187     fail_unless (mechanisms == NULL);
188     fail_unless (error->domain == SIGNON_ERROR);
189     fail_unless (error->code == SIGNON_ERROR_METHOD_NOT_KNOWN);
190     g_main_loop_quit (main_loop);
191 }
192
193 START_TEST(test_query_mechanisms)
194 {
195     g_type_init ();
196
197     g_debug("%s", G_STRFUNC);
198     auth_service = signon_auth_service_new ();
199
200     fail_unless (SIGNON_IS_AUTH_SERVICE (auth_service),
201                  "Failed to initialize the AuthService.");
202
203     signon_auth_service_query_mechanisms (auth_service,
204                                           "ssotest",
205                                           (SignonQueryMechanismCb)signon_query_mechanisms_cb,
206                                           "Hello");
207     if(!main_loop)
208         main_loop = g_main_loop_new (NULL, FALSE);
209
210     g_main_loop_run (main_loop);
211
212     /* Test a non existing method */
213     signon_auth_service_query_mechanisms (auth_service,
214                                           "non-existing",
215                                           (SignonQueryMechanismCb)signon_query_mechanisms_cb_fail,
216                                           "Hello");
217     g_main_loop_run (main_loop);
218     end_test ();
219 }
220 END_TEST
221
222
223 static gboolean
224 test_quit_main_loop_cb (gpointer data)
225 {
226     g_main_loop_quit (main_loop);
227     return FALSE;
228 }
229
230 static void
231 test_auth_session_query_mechanisms_cb (SignonAuthSession *self,
232                                        gchar **mechanisms,
233                                        const GError *error,
234                                        gpointer user_data)
235 {
236     if (error)
237     {
238         g_warning ("%s: %s", G_STRFUNC, error->message);
239         g_main_loop_quit (main_loop);
240         fail();
241     }
242
243     fail_unless (mechanisms != NULL, "The mechanisms does not exist");
244
245     gchar** patterns = (gchar**)user_data;
246
247     int i = g_strv_length(mechanisms);
248     int x = g_strv_length(patterns);
249     fail_unless( i == x, "The number of obtained methods is wrong: %d vs %d", i, x);
250
251     while ( i > 0 )
252     {
253         gchar* pattern = patterns[--i];
254         fail_unless(g_strcmp0(pattern, mechanisms[i]) == 0, "The obtained mechanism differs from predefined pattern: %s vs %s", mechanisms[i], pattern);
255     }
256
257     g_strfreev(mechanisms);
258     g_main_loop_quit (main_loop);
259 }
260
261 START_TEST(test_auth_session_query_mechanisms)
262 {
263     g_type_init();
264
265     GError *err = NULL;
266
267     g_debug("%s", G_STRFUNC);
268     SignonIdentity *idty = signon_identity_new(NULL);
269     fail_unless (idty != NULL, "Cannot create Iddentity object");
270
271     SignonAuthSession *auth_session = signon_identity_create_session(idty,
272                                                                      "ssotest",
273                                                                      &err);
274     fail_unless (auth_session != NULL, "Cannot create AuthSession object");
275
276     g_clear_error(&err);
277
278     gchar* patterns[4];
279     patterns[0] = g_strdup("mech1");
280     patterns[1] = g_strdup("mech2");
281     patterns[2] = g_strdup("mech3");
282     patterns[3] = NULL;
283
284     signon_auth_session_query_available_mechanisms(auth_session,
285                                                   (const gchar**)patterns,
286                                                   test_auth_session_query_mechanisms_cb,
287                                                   (gpointer)patterns);
288     if(!main_loop)
289         main_loop = g_main_loop_new (NULL, FALSE);
290
291     g_main_loop_run (main_loop);
292
293     g_free(patterns[2]);
294     patterns[2] = NULL;
295
296     signon_auth_session_query_available_mechanisms(auth_session,
297                                                   (const gchar**)patterns,
298                                                   test_auth_session_query_mechanisms_cb,
299                                                   (gpointer)patterns);
300
301     g_main_loop_run (main_loop);
302
303     g_free(patterns[1]);
304     patterns[1] = NULL;
305
306     signon_auth_session_query_available_mechanisms(auth_session,
307                                                   (const gchar**)patterns,
308                                                   test_auth_session_query_mechanisms_cb,
309                                                   (gpointer)patterns);
310
311     g_main_loop_run (main_loop);
312
313     g_free(patterns[0]);
314     g_object_unref(idty);
315
316     end_test ();
317 }
318 END_TEST
319
320 static void
321 test_auth_session_query_mechanisms_nonexisting_cb (SignonAuthSession *self,
322                                                   gchar **mechanisms,
323                                                   const GError *error,
324                                                   gpointer user_data)
325 {
326     if (!error)
327     {
328         g_main_loop_quit (main_loop);
329         fail();
330         return;
331     }
332
333     g_warning ("%s: %s", G_STRFUNC, error->message);
334     g_main_loop_quit (main_loop);
335 }
336
337 START_TEST(test_auth_session_query_mechanisms_nonexisting)
338 {
339     g_type_init();
340     GError *err = NULL;
341
342     g_debug("%s", G_STRFUNC);
343     SignonIdentity *idty = signon_identity_new(NULL);
344     fail_unless (idty != NULL, "Cannot create Iddentity object");
345
346     SignonAuthSession *auth_session = signon_identity_create_session(idty,
347                                                                      "nonexisting",
348                                                                      &err);
349     fail_unless (auth_session != NULL, "Cannot create AuthSession object");
350
351     g_clear_error(&err);
352
353     gchar* patterns[4];
354     patterns[0] = g_strdup("mech1");
355     patterns[1] = g_strdup("mech2");
356     patterns[2] = g_strdup("mech3");
357     patterns[3] = NULL;
358
359     signon_auth_session_query_available_mechanisms(auth_session,
360                                                   (const gchar**)patterns,
361                                                   test_auth_session_query_mechanisms_nonexisting_cb,
362                                                   (gpointer)patterns);
363     if(!main_loop)
364         main_loop = g_main_loop_new (NULL, FALSE);
365
366     g_main_loop_run (main_loop);
367
368     g_free(patterns[0]);
369     g_free(patterns[1]);
370     g_free(patterns[2]);
371     g_object_unref(idty);
372
373     end_test ();
374 }
375 END_TEST
376
377 static void
378 test_auth_session_states_cb (SignonAuthSession *self,
379                              gint state,
380                              gchar *message,
381                              gpointer user_data)
382 {
383     gint *state_counter = (gint *)user_data;
384     (*state_counter)++;
385 }
386
387 static void
388 test_auth_session_process_cb (SignonAuthSession *self,
389                              GHashTable *sessionData,
390                              const GError *error,
391                              gpointer user_data)
392 {
393     if (error)
394     {
395         g_warning ("%s: %s", G_STRFUNC, error->message);
396         g_main_loop_quit (main_loop);
397         fail();
398     }
399
400     fail_unless (sessionData != NULL, "The result is empty");
401
402     gchar* usernameKey = g_strdup(SIGNON_SESSION_DATA_USERNAME);
403     GValue* usernameVa = (GValue*)g_hash_table_lookup(sessionData, usernameKey);
404
405     gchar* realmKey = g_strdup(SIGNON_SESSION_DATA_REALM);
406     GValue* realmVa = (GValue*)g_hash_table_lookup(sessionData, realmKey);
407
408     fail_unless(g_strcmp0(g_value_get_string(usernameVa), "test_username") == 0, "Wrong value of username");
409     fail_unless(g_strcmp0(g_value_get_string(realmVa), "testRealm_after_test") == 0, "Wrong value of realm");
410
411     g_hash_table_destroy(sessionData);
412
413     g_free(usernameKey);
414     g_free(realmKey);
415
416     g_main_loop_quit (main_loop);
417 }
418
419 START_TEST(test_auth_session_creation)
420 {
421     g_type_init();
422     GError *err = NULL;
423
424     g_debug("%s", G_STRFUNC);
425     SignonIdentity *idty = signon_identity_new(NULL);
426     fail_unless (idty != NULL, "Cannot create Identity object");
427
428     SignonAuthSession *auth_session = signon_identity_create_session(idty,
429                                                                     "ssotest",
430                                                                     &err);
431
432     fail_unless (auth_session != NULL, "Cannot create AuthSession object");
433
434     g_object_unref (idty);
435     fail_unless (SIGNON_IS_IDENTITY(idty), "Identity must stay untill all its session are not destroyed");
436     g_object_unref (auth_session);
437
438     fail_if (SIGNON_IS_AUTH_SESSION(auth_session), "AuthSession is not synchronized with parent Identity");
439     fail_if (SIGNON_IS_IDENTITY(idty), "Identity is not synchronized with its AuthSession");
440
441     g_clear_error(&err);
442 }
443 END_TEST
444
445 START_TEST(test_auth_session_process)
446 {
447     g_type_init();
448     gint state_counter = 0;
449     GError *err = NULL;
450
451     g_debug("%s", G_STRFUNC);
452     SignonIdentity *idty = signon_identity_new(NULL);
453     fail_unless (idty != NULL, "Cannot create Iddentity object");
454
455     SignonAuthSession *auth_session = signon_identity_create_session(idty,
456                                                                      "ssotest",
457                                                                      &err);
458
459     fail_unless (auth_session != NULL, "Cannot create AuthSession object");
460
461     g_clear_error(&err);
462
463     g_signal_connect(auth_session, "state-changed",
464                      G_CALLBACK(test_auth_session_states_cb), &state_counter);
465
466     GHashTable* sessionData = g_hash_table_new(g_str_hash,
467                                                g_str_equal);
468     GValue* usernameVa = g_new0(GValue, 1);
469     gchar* usernameKey = g_strdup(SIGNON_SESSION_DATA_USERNAME);
470     g_value_init (usernameVa, G_TYPE_STRING);
471     g_value_set_static_string(usernameVa, "test_username");
472
473     g_hash_table_insert (sessionData,
474                          usernameKey,
475                          usernameVa);
476
477     GValue* passwordVa = g_new0(GValue, 1);
478     gchar* passwordKey = g_strdup(SIGNON_SESSION_DATA_SECRET);
479
480     g_value_init (passwordVa, G_TYPE_STRING);
481     g_value_set_static_string(passwordVa, "test_username");
482
483     g_hash_table_insert (sessionData,
484                          passwordKey,
485                          passwordVa);
486
487     signon_auth_session_process(auth_session,
488                                sessionData,
489                                "mech1",
490                                test_auth_session_process_cb,
491                                sessionData);
492     if(!main_loop)
493         main_loop = g_main_loop_new (NULL, FALSE);
494
495
496     g_main_loop_run (main_loop);
497     fail_unless (state_counter == 12, "Wrong numer of state change signals: %d", state_counter);
498     state_counter = 0;
499
500     signon_auth_session_process(auth_session,
501                                sessionData,
502                                "mech1",
503                                test_auth_session_process_cb,
504                                sessionData);
505
506     g_main_loop_run (main_loop);
507     fail_unless (state_counter == 12, "Wrong numer of state change signals: %d", state_counter);
508     state_counter = 0;
509
510     signon_auth_session_process(auth_session,
511                                sessionData,
512                                "mech1",
513                                test_auth_session_process_cb,
514                                sessionData);
515
516     g_main_loop_run (main_loop);
517     fail_unless (state_counter == 12, "Wrong numer of state change signals: %d", state_counter);
518     state_counter = 0;
519
520     g_object_unref (auth_session);
521     g_object_unref (idty);
522
523     g_value_unset(usernameVa);
524     g_free(usernameVa);
525     g_free(usernameKey);
526
527     g_value_unset(passwordVa);
528     g_free(passwordVa);
529     g_free(passwordKey);
530
531     end_test ();
532 }
533 END_TEST
534
535 static void
536 test_auth_session_process_failure_cb (GObject *source_object,
537                                       GAsyncResult *res,
538                                       gpointer user_data)
539 {
540     SignonAuthSession *auth_session = SIGNON_AUTH_SESSION (source_object);
541     GVariant *v_reply;
542     GError **error = user_data;
543
544     fail_unless (SIGNON_IS_AUTH_SESSION (source_object));
545
546     v_reply = signon_auth_session_process_finish (auth_session, res, error);
547     fail_unless (v_reply == NULL);
548
549     g_main_loop_quit (main_loop);
550 }
551
552 START_TEST(test_auth_session_process_failure)
553 {
554     SignonIdentity *identity;
555     SignonAuthSession *auth_session;
556     GVariantBuilder builder;
557     GVariant *session_data;
558     GError *error = NULL;
559
560     g_debug("%s", G_STRFUNC);
561
562     g_type_init ();
563
564     identity = signon_identity_new_from_db (1, NULL);
565     fail_unless (identity != NULL, "Cannot create Identity object");
566     auth_session = signon_auth_session_new (identity,
567                                             "ssotest",
568                                             &error);
569     fail_unless (auth_session != NULL, "Cannot create AuthSession object");
570     fail_unless (error == NULL);
571
572     g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
573     g_variant_builder_add (&builder, "{sv}",
574                            "key", g_variant_new_string ("value"));
575
576     session_data = g_variant_builder_end (&builder);
577
578     signon_auth_session_process_async (auth_session,
579                                        session_data,
580                                        "mechx",
581                                        NULL,
582                                        test_auth_session_process_failure_cb,
583                                        &error);
584
585     main_loop = g_main_loop_new (NULL, FALSE);
586     g_main_loop_run (main_loop);
587     fail_unless (error != NULL);
588     fail_unless (error->domain == SIGNON_ERROR);
589     fail_unless (error->code == SIGNON_ERROR_MECHANISM_NOT_AVAILABLE);
590
591     g_object_unref (auth_session);
592     g_object_unref (identity);
593
594     end_test ();
595 }
596 END_TEST
597
598 static void
599 test_auth_session_process_after_store_cb (SignonAuthSession *self,
600                                           GHashTable *reply,
601                                           const GError *error,
602                                           gpointer user_data)
603 {
604     GValue *v_username;
605
606     if (error != NULL)
607     {
608         fail("Got error: %s", error->message);
609         g_main_loop_quit (main_loop);
610         return;
611     }
612
613     fail_unless (reply != NULL, "The result is empty");
614
615     v_username = g_hash_table_lookup(reply,
616                                      SIGNON_SESSION_DATA_USERNAME);
617
618     fail_unless (g_strcmp0 (g_value_get_string (v_username), "Nice user") == 0,
619                  "Wrong value of username");
620
621     g_hash_table_unref (reply);
622     g_object_unref (self);
623
624     g_main_loop_quit (main_loop);
625 }
626
627 static void
628 test_auth_session_process_after_store_start_session(SignonIdentity *self,
629                                                     guint32 id,
630                                                     const GError *error,
631                                                     gpointer user_data)
632 {
633     GError *err = NULL;
634
635     if (error != NULL)
636     {
637         g_warning ("%s %d: %s", G_STRFUNC, __LINE__, error->message);
638         fail();
639         g_main_loop_quit (main_loop);
640         return;
641     }
642
643     fail_unless (id > 0);
644
645     SignonAuthSession *auth_session =
646         signon_identity_create_session (self,
647                                         "ssotest",
648                                         &err);
649
650     fail_unless (auth_session != NULL, "Cannot create AuthSession object");
651     if (err != NULL)
652     {
653         fail ("Got error: %s", err->message);
654         g_clear_error (&err);
655     }
656
657     GHashTable *session_data = g_hash_table_new (g_str_hash,
658                                                  g_str_equal);
659
660     signon_auth_session_process (auth_session,
661                                  session_data,
662                                  "mech1",
663                                  test_auth_session_process_after_store_cb,
664                                  NULL);
665 }
666
667 START_TEST(test_auth_session_process_after_store)
668 {
669     SignonIdentityInfo *info;
670     SignonIdentity *identity;
671
672     g_debug("%s", G_STRFUNC);
673
674     g_type_init();
675     main_loop = g_main_loop_new (NULL, FALSE);
676
677     identity = signon_identity_new (NULL);
678     fail_unless (SIGNON_IS_IDENTITY (identity),
679                  "Failed to initialize the Identity.");
680
681     info = signon_identity_info_new ();
682     signon_identity_info_set_method (info, "ssotest", ssotest_mechanisms);
683     signon_identity_info_set_owner_from_values (info, "", "");
684     signon_identity_info_access_control_list_append (info,
685         signon_security_context_new_from_values ("*", "*"));
686     signon_identity_info_set_username (info, "Nice user");
687
688     signon_identity_store_credentials_with_info (identity,
689                                                  info,
690                                                  test_auth_session_process_after_store_start_session,
691                                                  NULL);
692     g_main_loop_run (main_loop);
693
694     g_object_unref (identity);
695
696     end_test ();
697 }
698 END_TEST
699
700 static GHashTable *create_methods_hashtable()
701 {
702     gchar *mechanisms[] = {
703             "mechanism1",
704             "mechanism2",
705             "mechanism3",
706             NULL
707     };
708
709     GHashTable *methods = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
710                                                 (GDestroyNotify)g_strfreev);
711
712     g_hash_table_insert (methods, g_strdup("method1"), g_strdupv(mechanisms));
713     g_hash_table_insert (methods, g_strdup("method2"), g_strdupv(mechanisms));
714     g_hash_table_insert (methods, g_strdup("method3"), g_strdupv(mechanisms));
715
716     return methods;
717 }
718
719 static void new_identity_store_credentials_cb(SignonIdentity *self,
720                                               guint32 id,
721                                               const GError *error,
722                                               gpointer user_data)
723 {
724     gint *new_id = user_data;
725
726     if(error)
727     {
728         g_warning ("%s %d: %s", G_STRFUNC, __LINE__, error->message);
729         fail();
730     }
731
732     fail_unless (id > 0);
733
734     *new_id = id;
735
736     g_main_loop_quit (main_loop);
737 }
738
739 static guint
740 new_identity()
741 {
742     SignonIdentity *identity;
743     GHashTable *methods;
744     guint id = 0;
745
746     if (main_loop == NULL)
747         main_loop = g_main_loop_new (NULL, FALSE);
748
749     identity = signon_identity_new (NULL);
750     fail_unless (SIGNON_IS_IDENTITY (identity));
751     methods = g_hash_table_new (g_str_hash, g_str_equal);
752     g_hash_table_insert (methods, "ssotest", ssotest_mechanisms);
753     signon_identity_store_credentials_with_args (identity,
754                                                  "James Bond",
755                                                  "007",
756                                                  TRUE,
757                                                  methods,
758                                                  "MI-6",
759                                                  NULL,
760                                                  NULL,
761                                                  NULL,
762                                                  0,
763                                                  new_identity_store_credentials_cb,
764                                                  &id);
765     g_hash_table_destroy (methods);
766
767     if (id == 0)
768         g_main_loop_run (main_loop);
769
770     return id;
771
772 }
773
774 static gboolean
775 identity_registered_cb (gpointer data)
776 {
777     g_main_loop_quit (main_loop);
778     return FALSE;
779 }
780
781 START_TEST(test_get_existing_identity)
782 {
783     g_type_init ();
784
785     g_debug("%s", G_STRFUNC);
786     guint id = new_identity();
787
788     fail_unless (id != 0);
789
790     identity = signon_identity_new_from_db (id, NULL);
791
792     fail_unless (identity != NULL);
793     fail_unless (SIGNON_IS_IDENTITY (identity),
794                  "Failed to initialize the Identity.");
795
796     g_timeout_add (1000, identity_registered_cb, identity);
797     main_loop = g_main_loop_new (NULL, FALSE);
798     g_main_loop_run (main_loop);
799
800     end_test ();
801 }
802 END_TEST
803
804 START_TEST(test_get_nonexisting_identity)
805 {
806     g_type_init ();
807
808     g_debug("%s", G_STRFUNC);
809     identity = signon_identity_new_from_db (G_MAXINT, NULL);
810
811     fail_unless (identity != NULL);
812     fail_unless (SIGNON_IS_IDENTITY (identity),
813                  "Failed to initialize the Identity.");
814
815     g_timeout_add (1000, identity_registered_cb, identity);
816     main_loop = g_main_loop_new (NULL, FALSE);
817     g_main_loop_run (main_loop);
818
819     const GError *error = NULL;
820     error = signon_identity_get_last_error(identity);
821     fail_unless (error != NULL);
822
823     fail_unless (error->domain == SIGNON_ERROR);
824     fail_unless (error->code == SIGNON_ERROR_IDENTITY_NOT_FOUND);
825
826     end_test ();
827 }
828 END_TEST
829
830 static void store_credentials_identity_cb(SignonIdentity *self,
831                                          guint32 id,
832                                          const GError *error,
833                                          gpointer user_data)
834 {
835     if(error)
836     {
837         g_warning ("%s %d: %s", G_STRFUNC, __LINE__, error->message);
838         fail();
839     }
840
841     fail_unless (id > 0);
842
843     if (user_data != NULL)
844     {
845         gint *last_id = (gint *)user_data;
846         g_warning ("%s (prev_id vs new_id): %d vs %d", G_STRFUNC, *last_id, id);
847
848         fail_unless (id == (*last_id) + 1);
849         (*last_id) += 1;
850     }
851
852     /* Wait some time to ensure that the info-updated signals are
853      * processed
854      */
855     g_timeout_add_seconds (2, test_quit_main_loop_cb, main_loop);
856 }
857
858 START_TEST(test_store_credentials_identity)
859 {
860     g_type_init ();
861     g_debug("%s", G_STRFUNC);
862     SignonIdentity *idty = signon_identity_new(NULL);
863     fail_unless (idty != NULL);
864     fail_unless (SIGNON_IS_IDENTITY (idty),
865                  "Failed to initialize the Identity.");
866
867     gint last_id = new_identity();
868
869     GHashTable *methods = create_methods_hashtable();
870
871     signon_identity_store_credentials_with_args (idty,
872                                                  "James Bond",
873                                                  "007",
874                                                  1,
875                                                  methods,
876                                                  "MI-6",
877                                                  NULL,
878                                                  NULL,
879                                                  NULL,
880                                                  0,
881                                                  store_credentials_identity_cb,
882                                                  &last_id);
883     g_hash_table_destroy (methods);
884
885     g_timeout_add (1000, test_quit_main_loop_cb, idty);
886     main_loop = g_main_loop_new (NULL, FALSE);
887     g_main_loop_run (main_loop);
888
889     g_object_unref(idty);
890     end_test ();
891 }
892 END_TEST
893
894 static void identity_verify_username_cb(SignonIdentity *self,
895                                         gboolean valid,
896                                         const GError *error,
897                                         gpointer user_data)
898 {
899     fail_unless (error != NULL, "The callback returned NULL error for unimplemented function");
900     g_warning ("Error: %s ", error->message);
901
902     g_main_loop_quit((GMainLoop *)user_data);
903 }
904
905 static void identity_remove_cb(SignonIdentity *self, const GError *error, gpointer user_data)
906 {
907
908     g_warning (" %s ", __func__);
909      if (error)
910      {
911         g_warning ("Error: %s ", error->message);
912         fail_if (user_data == NULL, "There should be no error in callback");
913      }
914     else
915     {
916         g_warning ("No error");
917         fail_if (user_data != NULL, "The callback must return an error");
918     }
919
920     g_main_loop_quit(main_loop);
921 }
922
923 START_TEST(test_remove_identity)
924 {
925     g_type_init ();
926     g_debug("%s", G_STRFUNC);
927     SignonIdentity *idty = signon_identity_new (NULL);
928     fail_unless (idty != NULL);
929     fail_unless (SIGNON_IS_IDENTITY (idty),
930                  "Failed to initialize the Identity.");
931
932     main_loop = g_main_loop_new (NULL, FALSE);
933     /*
934      * Try to remove non-stored identity
935      * */
936     signon_identity_remove(idty, identity_remove_cb, NULL);
937     g_main_loop_run (main_loop);
938
939     GHashTable *methods = create_methods_hashtable();
940
941     /*
942      * Try to remove existing identy
943      * */
944
945     gint id = new_identity();
946     SignonIdentity *idty2 = signon_identity_new_from_db (id, NULL);
947
948     signon_identity_remove(idty2, identity_remove_cb, NULL);
949     g_main_loop_run (main_loop);
950
951     /*
952      * Try to remove already removed
953      * */
954
955     signon_identity_remove(idty2, identity_remove_cb, GINT_TO_POINTER(TRUE));
956
957     g_object_unref (idty);
958     g_object_unref (idty2);
959     end_test ();
960 }
961 END_TEST
962
963 static gboolean _contains(gchar **mechs, gchar *mech)
964 {
965     gboolean present = FALSE;
966     gint i = 0;
967     while (mechs[i] != NULL)
968     {
969         if (g_strcmp0 (mech, mechs[i]) == 0) present = TRUE;
970         i++;
971     }
972     return present;
973 }
974
975 static void identity_info_cb(SignonIdentity *self, const SignonIdentityInfo *info, const GError *error, gpointer user_data)
976 {
977      if (error)
978      {
979         g_warning ("%s: Error: %s ", __func__, error->message);
980         fail_if (info != NULL, "Error: %s ", error->message);
981         g_main_loop_quit(main_loop);
982         return;
983      }
984
985      g_warning ("No error");
986
987      SignonIdentityInfo **pattern_ptr = (SignonIdentityInfo **)user_data;
988      SignonIdentityInfo *pattern = NULL;
989
990      if (pattern_ptr)
991          pattern = (*pattern_ptr);
992
993      if (pattern == NULL)
994          fail_unless (info == NULL, "The info must be NULL");
995      else
996      {
997          fail_unless (info != NULL, "The info must be non-null");
998          fail_unless (g_strcmp0 (signon_identity_info_get_username(info),
999                                  signon_identity_info_get_username(pattern)) == 0, "The info has wrong username");
1000          fail_unless (g_strcmp0 (signon_identity_info_get_caption(info),
1001                                  signon_identity_info_get_caption(pattern)) == 0, "The info has wrong caption");
1002
1003          GHashTable *methods = (GHashTable *)signon_identity_info_get_methods (info);
1004          gchar **mechs1 = g_hash_table_lookup (methods, "method1");
1005          gchar **mechs2 = g_hash_table_lookup (methods, "method2");
1006          gchar **mechs3 = g_hash_table_lookup (methods, "method3");
1007
1008          fail_unless (g_strv_length (mechs1) == 3);
1009          fail_unless (g_strv_length (mechs2) == 3);
1010          fail_unless (g_strv_length (mechs3) == 3);
1011
1012          fail_unless (_contains(mechs1, "mechanism1"));
1013          fail_unless (_contains(mechs1, "mechanism2"));
1014          fail_unless (_contains(mechs1, "mechanism3"));
1015
1016          fail_unless (_contains(mechs2, "mechanism1"));
1017          fail_unless (_contains(mechs2, "mechanism2"));
1018          fail_unless (_contains(mechs2, "mechanism3"));
1019
1020          fail_unless (_contains(mechs3, "mechanism1"));
1021          fail_unless (_contains(mechs3, "mechanism2"));
1022          fail_unless (_contains(mechs3, "mechanism3"));
1023      }
1024
1025      if (info)
1026      {
1027          signon_identity_info_free (pattern);
1028          *pattern_ptr = signon_identity_info_copy (info);
1029      }
1030
1031      g_main_loop_quit(main_loop);
1032 }
1033
1034 static SignonIdentityInfo *create_standard_info()
1035 {
1036     GHashTable *methods;
1037
1038     g_debug("%s", G_STRFUNC);
1039
1040     SignonIdentityInfo *info = signon_identity_info_new ();
1041
1042     methods = g_hash_table_new (g_str_hash, g_str_equal);
1043     g_hash_table_insert (methods, "ssotest", ssotest_mechanisms);
1044     signon_identity_info_set_methods (info, methods);
1045     g_hash_table_destroy (methods);
1046
1047     signon_identity_info_set_owner_from_values (info, "", "");
1048     signon_identity_info_access_control_list_append (info,
1049         signon_security_context_new_from_values ("*", "*"));
1050     signon_identity_info_set_username (info, "James Bond");
1051     signon_identity_info_set_secret (info, "007", TRUE);
1052     signon_identity_info_set_caption (info, "MI-6");
1053
1054     gchar *mechanisms[] = {
1055             "mechanism1",
1056             "mechanism2",
1057             "mechanism3",
1058             NULL
1059     };
1060
1061     signon_identity_info_set_method (info, "method1", (const gchar **)mechanisms);
1062     signon_identity_info_set_method (info, "method2", (const gchar **)mechanisms);
1063     signon_identity_info_set_method (info, "method3", (const gchar **)mechanisms);
1064
1065     return info;
1066 }
1067
1068 START_TEST(test_info_identity)
1069 {
1070     g_debug("%s", G_STRFUNC);
1071     g_type_init ();
1072     SignonIdentity *idty = signon_identity_new (NULL);
1073     fail_unless (idty != NULL);
1074     fail_unless (SIGNON_IS_IDENTITY (idty),
1075                  "Failed to initialize the Identity.");
1076
1077     SignonIdentityInfo *info = NULL;
1078
1079     main_loop = g_main_loop_new (NULL, FALSE);
1080     /*
1081      * Try to get_info for non-stored idetnity
1082      * */
1083     signon_identity_query_info (idty, identity_info_cb, &info);
1084     g_main_loop_run (main_loop);
1085
1086     GHashTable *methods = create_methods_hashtable();
1087     signon_identity_store_credentials_with_args (idty,
1088                                                 "James Bond",
1089                                                 "007",
1090                                                  1,
1091                                                  methods,
1092                                                  "MI-6",
1093                                                  NULL,
1094                                                  NULL,
1095                                                  NULL,
1096                                                  0,
1097                                                  store_credentials_identity_cb,
1098                                                  NULL);
1099     g_hash_table_destroy (methods);
1100     g_main_loop_run (main_loop);
1101
1102     info = signon_identity_info_new ();
1103     signon_identity_info_set_username (info, "James Bond");
1104     signon_identity_info_set_secret (info, "007", TRUE);
1105     signon_identity_info_set_caption (info, "MI-6");
1106
1107     gchar *mechanisms[] = {
1108             "mechanism1",
1109             "mechanism2",
1110             "mechanism3",
1111             NULL
1112     };
1113
1114     signon_identity_info_set_method (info, "method1", (const gchar **)mechanisms);
1115     signon_identity_info_set_method (info, "method2", (const gchar **)mechanisms);
1116     signon_identity_info_set_method (info, "method3", (const gchar **)mechanisms);
1117
1118     signon_identity_query_info (idty, identity_info_cb, &info);
1119     g_main_loop_run (main_loop);
1120
1121     gint id = signon_identity_info_get_id (info);
1122     fail_unless (id != 0);
1123     SignonIdentity *idty2 = signon_identity_new_from_db (id, NULL);
1124
1125     signon_identity_query_info (idty2, identity_info_cb, &info);
1126     g_main_loop_run (main_loop);
1127
1128     /*
1129      * Try to update one identity and
1130      * have a look what will happen
1131      * */
1132     signon_identity_info_set_username (info, "James Bond_2nd version");
1133     signon_identity_info_set_caption (info, "caption_2nd version");
1134
1135     signon_identity_store_credentials_with_info (idty2,
1136                                                  info,
1137                                                  store_credentials_identity_cb,
1138                                                  NULL);
1139     g_main_loop_run (main_loop);
1140
1141     signon_identity_query_info (idty, identity_info_cb, &info);
1142     g_main_loop_run (main_loop);
1143     /*
1144      * Try to remove existing identity and
1145      * have a look what will happen
1146      * */
1147     signon_identity_remove(idty2, identity_remove_cb, NULL);
1148     g_main_loop_run (main_loop);
1149
1150     /*
1151      * no main_loops required as
1152      * the callback is executed immediately
1153      * */
1154     signon_identity_query_info (idty2, identity_info_cb, NULL);
1155     signon_identity_query_info (idty, identity_info_cb, NULL);
1156
1157     signon_identity_info_free (info);
1158     g_object_unref (idty);
1159     g_object_unref (idty2);
1160     end_test ();
1161 }
1162 END_TEST
1163
1164 static void identity_signout_cb (SignonIdentity *self,
1165                                 const GError *error,
1166                                 gpointer user_data)
1167 {
1168     if (error)
1169         g_warning ("%s: %s", G_STRFUNC, error->message);
1170     else
1171         g_warning ("%s: No error", G_STRFUNC);
1172
1173     fail_unless (error == NULL, "There should be no error in callback");
1174     g_main_loop_quit (main_loop);
1175 }
1176
1177 static void identity_signout_signal_cb (gpointer instance, gpointer user_data)
1178 {
1179     gint *incr = (gint *)user_data;
1180     (*incr) = (*incr) + 1;
1181     g_warning ("%s: %d", G_STRFUNC, *incr);
1182 }
1183
1184 START_TEST(test_signout_identity)
1185 {
1186     g_debug("%s", G_STRFUNC);
1187     g_type_init ();
1188     SignonIdentity *idty = signon_identity_new (NULL);
1189     fail_unless (idty != NULL);
1190     fail_unless (SIGNON_IS_IDENTITY (idty),
1191                  "Failed to initialize the Identity.");
1192
1193     SignonIdentityInfo *info = create_standard_info();
1194     main_loop = g_main_loop_new (NULL, FALSE);
1195
1196     signon_identity_store_credentials_with_info (idty,
1197                                                  info,
1198                                                  store_credentials_identity_cb,
1199                                                  NULL);
1200     g_main_loop_run (main_loop);
1201     signon_identity_query_info (idty, identity_info_cb, &info);
1202     g_main_loop_run (main_loop);
1203
1204     gint id = signon_identity_info_get_id (info);
1205     SignonIdentity *idty2 = signon_identity_new_from_db (id, NULL);
1206
1207     /* wait some more time to ensure that the object gets registered */
1208     g_timeout_add_seconds (2, test_quit_main_loop_cb, main_loop);
1209     g_main_loop_run (main_loop);
1210
1211     signon_identity_info_free (info);
1212
1213     GError *err = NULL;
1214
1215     SignonAuthSession *as1 = signon_identity_create_session (idty,
1216                                                             "ssotest",
1217                                                             &err);
1218     fail_unless (as1 != NULL, "cannot create AuthSession");
1219
1220     SignonAuthSession *as2 = signon_identity_create_session (idty2,
1221                                                              "ssotest",
1222                                                              &err);
1223     fail_unless (as2 != NULL, "cannot create AuthSession");
1224
1225     gint counter = 0;
1226
1227     g_signal_connect (idty, "signout",
1228                       G_CALLBACK(identity_signout_signal_cb), &counter);
1229     g_signal_connect (idty2, "signout",
1230                       G_CALLBACK(identity_signout_signal_cb), &counter);
1231
1232     signon_identity_signout (idty, identity_signout_cb, NULL);
1233     g_main_loop_run (main_loop);
1234
1235     fail_unless (counter == 2, "Lost some of SIGNOUT signals");
1236     fail_if (SIGNON_IS_AUTH_SESSION (as1), "Authsession1 was not destroyed after signout");
1237     fail_if (SIGNON_IS_AUTH_SESSION (as2), "Authsession2 was not destroyed after signout");
1238
1239     g_object_unref (idty);
1240     g_object_unref (idty2);
1241 }
1242 END_TEST
1243
1244 START_TEST(test_unregistered_identity)
1245 {
1246     g_type_init ();
1247     g_debug("%s", G_STRFUNC);
1248     SignonIdentity *idty = signon_identity_new (NULL);
1249     fail_unless (idty != NULL);
1250     fail_unless (SIGNON_IS_IDENTITY (idty),
1251                  "Failed to initialize the Identity.");
1252
1253     SignonIdentityInfo *info = create_standard_info();
1254     main_loop = g_main_loop_new (NULL, FALSE);
1255
1256     signon_identity_store_credentials_with_info (idty,
1257                                                  info,
1258                                                  store_credentials_identity_cb,
1259                                                  NULL);
1260     g_main_loop_run (main_loop);
1261
1262     /*
1263      * give the time for identity to became idle
1264      * */
1265     sleep(SIGNOND_IDLE_TIMEOUT);
1266     SignonIdentity *idty2 = signon_identity_new (NULL);
1267
1268     /*
1269      * give time to handle unregistered signal
1270      * */
1271     g_timeout_add_seconds (5, test_quit_main_loop_cb, main_loop);
1272
1273     signon_identity_query_info (idty, identity_info_cb, &info);
1274     g_main_loop_run (main_loop);
1275
1276     g_object_unref (idty);
1277     g_object_unref (idty2);
1278 }
1279 END_TEST
1280
1281 START_TEST(test_unregistered_auth_session)
1282 {
1283     g_debug("%s", G_STRFUNC);
1284     g_type_init ();
1285     SignonIdentity *idty = signon_identity_new (NULL);
1286     fail_unless (idty != NULL);
1287     fail_unless (SIGNON_IS_IDENTITY (idty),
1288                  "Failed to initialize the Identity.");
1289
1290     main_loop = g_main_loop_new (NULL, FALSE);
1291
1292     GError *err = NULL;
1293     SignonAuthSession *as = signon_identity_create_session(idty,
1294                                                           "ssotest",
1295                                                            &err);
1296     /* give time to register the objects */
1297     g_timeout_add_seconds (2, test_quit_main_loop_cb, main_loop);
1298     g_main_loop_run (main_loop);
1299
1300     /*
1301      * give the time for identity to became idle
1302      * */
1303     sleep(SIGNOND_IDLE_TIMEOUT);
1304     SignonIdentity *idty2 = signon_identity_new (NULL);
1305
1306     /*
1307      * give time to handle unregistered signal
1308      * */
1309     g_timeout_add_seconds (5, test_quit_main_loop_cb, main_loop);
1310     g_main_loop_run (main_loop);
1311
1312
1313     gchar* patterns[4];
1314     patterns[0] = g_strdup("mech1");
1315     patterns[1] = g_strdup("mech2");
1316     patterns[2] = g_strdup("mech3");
1317     patterns[3] = NULL;
1318
1319     signon_auth_session_query_available_mechanisms(as,
1320                                                   (const gchar**)patterns,
1321                                                   test_auth_session_query_mechanisms_cb,
1322                                                   (gpointer)patterns);
1323     g_main_loop_run (main_loop);
1324
1325     g_object_unref (as);
1326     g_object_unref (idty);
1327     g_object_unref (idty2);
1328
1329     g_free (patterns[0]);
1330     g_free (patterns[1]);
1331     g_free (patterns[2]);
1332     g_free (patterns[3]);
1333 }
1334 END_TEST
1335
1336 static void
1337 test_regression_unref_process_cb (SignonAuthSession *self,
1338                                   GHashTable *reply,
1339                                   const GError *error,
1340                                   gpointer user_data)
1341 {
1342     GValue *v_string;
1343
1344     if (error)
1345     {
1346         g_warning ("%s: %s", G_STRFUNC, error->message);
1347         g_main_loop_quit (main_loop);
1348         fail();
1349     }
1350
1351     fail_unless (reply != NULL, "The result is empty");
1352
1353     fail_unless (g_strcmp0 (user_data, "Hi there!") == 0,
1354                  "Didn't get expected user_data");
1355
1356     v_string = g_hash_table_lookup(reply, "James");
1357     fail_unless (v_string != 0);
1358     fail_unless (g_strcmp0 (g_value_get_string (v_string), "Bond") == 0,
1359                  "Wrong reply data");
1360
1361     /* The next line is actually the regression we want to test */
1362     g_object_unref (self);
1363
1364     g_main_loop_quit (main_loop);
1365 }
1366
1367 START_TEST(test_regression_unref)
1368 {
1369     SignonIdentity *identity;
1370     SignonAuthSession *auth_session;
1371     GHashTable *session_data;
1372     GError *error = NULL;
1373     GValue v_string = G_VALUE_INIT;
1374
1375     g_debug ("%s", G_STRFUNC);
1376
1377     g_type_init ();
1378     main_loop = g_main_loop_new (NULL, FALSE);
1379
1380     identity = signon_identity_new_from_db (1, NULL);
1381     fail_unless (identity != NULL);
1382     auth_session = signon_auth_session_new (identity, "ssotest", &error);
1383     fail_unless (auth_session != NULL);
1384
1385     session_data = g_hash_table_new (g_str_hash, g_str_equal);
1386     g_value_init (&v_string, G_TYPE_STRING);
1387     g_value_set_static_string (&v_string, "Bond");
1388     g_hash_table_insert (session_data, "James", &v_string);
1389
1390     signon_auth_session_process (auth_session,
1391                                  session_data,
1392                                  "mech1",
1393                                  test_regression_unref_process_cb,
1394                                  g_strdup ("Hi there!"));
1395     g_main_loop_run (main_loop);
1396
1397     g_object_unref (auth_session);
1398     g_object_unref (identity);
1399
1400     end_test ();
1401 }
1402 END_TEST
1403
1404 Suite *
1405 signon_suite(void)
1406 {
1407     Suite *s = suite_create ("signon-glib");
1408
1409     /* Core test case */
1410     TCase * tc_core = tcase_create("Core");
1411
1412     /*
1413      * 18 minutes timeout
1414      * */
1415     tcase_set_timeout(tc_core, 1080);
1416     tcase_add_test (tc_core, test_init);
1417     tcase_add_test (tc_core, test_query_methods);
1418     tcase_add_test (tc_core, test_query_mechanisms);
1419     tcase_add_test (tc_core, test_get_existing_identity);
1420     tcase_add_test (tc_core, test_get_nonexisting_identity);
1421
1422     tcase_add_test (tc_core, test_auth_session_creation);
1423     tcase_add_test (tc_core, test_auth_session_query_mechanisms);
1424     tcase_add_test (tc_core, test_auth_session_query_mechanisms_nonexisting);
1425     tcase_add_test (tc_core, test_auth_session_process);
1426     tcase_add_test (tc_core, test_auth_session_process_failure);
1427     tcase_add_test (tc_core, test_auth_session_process_after_store);
1428     tcase_add_test (tc_core, test_store_credentials_identity);
1429     tcase_add_test (tc_core, test_remove_identity);
1430     tcase_add_test (tc_core, test_info_identity);
1431
1432     tcase_add_test (tc_core, test_signout_identity);
1433     tcase_add_test (tc_core, test_unregistered_identity);
1434     tcase_add_test (tc_core, test_unregistered_auth_session);
1435
1436     tcase_add_test (tc_core, test_regression_unref);
1437
1438     suite_add_tcase (s, tc_core);
1439
1440     return s;
1441 }
1442
1443 int main(void)
1444 {
1445     int number_failed;
1446     Suite * s = signon_suite();
1447     SRunner * sr = srunner_create(s);
1448
1449     srunner_set_xml(sr, "/tmp/result.xml");
1450     srunner_run_all(sr, CK_NORMAL);
1451     number_failed = srunner_ntests_failed(sr);
1452     srunner_free (sr);
1453
1454     return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1455 }
1456
1457 /* vim: set ai et tw=75 ts=4 sw=4: */
1458