Update to upstream 1.0.1
[profile/ivi/gsignond.git] / test / plugins / pluginproxytest.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2012 Intel Corporation.
7  *
8  * Contact: Alexander Kanavin <alex.kanavin@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include <check.h>
27 #include <stdlib.h>
28 #include <glib-object.h>
29 #include <string.h>
30
31 #include "gsignond-plugin-proxy.h"
32 #include "gsignond-plugin-proxy-factory.h"
33 #include "gsignond-plugin-remote.h"
34 #include "gsignond/gsignond-error.h"
35 #include "gsignond/gsignond-log.h"
36
37 static GMainLoop *main_loop = NULL;
38
39 static void
40 _stop_mainloop ()
41 {
42     if (main_loop) {
43         g_main_loop_quit (main_loop);
44     }
45 }
46
47 static void
48 _run_mainloop ()
49 {
50     g_main_loop_run (main_loop);
51 }
52
53
54 static void
55 _setup ()
56 {
57 #if !GLIB_CHECK_VERSION (2, 36, 0)
58     g_type_init ();
59 #endif
60     if (main_loop == NULL) {
61         main_loop = g_main_loop_new (NULL, FALSE);
62     }
63 }
64
65 static void
66 _teardown ()
67 {
68     if (main_loop) {
69         _stop_mainloop ();
70         g_main_loop_unref (main_loop);
71         main_loop = NULL;
72     }
73 }
74
75 struct _GSignondAuthSession
76 {
77     GObject parent;
78
79 };
80
81 struct _GSignondAuthSessionClass
82 {
83     GObjectClass parent_class;
84 };
85
86 G_DEFINE_TYPE (GSignondAuthSession, gsignond_auth_session, G_TYPE_OBJECT);
87
88 static void
89 gsignond_auth_session_init (
90         GSignondAuthSession *self)
91 {
92 }
93
94 static void
95 gsignond_auth_session_class_init (
96         GSignondAuthSessionClass *klass)
97 {
98 //    GObjectClass *object_class = G_OBJECT_CLASS (klass);
99 }
100
101 gboolean testing_proxy_process = FALSE;
102 gboolean testing_proxy_process_cancel = FALSE;
103 gboolean testing_proxy_process_queue = FALSE;
104 gint proxy_process_queue_results = 0;
105 gboolean testing_proxy_process_queue_cancel = FALSE;
106 gint proxy_process_queue_cancel_results = 0;
107 gboolean testing_proxy_process_cancel_triggered = FALSE;
108
109 void
110 gsignond_auth_session_notify_process_result (
111         GSignondAuthSession *iface,
112         GSignondSessionData *result,
113         gpointer user_data)
114 {
115     int i;
116
117     DBG ("");
118
119     if (testing_proxy_process) {
120         testing_proxy_process = FALSE;
121         fail_if(g_strcmp0(
122             gsignond_session_data_get_username(result), "megauser") != 0);
123         fail_if(g_strcmp0(
124             gsignond_session_data_get_secret(result), "megapassword") != 0);
125         _stop_mainloop ();
126
127     } else if (testing_proxy_process_queue) {
128         proxy_process_queue_results++;
129         if (proxy_process_queue_results == 1) {
130             GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
131             GSignondSessionData* data = gsignond_dictionary_new();
132             fail_if(data == NULL);
133             gsignond_session_data_set_username(data, "megauser");
134             gsignond_session_data_set_secret(data, "megapassword");
135
136             gsignond_plugin_proxy_process(proxy, iface, data, NULL, "password",
137                     proxy);
138
139             gsignond_plugin_proxy_process(proxy, iface, data, NULL, "password",
140                     proxy);
141     
142             gsignond_dictionary_unref(data);
143         }
144         if (proxy_process_queue_results == 3) {
145             testing_proxy_process_queue = FALSE;
146             _stop_mainloop ();
147         }
148     } else if (testing_proxy_process_queue_cancel) {
149         proxy_process_queue_cancel_results++;
150         if (proxy_process_queue_cancel_results == 1) {
151             GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
152             GSignondSessionData* data = gsignond_dictionary_new();
153             fail_if(data == NULL);
154
155             for (i = 0; i < 9; i++) {
156                 gsignond_plugin_proxy_process(proxy, iface, data, NULL, "mech1",
157                         proxy);
158             }
159             gsignond_dictionary_unref(data);
160         }
161         if (proxy_process_queue_cancel_results == 10) {
162             testing_proxy_process_queue_cancel = FALSE;
163             _stop_mainloop ();
164         }
165     } else 
166         fail_if(TRUE);    
167 }
168
169 void
170 gsignond_auth_session_notify_process_error (
171         GSignondAuthSession *iface,
172         const GError *error,
173         gpointer user_data)
174 {
175     DBG ("");
176
177     if (testing_proxy_process_cancel) {
178         fail_if(error->code != GSIGNOND_ERROR_SESSION_CANCELED);
179         testing_proxy_process_cancel = FALSE;
180         _stop_mainloop ();
181     } else if (testing_proxy_process_queue_cancel) {
182         fail_if(error->code != GSIGNOND_ERROR_SESSION_CANCELED);
183         proxy_process_queue_cancel_results++;
184     }
185
186 }
187
188 void 
189 gsignond_auth_session_notify_store (
190         GSignondAuthSession *self,
191         GSignondSessionData *session_data)
192 {
193     DBG ("");
194     fail_if(TRUE);
195 }
196
197 void 
198 gsignond_auth_session_notify_user_action_required (
199         GSignondAuthSession *self,
200         GSignondSignonuiData *session_data)
201 {
202     DBG ("");
203     fail_if(TRUE);
204 }
205
206 void 
207 gsignond_auth_session_notify_refreshed (
208         GSignondAuthSession *self,
209         GSignondSignonuiData *session_data)
210 {
211     DBG ("");
212     fail_if(TRUE);
213 }
214
215 void 
216 gsignond_auth_session_notify_state_changed (
217         GSignondAuthSession *self,
218         gint state,
219         const gchar *message,
220         gpointer user_data)
221 {
222     if (testing_proxy_process_cancel &&
223             !testing_proxy_process_cancel_triggered &&
224             state == GSIGNOND_PLUGIN_STATE_WAITING) {
225         GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
226         gsignond_plugin_proxy_cancel(proxy, self);
227         testing_proxy_process_cancel_triggered = TRUE;
228     } else if (testing_proxy_process_queue_cancel &&
229             state == GSIGNOND_PLUGIN_STATE_WAITING &&
230             proxy_process_queue_cancel_results == 5) {
231         GSignondPluginProxy* proxy = GSIGNOND_PLUGIN_PROXY(user_data);
232         gsignond_plugin_proxy_cancel(proxy, self);
233     }
234 }
235
236 static void
237 check_plugin_proxy(
238         GSignondPluginProxy* proxy,
239         gchar *type,
240         gchar **mechanisms)
241 {
242     gchar* ptype = NULL;
243     gchar** pmechanisms = NULL;
244     gint i = 0;
245
246     fail_if(proxy == NULL);
247
248     g_object_get(proxy, "type", &ptype, "mechanisms", &pmechanisms, NULL);
249     fail_unless(g_strcmp0(ptype, type) == 0);
250     g_free(ptype);
251
252     guint len = g_strv_length (pmechanisms);
253     fail_unless (len == g_strv_length (mechanisms));
254
255     for (i=0; i<len; i++) {
256         fail_unless(g_strcmp0(pmechanisms[i], mechanisms[i]) == 0);
257     }
258     if (pmechanisms) {
259         g_strfreev(pmechanisms);
260     }
261 }
262
263 static GSignondPluginProxy* _make_plugin_proxy(GSignondConfig* config, const gchar* plugin_type)
264 {
265     gchar* loader_path = g_build_filename (g_getenv("SSO_BIN_DIR"), "gsignond-plugind", NULL);
266
267     GSignondPluginProxy* proxy = gsignond_plugin_proxy_new(loader_path, plugin_type,
268                                       gsignond_config_get_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT));
269     g_free(loader_path);
270     return proxy;
271 }
272
273 START_TEST (test_pluginproxy_create)
274 {
275     DBG("test_pluginproxy_create\n");
276
277     gchar *pass_mechs[] = {"password", NULL};
278
279     GSignondConfig* config = gsignond_config_new();
280     fail_if(config == NULL);
281
282     GSignondPluginProxy* proxy2 = _make_plugin_proxy(config,
283             "absentplugin");
284     fail_if (proxy2 != NULL);
285
286     GSignondPluginProxy* proxy = _make_plugin_proxy(config, "password");
287     fail_if (proxy == NULL);
288     check_plugin_proxy(proxy, "password", pass_mechs);
289
290     g_object_unref(proxy);
291     g_object_unref(config);
292 }
293 END_TEST
294
295 START_TEST (test_pluginproxy_process)
296 {
297     DBG("test_pluginproxy_process\n");
298
299     GSignondConfig* config = gsignond_config_new();
300     fail_if(config == NULL);
301     
302     GSignondPluginProxy* proxy = _make_plugin_proxy(config, "password");
303     fail_if (proxy == NULL);
304     
305     GSignondSessionData* data = gsignond_dictionary_new();
306     fail_if(data == NULL);
307     gsignond_session_data_set_username(data, "megauser");
308     gsignond_session_data_set_secret(data, "megapassword");
309     
310     GSignondAuthSession* test_auth_session =
311             g_object_new(gsignond_auth_session_get_type(), NULL);
312
313     testing_proxy_process = TRUE;
314
315     gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "password",
316             proxy);
317
318     _run_mainloop ();
319
320     fail_if(testing_proxy_process);
321     
322     gsignond_dictionary_unref(data);
323     g_object_unref(test_auth_session);
324     g_object_unref(proxy);
325     g_object_unref(config);
326 }
327 END_TEST
328
329 START_TEST (test_pluginproxy_process_cancel)
330 {
331     DBG("test_pluginproxy_process_cancel\n");
332
333     GSignondConfig* config = gsignond_config_new();
334     fail_if(config == NULL);
335     
336     GSignondPluginProxy* proxy = _make_plugin_proxy(config, "ssotest");
337     fail_if (proxy == NULL);
338     
339     GSignondSessionData* data = gsignond_dictionary_new();
340     fail_if(data == NULL);
341
342     GSignondAuthSession* test_auth_session = g_object_new(
343             gsignond_auth_session_get_type(), NULL);
344     
345     testing_proxy_process_cancel = TRUE;
346     
347     gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "mech1",
348             proxy);
349
350     _run_mainloop ();
351
352     fail_if(testing_proxy_process_cancel);
353     
354     gsignond_dictionary_unref(data);
355     g_object_unref(test_auth_session);
356     g_object_unref(proxy);
357     g_object_unref(config);
358 }
359 END_TEST
360
361 START_TEST (test_pluginproxy_process_queue)
362 {
363     DBG("test_pluginproxy_process_queue\n");
364
365     GSignondConfig* config = gsignond_config_new();
366     fail_if(config == NULL);
367     
368     GSignondPluginProxy* proxy = _make_plugin_proxy(config, "password");
369     fail_if (proxy == NULL);
370     
371     GSignondSessionData* data = gsignond_dictionary_new();
372     fail_if(data == NULL);
373     gsignond_session_data_set_username(data, "megauser");
374     gsignond_session_data_set_secret(data, "megapassword");
375
376     GSignondAuthSession* test_auth_session = g_object_new(
377             gsignond_auth_session_get_type(), NULL);
378     
379     testing_proxy_process_queue = TRUE;
380     
381     gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "password",
382             proxy);
383     _run_mainloop ();
384
385     fail_if(testing_proxy_process_queue);
386     fail_if(proxy_process_queue_results < 3);
387
388     gsignond_dictionary_unref(data);
389     g_object_unref(test_auth_session);
390     g_object_unref(proxy);
391     g_object_unref(config);
392 }
393 END_TEST
394
395 START_TEST (test_pluginproxy_process_queue_cancel)
396 {
397     GSignondConfig* config = gsignond_config_new();
398     fail_if(config == NULL);
399     
400     GSignondPluginProxy* proxy = _make_plugin_proxy(config, "ssotest");
401     fail_if (proxy == NULL);
402     
403     GSignondSessionData* data = gsignond_dictionary_new();
404     fail_if(data == NULL);
405
406     GSignondAuthSession* test_auth_session = g_object_new(
407             gsignond_auth_session_get_type(), NULL);
408     
409     testing_proxy_process_queue_cancel = TRUE;
410     
411     gsignond_plugin_proxy_process(proxy, test_auth_session, data, NULL, "mech1",
412             proxy);
413
414     _run_mainloop ();
415
416     fail_if(testing_proxy_process_queue_cancel);
417     fail_if(proxy_process_queue_cancel_results != 10);
418
419     gsignond_dictionary_unref(data);
420     g_object_unref(test_auth_session);
421     g_object_unref(proxy);
422     g_object_unref(config);
423 }
424 END_TEST
425
426 START_TEST (test_pluginproxyfactory_methods_and_mechanisms)
427 {
428     DBG("");
429     GSignondConfig* config = gsignond_config_new();
430     fail_if(config == NULL);
431     
432     GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(
433             config);
434     fail_if(factory == NULL);
435     const gchar *pass_method = NULL;
436     const gchar** pmethods = NULL;
437     
438     const gchar** methods = gsignond_plugin_proxy_factory_get_plugin_types(
439             factory);
440     fail_if(methods == NULL);
441     pmethods = methods;
442     while (pmethods[0] != NULL) {
443         DBG ("Method %s", pmethods[0]);
444         if (g_strcmp0 (pmethods[0], "password") == 0) {
445             pass_method = pmethods[0];
446         }
447         pmethods++;
448     }
449     const gchar** mechanisms =
450             gsignond_plugin_proxy_factory_get_plugin_mechanisms(factory,
451                     pass_method);
452     fail_if(mechanisms == NULL);
453     fail_if(strcmp(mechanisms[0], "password") != 0);
454     fail_if(mechanisms[1] != NULL);
455     
456     g_object_unref(factory);
457     g_object_unref(config);
458 }
459 END_TEST
460
461 START_TEST (test_pluginproxyfactory_get)
462 {
463     DBG("");
464     gchar *pass_mechs[] = {"password", NULL};
465     GSignondConfig* config = gsignond_config_new();
466     fail_if(config == NULL);
467     
468     GSignondPluginProxyFactory* factory = gsignond_plugin_proxy_factory_new(
469             config);
470     fail_if(factory == NULL);
471     
472     fail_if(gsignond_plugin_proxy_factory_get_plugin(factory, "absentplugin")
473             != NULL);
474
475     GSignondPluginProxy* proxy1 = gsignond_plugin_proxy_factory_get_plugin(
476         factory, "password");
477     GSignondPluginProxy* proxy2 = gsignond_plugin_proxy_factory_get_plugin(
478         factory, "password");
479     GSignondPluginProxy* proxy3 = gsignond_plugin_proxy_factory_get_plugin(
480         factory, "password");
481     fail_if(proxy1 == NULL || proxy2 == NULL || proxy3 == NULL);
482     fail_if(proxy1 != proxy3 || proxy1 != proxy2);
483     check_plugin_proxy(proxy1, "password", pass_mechs);
484
485     g_object_unref(proxy1);
486     g_object_unref(proxy2);
487     g_object_unref(proxy3);    
488     
489     g_object_unref(factory);
490     g_object_unref(config);
491 }
492 END_TEST
493
494 typedef struct {
495     GSignondPluginProxyFactory *factory;
496     GSignondPluginProxy *proxy;
497 } ProxyTimeoutData;
498
499 static gboolean
500 _validate_new_proxy(gpointer userdata)
501 {
502     ProxyTimeoutData *data = (ProxyTimeoutData *)userdata;
503     fail_if (data == NULL);
504
505     fail_if(g_hash_table_size(data->factory->plugins) != 0);
506
507     GSignondPluginProxy *proxy = gsignond_plugin_proxy_factory_get_plugin (data->factory, "ssotest");
508     fail_if (proxy == NULL);
509     fail_if(g_hash_table_size(data->factory->plugins) != 1);
510
511     // This is unreliable: the proxy object may be allocated to the same location
512     // as the old object!
513     //fail_if (proxy == data->proxy, "expected new proxy object, but got cached object");
514     g_object_unref(proxy);
515
516     g_free (userdata);
517
518     _stop_mainloop();
519
520     return FALSE;
521 }
522
523 static gboolean
524 _validate_cached_proxy (gpointer userdata)
525 {
526     ProxyTimeoutData *data = (ProxyTimeoutData *)userdata;
527     fail_if (data == NULL);
528     
529     fail_if(g_hash_table_size(data->factory->plugins) != 1);
530     GSignondPluginProxy *proxy = gsignond_plugin_proxy_factory_get_plugin (data->factory, "ssotest");
531     fail_if (proxy == NULL);
532     fail_if(g_hash_table_size(data->factory->plugins) != 1);
533
534     fail_unless (proxy == data->proxy, "expected cached proxy object, but got new object");
535
536     g_object_unref (proxy);
537
538     g_timeout_add (2200, _validate_new_proxy, userdata);
539
540     return FALSE;
541 }
542
543 START_TEST (test_pluginproxyfactory_proxy_timeout)
544 {
545     DBG("test_pluginproxyfactory_proxy_timeout\n");
546     GSignondPluginProxyFactory *factory = NULL;
547     GSignondPluginProxy *proxy1 = NULL, *proxy2 = NULL;
548     GSignondConfig *config = NULL;
549
550     /* CASE 1: proxy timeout disabled */
551     config = gsignond_config_new();
552     fail_if(config == NULL);
553     gsignond_config_set_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT, 0);
554
555     factory = gsignond_plugin_proxy_factory_new (config);
556     fail_if (factory == NULL);
557
558     proxy1 = gsignond_plugin_proxy_factory_get_plugin (factory, "ssotest");
559     fail_if (proxy1 == NULL);
560     g_object_unref (proxy1);
561     fail_if(g_hash_table_size(factory->plugins) != 1);
562
563     proxy2 = gsignond_plugin_proxy_factory_get_plugin (factory, "ssotest");
564     fail_if (proxy2 == NULL);
565     fail_if(g_hash_table_size(factory->plugins) != 1);
566
567     fail_unless (proxy1 == proxy2, "got new plugin proxy object, "
568                                    "where expected cached object(%p,%p)",
569                                     proxy1, proxy2);
570     g_object_unref (proxy2);
571
572     g_object_unref (config);
573     g_object_unref (factory);
574
575     /* CASE 2: proxy timeout enbled */ 
576     config = gsignond_config_new();
577     fail_if(config == NULL);
578     gsignond_config_set_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT, 1);
579
580     factory = gsignond_plugin_proxy_factory_new (config);
581     fail_if (factory == NULL);
582
583     proxy1 = gsignond_plugin_proxy_factory_get_plugin (factory, "ssotest");
584     fail_if (proxy1 == NULL);
585     g_object_unref (proxy1);
586     ProxyTimeoutData *data = g_new0(ProxyTimeoutData, 1);
587     data->factory = factory;
588     data->proxy = proxy1;
589     g_timeout_add_seconds (2, _validate_new_proxy, (gpointer)data);
590
591     _run_mainloop ();
592
593     g_object_unref(config);
594     g_object_unref(factory);
595
596     /* CASE 3: proxy timeout enable - request recently closed plugin */
597     config = gsignond_config_new ();
598     fail_if (config == NULL);
599     gsignond_config_set_integer (config, GSIGNOND_CONFIG_PLUGIN_TIMEOUT, 2);
600
601     factory = gsignond_plugin_proxy_factory_new(config);
602     fail_if (factory == NULL);
603
604     proxy1 = gsignond_plugin_proxy_factory_get_plugin(factory, "ssotest");
605     fail_if (proxy1 == NULL);
606     g_object_unref (proxy1);
607
608     ProxyTimeoutData *data1 = g_new0(ProxyTimeoutData, 1);
609     data1->factory = factory;
610     data1->proxy = proxy1;
611
612     g_timeout_add_seconds (1, _validate_cached_proxy, (gpointer)data1);
613
614     _run_mainloop();
615
616     g_object_unref(config);
617     g_object_unref(factory);
618 }
619 END_TEST
620
621 Suite* pluginproxy_suite (void)
622 {
623     Suite *s = suite_create ("Plugin proxy");
624     
625     /* Core test case */
626     TCase *tc_core = tcase_create ("Tests");
627     tcase_add_checked_fixture (tc_core, _setup, _teardown);
628
629     tcase_set_timeout (tc_core, 10);
630     tcase_add_test (tc_core, test_pluginproxy_create);
631     tcase_add_test (tc_core, test_pluginproxy_process);
632     tcase_add_test (tc_core, test_pluginproxy_process_cancel);
633     tcase_add_test (tc_core, test_pluginproxy_process_queue);
634     tcase_add_test (tc_core, test_pluginproxy_process_queue_cancel);
635     tcase_add_test (tc_core, test_pluginproxyfactory_methods_and_mechanisms);
636     tcase_add_test (tc_core, test_pluginproxyfactory_get);
637     tcase_add_test (tc_core, test_pluginproxyfactory_proxy_timeout);
638
639     suite_add_tcase (s, tc_core);
640     return s;
641 }
642
643 int main (void)
644 {
645     int number_failed;
646     
647     Suite *s = pluginproxy_suite();
648     SRunner *sr = srunner_create(s);
649     srunner_run_all(sr, CK_NORMAL);
650     number_failed = srunner_ntests_failed(sr);
651     srunner_free(sr);
652     return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
653 }
654   
655