[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gio / tests / tls-interaction.c
1 /* GLib testing framework examples and tests
2  *
3  * Copyright (C) 2011 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Stef Walter <stefw@collobora.co.uk>
19  */
20
21 #include "config.h"
22
23 #include <gio/gio.h>
24
25 #include "gtesttlsbackend.h"
26
27 static GPtrArray *fixtures = NULL;
28
29 typedef struct {
30   /* Class virtual interaction methods */
31   gpointer ask_password_func;
32   gpointer ask_password_async_func;
33   gpointer ask_password_finish_func;
34   gpointer request_certificate_func;
35   gpointer request_certificate_async_func;
36   gpointer request_certificate_finish_func;
37
38   /* Expected results */
39   GTlsInteractionResult result;
40   GQuark error_domain;
41   gint error_code;
42   const gchar *error_message;
43 } Fixture;
44
45 typedef struct {
46   GTlsInteraction *interaction;
47   GTlsPassword *password;
48   GTlsConnection *connection;
49   GMainLoop *loop;
50   GThread *interaction_thread;
51   GThread *test_thread;
52   GThread *loop_thread;
53   const Fixture *fixture;
54 } Test;
55
56 typedef struct {
57   GTlsInteraction parent;
58   Test *test;
59 } TestInteraction;
60
61 typedef struct {
62   GTlsInteractionClass parent;
63 } TestInteractionClass;
64
65 static GType test_interaction_get_type (void);
66 G_DEFINE_TYPE (TestInteraction, test_interaction, G_TYPE_TLS_INTERACTION);
67
68 #define TEST_TYPE_INTERACTION         (test_interaction_get_type ())
69 #define TEST_INTERACTION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_INTERACTION, TestInteraction))
70 #define TEST_IS_INTERACTION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_INTERACTION))
71
72 static void
73 test_interaction_init (TestInteraction *self)
74 {
75
76 }
77
78 static void
79 test_interaction_class_init (TestInteractionClass *klass)
80 {
81   /* By default no virtual methods */
82 }
83
84 static void
85 test_interaction_ask_password_async_success (GTlsInteraction    *interaction,
86                                              GTlsPassword       *password,
87                                              GCancellable       *cancellable,
88                                              GAsyncReadyCallback callback,
89                                              gpointer            user_data)
90 {
91   GTask *task;
92   TestInteraction *self;
93
94   g_assert (TEST_IS_INTERACTION (interaction));
95   self = TEST_INTERACTION (interaction);
96
97   g_assert (g_thread_self () == self->test->interaction_thread);
98
99   g_assert (G_IS_TLS_PASSWORD (password));
100   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
101
102   task = g_task_new (self, cancellable, callback, user_data);
103
104   /* Don't do this in real life. Include a null terminator for testing */
105   g_tls_password_set_value (password, (const guchar *)"the password", 13);
106   g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
107   g_object_unref (task);
108 }
109
110
111 static GTlsInteractionResult
112 test_interaction_ask_password_finish_success (GTlsInteraction    *interaction,
113                                               GAsyncResult       *result,
114                                               GError            **error)
115 {
116   TestInteraction *self;
117
118   g_assert (TEST_IS_INTERACTION (interaction));
119   self = TEST_INTERACTION (interaction);
120
121   g_assert (g_thread_self () == self->test->interaction_thread);
122
123   g_assert (g_task_is_valid (result, interaction));
124   g_assert (error != NULL);
125   g_assert (*error == NULL);
126
127   return g_task_propagate_int (G_TASK (result), error);
128 }
129
130 static void
131 test_interaction_ask_password_async_failure (GTlsInteraction    *interaction,
132                                              GTlsPassword       *password,
133                                              GCancellable       *cancellable,
134                                              GAsyncReadyCallback callback,
135                                              gpointer            user_data)
136 {
137   GTask *task;
138   TestInteraction *self;
139
140   g_assert (TEST_IS_INTERACTION (interaction));
141   self = TEST_INTERACTION (interaction);
142
143   g_assert (g_thread_self () == self->test->interaction_thread);
144
145   g_assert (G_IS_TLS_PASSWORD (password));
146   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
147
148   task = g_task_new (self, cancellable, callback, user_data);
149
150   g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
151   g_object_unref (task);
152 }
153
154 static GTlsInteractionResult
155 test_interaction_ask_password_finish_failure (GTlsInteraction    *interaction,
156                                               GAsyncResult       *result,
157                                               GError            **error)
158 {
159   TestInteraction *self;
160
161   g_assert (TEST_IS_INTERACTION (interaction));
162   self = TEST_INTERACTION (interaction);
163
164   g_assert (g_thread_self () == self->test->interaction_thread);
165
166   g_assert (g_task_is_valid (result, interaction));
167   g_assert (error != NULL);
168   g_assert (*error == NULL);
169
170   if (g_task_propagate_int (G_TASK (result), error) != -1)
171     g_assert_not_reached ();
172
173   return G_TLS_INTERACTION_FAILED;
174 }
175
176
177 static GTlsInteractionResult
178 test_interaction_ask_password_sync_success (GTlsInteraction    *interaction,
179                                             GTlsPassword       *password,
180                                             GCancellable       *cancellable,
181                                             GError            **error)
182 {
183   TestInteraction *self;
184
185   g_assert (TEST_IS_INTERACTION (interaction));
186   self = TEST_INTERACTION (interaction);
187
188   g_assert (g_thread_self () == self->test->interaction_thread);
189
190   g_assert (G_IS_TLS_PASSWORD (password));
191   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
192   g_assert (error != NULL);
193   g_assert (*error == NULL);
194
195   /* Don't do this in real life. Include a null terminator for testing */
196   g_tls_password_set_value (password, (const guchar *)"the password", 13);
197   return G_TLS_INTERACTION_HANDLED;
198 }
199
200 static GTlsInteractionResult
201 test_interaction_ask_password_sync_failure (GTlsInteraction    *interaction,
202                                             GTlsPassword       *password,
203                                             GCancellable       *cancellable,
204                                             GError            **error)
205 {
206   TestInteraction *self;
207
208   g_assert (TEST_IS_INTERACTION (interaction));
209   self = TEST_INTERACTION (interaction);
210
211   g_assert (g_thread_self () == self->test->interaction_thread);
212
213   g_assert (G_IS_TLS_PASSWORD (password));
214   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
215   g_assert (error != NULL);
216   g_assert (*error == NULL);
217
218   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
219   return G_TLS_INTERACTION_FAILED;
220 }
221
222 static void
223 test_interaction_request_certificate_async_success (GTlsInteraction    *interaction,
224                                                     GTlsConnection     *connection,
225                                                     gint                unused_flags,
226                                                     GCancellable       *cancellable,
227                                                     GAsyncReadyCallback callback,
228                                                     gpointer            user_data)
229 {
230   GTask *task;
231   TestInteraction *self;
232
233   g_assert (TEST_IS_INTERACTION (interaction));
234   self = TEST_INTERACTION (interaction);
235
236   g_assert (g_thread_self () == self->test->interaction_thread);
237
238   g_assert (G_IS_TLS_CONNECTION (connection));
239   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
240   g_assert (unused_flags == 0);
241
242   task = g_task_new (self, cancellable, callback, user_data);
243
244   /*
245    * IRL would call g_tls_connection_set_certificate(). But here just touch
246    * the connection in a detectable way.
247    */
248   g_object_set_data (G_OBJECT (connection), "chosen-certificate", "my-certificate");
249   g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
250   g_object_unref (task);
251 }
252
253 static GTlsInteractionResult
254 test_interaction_request_certificate_finish_success (GTlsInteraction    *interaction,
255                                                      GAsyncResult       *result,
256                                                      GError            **error)
257 {
258   TestInteraction *self;
259
260   g_assert (TEST_IS_INTERACTION (interaction));
261   self = TEST_INTERACTION (interaction);
262
263   g_assert (g_thread_self () == self->test->interaction_thread);
264
265   g_assert (g_task_is_valid (result, interaction));
266   g_assert (error != NULL);
267   g_assert (*error == NULL);
268
269   return g_task_propagate_int (G_TASK (result), error);
270 }
271
272 static void
273 test_interaction_request_certificate_async_failure (GTlsInteraction    *interaction,
274                                                     GTlsConnection     *connection,
275                                                     gint                unused_flags,
276                                                     GCancellable       *cancellable,
277                                                     GAsyncReadyCallback callback,
278                                                     gpointer            user_data)
279 {
280   GTask *task;
281   TestInteraction *self;
282
283   g_assert (TEST_IS_INTERACTION (interaction));
284   self = TEST_INTERACTION (interaction);
285
286   g_assert (g_thread_self () == self->test->interaction_thread);
287
288   g_assert (G_IS_TLS_CONNECTION (connection));
289   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
290   g_assert (unused_flags == 0);
291
292   task = g_task_new (self, cancellable, callback, user_data);
293
294   g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Another message");
295   g_object_unref (task);
296 }
297
298 static GTlsInteractionResult
299 test_interaction_request_certificate_finish_failure (GTlsInteraction    *interaction,
300                                                      GAsyncResult       *result,
301                                                      GError            **error)
302 {
303   TestInteraction *self;
304
305   g_assert (TEST_IS_INTERACTION (interaction));
306   self = TEST_INTERACTION (interaction);
307
308   g_assert (g_thread_self () == self->test->interaction_thread);
309
310   g_assert (g_task_is_valid (result, interaction));
311   g_assert (error != NULL);
312   g_assert (*error == NULL);
313
314   if (g_task_propagate_int (G_TASK (result), error) != -1)
315     g_assert_not_reached ();
316
317   return G_TLS_INTERACTION_FAILED;
318 }
319
320 static GTlsInteractionResult
321 test_interaction_request_certificate_sync_success (GTlsInteraction    *interaction,
322                                                    GTlsConnection      *connection,
323                                                    gint                 unused_flags,
324                                                    GCancellable        *cancellable,
325                                                    GError             **error)
326 {
327   TestInteraction *self;
328
329   g_assert (TEST_IS_INTERACTION (interaction));
330   self = TEST_INTERACTION (interaction);
331
332   g_assert (g_thread_self () == self->test->interaction_thread);
333
334   g_assert (G_IS_TLS_CONNECTION (connection));
335   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
336   g_assert (error != NULL);
337   g_assert (*error == NULL);
338
339   /*
340    * IRL would call g_tls_connection_set_certificate(). But here just touch
341    * the connection in a detectable way.
342    */
343   g_object_set_data (G_OBJECT (connection), "chosen-certificate", "my-certificate");
344   return G_TLS_INTERACTION_HANDLED;
345 }
346
347 static GTlsInteractionResult
348 test_interaction_request_certificate_sync_failure (GTlsInteraction    *interaction,
349                                                    GTlsConnection     *connection,
350                                                    gint                unused_flags,
351                                                    GCancellable       *cancellable,
352                                                    GError            **error)
353 {
354   TestInteraction *self;
355
356   g_assert (TEST_IS_INTERACTION (interaction));
357   self = TEST_INTERACTION (interaction);
358
359   g_assert (g_thread_self () == self->test->interaction_thread);
360
361   g_assert (G_IS_TLS_CONNECTION (connection));
362   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
363   g_assert (unused_flags == 0);
364   g_assert (error != NULL);
365   g_assert (*error == NULL);
366
367   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Another message");
368   return G_TLS_INTERACTION_FAILED;
369 }
370
371 /* ----------------------------------------------------------------------------
372  * ACTUAL TESTS
373  */
374
375 static void
376 on_ask_password_async_call (GObject      *source,
377                             GAsyncResult *result,
378                             gpointer      user_data)
379 {
380   Test *test = user_data;
381   GTlsInteractionResult res;
382   GError *error = NULL;
383
384   g_assert (G_IS_TLS_INTERACTION (source));
385   g_assert (G_TLS_INTERACTION (source) == test->interaction);
386
387   /* Check that this callback is being run in the right place */
388   g_assert (g_thread_self () == test->interaction_thread);
389
390   res = g_tls_interaction_ask_password_finish (test->interaction, result,
391                                                &error);
392
393   /* Check that the results match the fixture */
394   g_assert_cmpuint (test->fixture->result, ==, res);
395   switch (test->fixture->result)
396     {
397       case G_TLS_INTERACTION_HANDLED:
398         g_assert_no_error (error);
399         g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
400         break;
401       case G_TLS_INTERACTION_FAILED:
402         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
403         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
404         g_clear_error (&error);
405         break;
406       case G_TLS_INTERACTION_UNHANDLED:
407         g_assert_no_error (error);
408         break;
409       default:
410         g_assert_not_reached ();
411     }
412
413   /* Signal the end of the test */
414   g_main_loop_quit (test->loop);
415 }
416
417 static void
418 test_ask_password_async (Test            *test,
419                          gconstpointer    unused)
420 {
421   /* This test only works with a main loop */
422   g_assert (test->loop);
423
424   g_tls_interaction_ask_password_async (test->interaction,
425                                         test->password, NULL,
426                                         on_ask_password_async_call,
427                                         test);
428
429   /* teardown waits until g_main_loop_quit(). called from callback */
430 }
431
432 static void
433 test_invoke_ask_password (Test         *test,
434                           gconstpointer unused)
435 {
436   GTlsInteractionResult res;
437   GError *error = NULL;
438
439   res = g_tls_interaction_invoke_ask_password (test->interaction, test->password,
440                                                NULL, &error);
441
442   /* Check that the results match the fixture */
443   g_assert_cmpuint (test->fixture->result, ==, res);
444   switch (test->fixture->result)
445     {
446       case G_TLS_INTERACTION_HANDLED:
447         g_assert_no_error (error);
448         g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
449         break;
450       case G_TLS_INTERACTION_FAILED:
451         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
452         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
453         g_clear_error (&error);
454         break;
455       case G_TLS_INTERACTION_UNHANDLED:
456         g_assert_no_error (error);
457         break;
458       default:
459         g_assert_not_reached ();
460     }
461
462   /* This allows teardown to stop if running with loop */
463   if (test->loop)
464     g_main_loop_quit (test->loop);
465 }
466
467 static void
468 test_ask_password (Test         *test,
469                    gconstpointer unused)
470 {
471   GTlsInteractionResult res;
472   GError *error = NULL;
473
474   res = g_tls_interaction_ask_password (test->interaction, test->password,
475                                         NULL, &error);
476
477   /* Check that the results match the fixture */
478   g_assert_cmpuint (test->fixture->result, ==, res);
479   switch (test->fixture->result)
480     {
481       case G_TLS_INTERACTION_HANDLED:
482         g_assert_no_error (error);
483         g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
484         break;
485       case G_TLS_INTERACTION_FAILED:
486         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
487         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
488         g_clear_error (&error);
489         break;
490       case G_TLS_INTERACTION_UNHANDLED:
491         g_assert_no_error (error);
492         break;
493       default:
494         g_assert_not_reached ();
495     }
496
497   /* This allows teardown to stop if running with loop */
498   if (test->loop)
499     g_main_loop_quit (test->loop);
500 }
501
502 static void
503 on_request_certificate_async_call (GObject      *source,
504                                    GAsyncResult *result,
505                                    gpointer      user_data)
506 {
507   Test *test = user_data;
508   GTlsInteractionResult res;
509   GError *error = NULL;
510
511   g_assert (G_IS_TLS_INTERACTION (source));
512   g_assert (G_TLS_INTERACTION (source) == test->interaction);
513
514   /* Check that this callback is being run in the right place */
515   g_assert (g_thread_self () == test->interaction_thread);
516
517   res = g_tls_interaction_request_certificate_finish (test->interaction, result, &error);
518
519   /* Check that the results match the fixture */
520   g_assert_cmpuint (test->fixture->result, ==, res);
521   switch (test->fixture->result)
522     {
523       case G_TLS_INTERACTION_HANDLED:
524         g_assert_no_error (error);
525         g_assert_cmpstr (g_object_get_data (G_OBJECT (test->connection), "chosen-certificate"), ==, "my-certificate");
526         break;
527       case G_TLS_INTERACTION_FAILED:
528         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
529         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
530         g_clear_error (&error);
531         break;
532       case G_TLS_INTERACTION_UNHANDLED:
533         g_assert_no_error (error);
534         break;
535       default:
536         g_assert_not_reached ();
537     }
538
539   /* Signal the end of the test */
540   g_main_loop_quit (test->loop);
541 }
542
543 static void
544 test_request_certificate_async (Test            *test,
545                                 gconstpointer    unused)
546 {
547   /* This test only works with a main loop */
548   g_assert (test->loop);
549
550   g_tls_interaction_request_certificate_async (test->interaction,
551                                                test->connection, 0, NULL,
552                                                on_request_certificate_async_call,
553                                                test);
554
555   /* teardown waits until g_main_loop_quit(). called from callback */
556 }
557
558 static void
559 test_invoke_request_certificate (Test         *test,
560                                  gconstpointer unused)
561 {
562   GTlsInteractionResult res;
563   GError *error = NULL;
564
565   res = g_tls_interaction_invoke_request_certificate (test->interaction,
566                                                       test->connection,
567                                                       0, NULL, &error);
568
569   /* Check that the results match the fixture */
570   g_assert_cmpuint (test->fixture->result, ==, res);
571   switch (test->fixture->result)
572     {
573       case G_TLS_INTERACTION_HANDLED:
574         g_assert_no_error (error);
575         g_assert_cmpstr (g_object_get_data (G_OBJECT (test->connection), "chosen-certificate"), ==, "my-certificate");
576         break;
577       case G_TLS_INTERACTION_FAILED:
578         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
579         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
580         g_clear_error (&error);
581         break;
582       case G_TLS_INTERACTION_UNHANDLED:
583         g_assert_no_error (error);
584         break;
585       default:
586         g_assert_not_reached ();
587     }
588
589   /* This allows teardown to stop if running with loop */
590   if (test->loop)
591     g_main_loop_quit (test->loop);
592 }
593
594 static void
595 test_request_certificate (Test         *test,
596                           gconstpointer unused)
597 {
598   GTlsInteractionResult res;
599   GError *error = NULL;
600
601   res = g_tls_interaction_request_certificate (test->interaction, test->connection,
602                                                0, NULL, &error);
603
604   /* Check that the results match the fixture */
605   g_assert_cmpuint (test->fixture->result, ==, res);
606   switch (test->fixture->result)
607     {
608       case G_TLS_INTERACTION_HANDLED:
609         g_assert_no_error (error);
610         g_assert_cmpstr (g_object_get_data (G_OBJECT (test->connection), "chosen-certificate"), ==, "my-certificate");
611         break;
612       case G_TLS_INTERACTION_FAILED:
613         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
614         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
615         g_clear_error (&error);
616         break;
617       case G_TLS_INTERACTION_UNHANDLED:
618         g_assert_no_error (error);
619         break;
620       default:
621         g_assert_not_reached ();
622     }
623
624   /* This allows teardown to stop if running with loop */
625   if (test->loop)
626     g_main_loop_quit (test->loop);
627 }
628
629 /* ----------------------------------------------------------------------------
630  * TEST SETUP
631  */
632
633 static void
634 setup_without_loop (Test           *test,
635                     gconstpointer   user_data)
636 {
637   const Fixture *fixture = user_data;
638   GTlsInteractionClass *klass;
639   GTlsBackend *backend;
640   GError *error = NULL;
641
642   test->fixture = fixture;
643
644   test->interaction = g_object_new (TEST_TYPE_INTERACTION, NULL);
645   g_assert (TEST_IS_INTERACTION (test->interaction));
646
647   TEST_INTERACTION (test->interaction)->test = test;
648
649   klass =  G_TLS_INTERACTION_GET_CLASS (test->interaction);
650   klass->ask_password = fixture->ask_password_func;
651   klass->ask_password_async = fixture->ask_password_async_func;
652   klass->ask_password_finish = fixture->ask_password_finish_func;
653   klass->request_certificate = fixture->request_certificate_func;
654   klass->request_certificate_async = fixture->request_certificate_async_func;
655   klass->request_certificate_finish = fixture->request_certificate_finish_func;
656
657   backend = g_object_new (G_TYPE_TEST_TLS_BACKEND, NULL);
658   test->connection = g_object_new (g_tls_backend_get_server_connection_type (backend), NULL);
659   g_assert_no_error (error);
660   g_object_unref (backend);
661
662   test->password = g_tls_password_new (0, "Description");
663   test->test_thread = g_thread_self ();
664
665   /*
666    * If no loop is running then interaction should happen in the same
667    * thread that the tests are running in.
668    */
669   test->interaction_thread = test->test_thread;
670 }
671
672 static void
673 teardown_without_loop (Test            *test,
674                        gconstpointer    unused)
675 {
676   gpointer weak_pointer = test->interaction;
677
678   g_object_add_weak_pointer (weak_pointer, &weak_pointer);
679
680   g_object_unref (test->connection);
681
682   g_object_unref (test->password);
683
684   g_object_unref (test->interaction);
685
686   g_assert (weak_pointer == NULL);
687
688 }
689
690 typedef struct {
691   GMutex loop_mutex;
692   GCond loop_started;
693   gboolean started;
694   Test *test;
695 } ThreadLoop;
696
697 static gpointer
698 thread_loop (gpointer user_data)
699 {
700   GMainContext *context = g_main_context_default ();
701   ThreadLoop *closure = user_data;
702   Test *test = closure->test;
703
704   g_mutex_lock (&closure->loop_mutex);
705
706   g_assert (test->loop_thread == g_thread_self ());
707   g_assert (test->loop == NULL);
708   test->loop = g_main_loop_new (context, TRUE);
709
710   g_main_context_acquire (context);
711   closure->started = TRUE;
712   g_cond_signal (&closure->loop_started);
713   g_mutex_unlock (&closure->loop_mutex);
714
715   while (g_main_loop_is_running (test->loop))
716     g_main_context_iteration (context, TRUE);
717
718   g_main_context_release (context);
719   return test;
720 }
721
722 static void
723 setup_with_thread_loop (Test            *test,
724                         gconstpointer    user_data)
725 {
726   ThreadLoop closure;
727
728   setup_without_loop (test, user_data);
729
730   g_mutex_init (&closure.loop_mutex);
731   g_cond_init (&closure.loop_started);
732   closure.started = FALSE;
733   closure.test = test;
734
735   g_mutex_lock (&closure.loop_mutex);
736   test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
737   while (!closure.started)
738     g_cond_wait (&closure.loop_started, &closure.loop_mutex);
739   g_mutex_unlock (&closure.loop_mutex);
740
741   /*
742    * When a loop is running then interaction should always occur in the main
743    * context of that loop.
744    */
745   test->interaction_thread = test->loop_thread;
746
747   g_mutex_clear (&closure.loop_mutex);
748   g_cond_clear (&closure.loop_started);
749 }
750
751 static void
752 teardown_with_thread_loop (Test            *test,
753                            gconstpointer    unused)
754 {
755   gpointer check;
756
757   g_assert (test->loop_thread);
758   check = g_thread_join (test->loop_thread);
759   g_assert (check == test);
760   test->loop_thread = NULL;
761
762   g_main_loop_unref (test->loop);
763
764   teardown_without_loop (test, unused);
765 }
766
767 static void
768 setup_with_normal_loop (Test            *test,
769                         gconstpointer    user_data)
770 {
771   GMainContext *context;
772
773   setup_without_loop (test, user_data);
774
775   context = g_main_context_default ();
776   if (!g_main_context_acquire (context))
777     g_assert_not_reached ();
778
779   test->loop = g_main_loop_new (context, TRUE);
780   g_assert (g_main_loop_is_running (test->loop));
781 }
782
783 static void
784 teardown_with_normal_loop (Test            *test,
785                            gconstpointer    unused)
786 {
787   GMainContext *context;
788
789   context = g_main_context_default ();
790   while (g_main_loop_is_running (test->loop))
791     g_main_context_iteration (context, TRUE);
792
793   g_main_context_release (context);
794
795   /* Run test until complete */
796   g_main_loop_unref (test->loop);
797   test->loop = NULL;
798
799   teardown_without_loop (test, unused);
800 }
801
802 typedef void (*TestFunc) (Test *test, gconstpointer data);
803
804 static void
805 test_with_async_ask_password (const gchar *name,
806                               TestFunc     setup,
807                               TestFunc     func,
808                               TestFunc     teardown)
809 {
810   gchar *test_name;
811   Fixture *fixture;
812
813   /* Async implementation that succeeds */
814   fixture = g_new0 (Fixture, 1);
815   fixture->ask_password_async_func = test_interaction_ask_password_async_success;
816   fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
817   fixture->ask_password_func = NULL;
818   fixture->result = G_TLS_INTERACTION_HANDLED;
819   test_name = g_strdup_printf ("%s/async-implementation-success", name);
820   g_test_add (test_name, Test, fixture, setup, func, teardown);
821   g_free (test_name);
822   g_ptr_array_add (fixtures, fixture);
823
824   /* Async implementation that fails */
825   fixture = g_new0 (Fixture, 1);
826   fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
827   fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
828   fixture->ask_password_func = NULL;
829   fixture->result = G_TLS_INTERACTION_FAILED;
830   fixture->error_domain = G_FILE_ERROR;
831   fixture->error_code = G_FILE_ERROR_ACCES;
832   fixture->error_message = "The message";
833   test_name = g_strdup_printf ("%s/async-implementation-failure", name);
834   g_test_add (test_name, Test, fixture, setup, func, teardown);
835   g_free (test_name);
836   g_ptr_array_add (fixtures, fixture);
837 }
838
839 static void
840 test_with_unhandled_ask_password (const gchar *name,
841                                   TestFunc     setup,
842                                   TestFunc     func,
843                                   TestFunc     teardown)
844 {
845   gchar *test_name;
846   Fixture *fixture;
847
848   /* Unhandled implementation */
849   fixture = g_new0 (Fixture, 1);
850   fixture->ask_password_async_func = NULL;
851   fixture->ask_password_finish_func = NULL;
852   fixture->ask_password_func = NULL;
853   fixture->result = G_TLS_INTERACTION_UNHANDLED;
854   test_name = g_strdup_printf ("%s/unhandled-implementation", name);
855   g_test_add (test_name, Test, fixture, setup, func, teardown);
856   g_free (test_name);
857   g_ptr_array_add (fixtures, fixture);
858 }
859
860 static void
861 test_with_sync_ask_password (const gchar *name,
862                                              TestFunc     setup,
863                                              TestFunc     func,
864                                              TestFunc     teardown)
865 {
866   gchar *test_name;
867   Fixture *fixture;
868
869   /* Sync implementation that succeeds */
870   fixture = g_new0 (Fixture, 1);
871   fixture->ask_password_async_func = NULL;
872   fixture->ask_password_finish_func = NULL;
873   fixture->ask_password_func = test_interaction_ask_password_sync_success;
874   fixture->result = G_TLS_INTERACTION_HANDLED;
875   test_name = g_strdup_printf ("%s/sync-implementation-success", name);
876   g_test_add (test_name, Test, fixture, setup, func, teardown);
877   g_free (test_name);
878   g_ptr_array_add (fixtures, fixture);
879
880   /* Async implementation that fails */
881   fixture = g_new0 (Fixture, 1);
882   fixture->ask_password_async_func = NULL;
883   fixture->ask_password_finish_func = NULL;
884   fixture->ask_password_func = test_interaction_ask_password_sync_failure;
885   fixture->result = G_TLS_INTERACTION_FAILED;
886   fixture->error_domain = G_FILE_ERROR;
887   fixture->error_code = G_FILE_ERROR_ACCES;
888   fixture->error_message = "The message";
889   test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
890   g_test_add (test_name, Test, fixture, setup, func, teardown);
891   g_free (test_name);
892   g_ptr_array_add (fixtures, fixture);
893 }
894
895 static void
896 test_with_all_ask_password (const gchar *name,
897                             TestFunc setup,
898                             TestFunc func,
899                             TestFunc teardown)
900 {
901   test_with_unhandled_ask_password (name, setup, func, teardown);
902   test_with_async_ask_password (name, setup, func, teardown);
903   test_with_sync_ask_password (name, setup, func, teardown);
904 }
905
906 static void
907 test_with_async_request_certificate (const gchar *name,
908                                      TestFunc     setup,
909                                      TestFunc     func,
910                                      TestFunc     teardown)
911 {
912   gchar *test_name;
913   Fixture *fixture;
914
915   /* Async implementation that succeeds */
916   fixture = g_new0 (Fixture, 1);
917   fixture->request_certificate_async_func = test_interaction_request_certificate_async_success;
918   fixture->request_certificate_finish_func = test_interaction_request_certificate_finish_success;
919   fixture->request_certificate_func = NULL;
920   fixture->result = G_TLS_INTERACTION_HANDLED;
921   test_name = g_strdup_printf ("%s/async-implementation-success", name);
922   g_test_add (test_name, Test, fixture, setup, func, teardown);
923   g_free (test_name);
924   g_ptr_array_add (fixtures, fixture);
925
926   /* Async implementation that fails */
927   fixture = g_new0 (Fixture, 1);
928   fixture->request_certificate_async_func = test_interaction_request_certificate_async_failure;
929   fixture->request_certificate_finish_func = test_interaction_request_certificate_finish_failure;
930   fixture->request_certificate_func = NULL;
931   fixture->result = G_TLS_INTERACTION_FAILED;
932   fixture->error_domain = G_FILE_ERROR;
933   fixture->error_code = G_FILE_ERROR_NOENT;
934   fixture->error_message = "Another message";
935   test_name = g_strdup_printf ("%s/async-implementation-failure", name);
936   g_test_add (test_name, Test, fixture, setup, func, teardown);
937   g_free (test_name);
938   g_ptr_array_add (fixtures, fixture);
939 }
940
941 static void
942 test_with_unhandled_request_certificate (const gchar *name,
943                                          TestFunc     setup,
944                                          TestFunc     func,
945                                          TestFunc     teardown)
946 {
947   gchar *test_name;
948   Fixture *fixture;
949
950   /* Unhandled implementation */
951   fixture = g_new0 (Fixture, 1);
952   fixture->request_certificate_async_func = NULL;
953   fixture->request_certificate_finish_func = NULL;
954   fixture->request_certificate_func = NULL;
955   fixture->result = G_TLS_INTERACTION_UNHANDLED;
956   test_name = g_strdup_printf ("%s/unhandled-implementation", name);
957   g_test_add (test_name, Test, fixture, setup, func, teardown);
958   g_free (test_name);
959   g_ptr_array_add (fixtures, fixture);
960 }
961
962 static void
963 test_with_sync_request_certificate (const gchar *name,
964                                     TestFunc     setup,
965                                     TestFunc     func,
966                                     TestFunc     teardown)
967 {
968   gchar *test_name;
969   Fixture *fixture;
970
971   /* Sync implementation that succeeds */
972   fixture = g_new0 (Fixture, 1);
973   fixture->request_certificate_async_func = NULL;
974   fixture->request_certificate_finish_func = NULL;
975   fixture->request_certificate_func = test_interaction_request_certificate_sync_success;
976   fixture->result = G_TLS_INTERACTION_HANDLED;
977   test_name = g_strdup_printf ("%s/sync-implementation-success", name);
978   g_test_add (test_name, Test, fixture, setup, func, teardown);
979   g_free (test_name);
980   g_ptr_array_add (fixtures, fixture);
981
982   /* Async implementation that fails */
983   fixture = g_new0 (Fixture, 1);
984   fixture->request_certificate_async_func = NULL;
985   fixture->request_certificate_finish_func = NULL;
986   fixture->request_certificate_func = test_interaction_request_certificate_sync_failure;
987   fixture->result = G_TLS_INTERACTION_FAILED;
988   fixture->error_domain = G_FILE_ERROR;
989   fixture->error_code = G_FILE_ERROR_NOENT;
990   fixture->error_message = "Another message";
991   test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
992   g_test_add (test_name, Test, fixture, setup, func, teardown);
993   g_free (test_name);
994   g_ptr_array_add (fixtures, fixture);
995 }
996
997 static void
998 test_with_all_request_certificate (const gchar *name,
999                                    TestFunc setup,
1000                                    TestFunc func,
1001                                    TestFunc teardown)
1002 {
1003   test_with_unhandled_request_certificate (name, setup, func, teardown);
1004   test_with_async_request_certificate (name, setup, func, teardown);
1005   test_with_sync_request_certificate (name, setup, func, teardown);
1006 }
1007 int
1008 main (int   argc,
1009       char *argv[])
1010 {
1011   gint ret;
1012
1013   g_test_init (&argc, &argv, NULL);
1014
1015   fixtures = g_ptr_array_new_with_free_func (g_free);
1016
1017   /* Tests for g_tls_interaction_invoke_ask_password */
1018   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-with-loop",
1019                               setup_with_thread_loop, test_invoke_ask_password, teardown_with_thread_loop);
1020   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-without-loop",
1021                               setup_without_loop, test_invoke_ask_password, teardown_without_loop);
1022   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-in-loop",
1023                                               setup_with_normal_loop, test_invoke_ask_password, teardown_with_normal_loop);
1024
1025   /* Tests for g_tls_interaction_ask_password */
1026   test_with_unhandled_ask_password ("/tls-interaction/ask-password/sync",
1027                                     setup_without_loop, test_ask_password, teardown_without_loop);
1028   test_with_sync_ask_password ("/tls-interaction/ask-password/sync",
1029                                setup_without_loop, test_ask_password, teardown_without_loop);
1030
1031   /* Tests for g_tls_interaction_ask_password_async */
1032   test_with_unhandled_ask_password ("/tls-interaction/ask-password/async",
1033                                     setup_with_normal_loop, test_ask_password_async, teardown_with_normal_loop);
1034   test_with_async_ask_password ("/tls-interaction/ask-password/async",
1035                                 setup_with_normal_loop, test_ask_password_async, teardown_with_normal_loop);
1036
1037   /* Tests for g_tls_interaction_invoke_request_certificate */
1038   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-with-loop",
1039                                      setup_with_thread_loop, test_invoke_request_certificate, teardown_with_thread_loop);
1040   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-without-loop",
1041                                      setup_without_loop, test_invoke_request_certificate, teardown_without_loop);
1042   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-in-loop",
1043                               setup_with_normal_loop, test_invoke_request_certificate, teardown_with_normal_loop);
1044
1045   /* Tests for g_tls_interaction_ask_password */
1046   test_with_unhandled_request_certificate ("/tls-interaction/request-certificate/sync",
1047                                            setup_without_loop, test_request_certificate, teardown_without_loop);
1048   test_with_sync_request_certificate ("/tls-interaction/request-certificate/sync",
1049                                       setup_without_loop, test_request_certificate, teardown_without_loop);
1050
1051   /* Tests for g_tls_interaction_ask_password_async */
1052   test_with_unhandled_request_certificate ("/tls-interaction/request-certificate/async",
1053                                            setup_with_normal_loop, test_request_certificate_async, teardown_with_normal_loop);
1054   test_with_async_request_certificate ("/tls-interaction/request-certificate/async",
1055                                        setup_with_normal_loop, test_request_certificate_async, teardown_with_normal_loop);
1056
1057   ret = g_test_run();
1058   g_ptr_array_free (fixtures, TRUE);
1059   return ret;
1060 }