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