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