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