• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.1 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);
G_DEFINE_TYPE(TestInteraction,test_interaction,G_TYPE_TLS_INTERACTION)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
test_interaction_class_init(TestInteractionClass * klass)79 test_interaction_class_init (TestInteractionClass *klass)
80 {
81   /* By default no virtual methods */
82 }
83 
84 static void
test_interaction_ask_password_async_success(GTlsInteraction * interaction,GTlsPassword * password,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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
test_interaction_ask_password_finish_success(GTlsInteraction * interaction,GAsyncResult * result,GError ** error)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
test_interaction_ask_password_async_failure(GTlsInteraction * interaction,GTlsPassword * password,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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
test_interaction_ask_password_finish_failure(GTlsInteraction * interaction,GAsyncResult * result,GError ** error)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
test_interaction_ask_password_sync_success(GTlsInteraction * interaction,GTlsPassword * password,GCancellable * cancellable,GError ** error)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
test_interaction_ask_password_sync_failure(GTlsInteraction * interaction,GTlsPassword * password,GCancellable * cancellable,GError ** error)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
test_interaction_request_certificate_async_success(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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
test_interaction_request_certificate_finish_success(GTlsInteraction * interaction,GAsyncResult * result,GError ** error)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
test_interaction_request_certificate_async_failure(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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
test_interaction_request_certificate_finish_failure(GTlsInteraction * interaction,GAsyncResult * result,GError ** error)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
test_interaction_request_certificate_sync_success(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GError ** error)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
test_interaction_request_certificate_sync_failure(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GError ** error)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
on_ask_password_async_call(GObject * source,GAsyncResult * result,gpointer user_data)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
test_ask_password_async(Test * test,gconstpointer unused)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
test_invoke_ask_password(Test * test,gconstpointer unused)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
test_ask_password(Test * test,gconstpointer unused)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
on_request_certificate_async_call(GObject * source,GAsyncResult * result,gpointer user_data)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
test_request_certificate_async(Test * test,gconstpointer unused)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
test_invoke_request_certificate(Test * test,gconstpointer unused)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
test_request_certificate(Test * test,gconstpointer unused)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
setup_without_loop(Test * test,gconstpointer user_data)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
teardown_without_loop(Test * test,gconstpointer unused)673 teardown_without_loop (Test            *test,
674                        gconstpointer    unused)
675 {
676   g_object_unref (test->connection);
677   g_object_unref (test->password);
678 
679   g_assert_finalize_object (test->interaction);
680 }
681 
682 typedef struct {
683   GMutex loop_mutex;
684   GCond loop_started;
685   gboolean started;
686   Test *test;
687 } ThreadLoop;
688 
689 static gpointer
thread_loop(gpointer user_data)690 thread_loop (gpointer user_data)
691 {
692   GMainContext *context = g_main_context_default ();
693   ThreadLoop *closure = user_data;
694   Test *test = closure->test;
695 
696   g_mutex_lock (&closure->loop_mutex);
697 
698   g_assert (test->loop_thread == g_thread_self ());
699   g_assert (test->loop == NULL);
700   test->loop = g_main_loop_new (context, TRUE);
701 
702   g_main_context_acquire (context);
703   closure->started = TRUE;
704   g_cond_signal (&closure->loop_started);
705   g_mutex_unlock (&closure->loop_mutex);
706 
707   while (g_main_loop_is_running (test->loop))
708     g_main_context_iteration (context, TRUE);
709 
710   g_main_context_release (context);
711   return test;
712 }
713 
714 static void
setup_with_thread_loop(Test * test,gconstpointer user_data)715 setup_with_thread_loop (Test            *test,
716                         gconstpointer    user_data)
717 {
718   ThreadLoop closure;
719 
720   setup_without_loop (test, user_data);
721 
722   g_mutex_init (&closure.loop_mutex);
723   g_cond_init (&closure.loop_started);
724   closure.started = FALSE;
725   closure.test = test;
726 
727   g_mutex_lock (&closure.loop_mutex);
728   test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
729   while (!closure.started)
730     g_cond_wait (&closure.loop_started, &closure.loop_mutex);
731   g_mutex_unlock (&closure.loop_mutex);
732 
733   /*
734    * When a loop is running then interaction should always occur in the main
735    * context of that loop.
736    */
737   test->interaction_thread = test->loop_thread;
738 
739   g_mutex_clear (&closure.loop_mutex);
740   g_cond_clear (&closure.loop_started);
741 }
742 
743 static void
teardown_with_thread_loop(Test * test,gconstpointer unused)744 teardown_with_thread_loop (Test            *test,
745                            gconstpointer    unused)
746 {
747   gpointer check;
748 
749   g_assert (test->loop_thread);
750   check = g_thread_join (test->loop_thread);
751   g_assert (check == test);
752   test->loop_thread = NULL;
753 
754   g_main_loop_unref (test->loop);
755 
756   teardown_without_loop (test, unused);
757 }
758 
759 static void
setup_with_normal_loop(Test * test,gconstpointer user_data)760 setup_with_normal_loop (Test            *test,
761                         gconstpointer    user_data)
762 {
763   GMainContext *context;
764 
765   setup_without_loop (test, user_data);
766 
767   context = g_main_context_default ();
768   if (!g_main_context_acquire (context))
769     g_assert_not_reached ();
770 
771   test->loop = g_main_loop_new (context, TRUE);
772   g_assert (g_main_loop_is_running (test->loop));
773 }
774 
775 static void
teardown_with_normal_loop(Test * test,gconstpointer unused)776 teardown_with_normal_loop (Test            *test,
777                            gconstpointer    unused)
778 {
779   GMainContext *context;
780 
781   context = g_main_context_default ();
782   while (g_main_loop_is_running (test->loop))
783     g_main_context_iteration (context, TRUE);
784 
785   g_main_context_release (context);
786 
787   /* Run test until complete */
788   g_main_loop_unref (test->loop);
789   test->loop = NULL;
790 
791   teardown_without_loop (test, unused);
792 }
793 
794 typedef void (*TestFunc) (Test *test, gconstpointer data);
795 
796 static void
test_with_async_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)797 test_with_async_ask_password (const gchar *name,
798                               TestFunc     setup,
799                               TestFunc     func,
800                               TestFunc     teardown)
801 {
802   gchar *test_name;
803   Fixture *fixture;
804 
805   /* Async implementation that succeeds */
806   fixture = g_new0 (Fixture, 1);
807   fixture->ask_password_async_func = test_interaction_ask_password_async_success;
808   fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
809   fixture->ask_password_func = NULL;
810   fixture->result = G_TLS_INTERACTION_HANDLED;
811   test_name = g_strdup_printf ("%s/async-implementation-success", name);
812   g_test_add (test_name, Test, fixture, setup, func, teardown);
813   g_free (test_name);
814   g_ptr_array_add (fixtures, fixture);
815 
816   /* Async implementation that fails */
817   fixture = g_new0 (Fixture, 1);
818   fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
819   fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
820   fixture->ask_password_func = NULL;
821   fixture->result = G_TLS_INTERACTION_FAILED;
822   fixture->error_domain = G_FILE_ERROR;
823   fixture->error_code = G_FILE_ERROR_ACCES;
824   fixture->error_message = "The message";
825   test_name = g_strdup_printf ("%s/async-implementation-failure", name);
826   g_test_add (test_name, Test, fixture, setup, func, teardown);
827   g_free (test_name);
828   g_ptr_array_add (fixtures, fixture);
829 }
830 
831 static void
test_with_unhandled_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)832 test_with_unhandled_ask_password (const gchar *name,
833                                   TestFunc     setup,
834                                   TestFunc     func,
835                                   TestFunc     teardown)
836 {
837   gchar *test_name;
838   Fixture *fixture;
839 
840   /* Unhandled implementation */
841   fixture = g_new0 (Fixture, 1);
842   fixture->ask_password_async_func = NULL;
843   fixture->ask_password_finish_func = NULL;
844   fixture->ask_password_func = NULL;
845   fixture->result = G_TLS_INTERACTION_UNHANDLED;
846   test_name = g_strdup_printf ("%s/unhandled-implementation", name);
847   g_test_add (test_name, Test, fixture, setup, func, teardown);
848   g_free (test_name);
849   g_ptr_array_add (fixtures, fixture);
850 }
851 
852 static void
test_with_sync_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)853 test_with_sync_ask_password (const gchar *name,
854                                              TestFunc     setup,
855                                              TestFunc     func,
856                                              TestFunc     teardown)
857 {
858   gchar *test_name;
859   Fixture *fixture;
860 
861   /* Sync implementation that succeeds */
862   fixture = g_new0 (Fixture, 1);
863   fixture->ask_password_async_func = NULL;
864   fixture->ask_password_finish_func = NULL;
865   fixture->ask_password_func = test_interaction_ask_password_sync_success;
866   fixture->result = G_TLS_INTERACTION_HANDLED;
867   test_name = g_strdup_printf ("%s/sync-implementation-success", name);
868   g_test_add (test_name, Test, fixture, setup, func, teardown);
869   g_free (test_name);
870   g_ptr_array_add (fixtures, fixture);
871 
872   /* Async implementation that fails */
873   fixture = g_new0 (Fixture, 1);
874   fixture->ask_password_async_func = NULL;
875   fixture->ask_password_finish_func = NULL;
876   fixture->ask_password_func = test_interaction_ask_password_sync_failure;
877   fixture->result = G_TLS_INTERACTION_FAILED;
878   fixture->error_domain = G_FILE_ERROR;
879   fixture->error_code = G_FILE_ERROR_ACCES;
880   fixture->error_message = "The message";
881   test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
882   g_test_add (test_name, Test, fixture, setup, func, teardown);
883   g_free (test_name);
884   g_ptr_array_add (fixtures, fixture);
885 }
886 
887 static void
test_with_all_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)888 test_with_all_ask_password (const gchar *name,
889                             TestFunc setup,
890                             TestFunc func,
891                             TestFunc teardown)
892 {
893   test_with_unhandled_ask_password (name, setup, func, teardown);
894   test_with_async_ask_password (name, setup, func, teardown);
895   test_with_sync_ask_password (name, setup, func, teardown);
896 }
897 
898 static void
test_with_async_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)899 test_with_async_request_certificate (const gchar *name,
900                                      TestFunc     setup,
901                                      TestFunc     func,
902                                      TestFunc     teardown)
903 {
904   gchar *test_name;
905   Fixture *fixture;
906 
907   /* Async implementation that succeeds */
908   fixture = g_new0 (Fixture, 1);
909   fixture->request_certificate_async_func = test_interaction_request_certificate_async_success;
910   fixture->request_certificate_finish_func = test_interaction_request_certificate_finish_success;
911   fixture->request_certificate_func = NULL;
912   fixture->result = G_TLS_INTERACTION_HANDLED;
913   test_name = g_strdup_printf ("%s/async-implementation-success", name);
914   g_test_add (test_name, Test, fixture, setup, func, teardown);
915   g_free (test_name);
916   g_ptr_array_add (fixtures, fixture);
917 
918   /* Async implementation that fails */
919   fixture = g_new0 (Fixture, 1);
920   fixture->request_certificate_async_func = test_interaction_request_certificate_async_failure;
921   fixture->request_certificate_finish_func = test_interaction_request_certificate_finish_failure;
922   fixture->request_certificate_func = NULL;
923   fixture->result = G_TLS_INTERACTION_FAILED;
924   fixture->error_domain = G_FILE_ERROR;
925   fixture->error_code = G_FILE_ERROR_NOENT;
926   fixture->error_message = "Another message";
927   test_name = g_strdup_printf ("%s/async-implementation-failure", name);
928   g_test_add (test_name, Test, fixture, setup, func, teardown);
929   g_free (test_name);
930   g_ptr_array_add (fixtures, fixture);
931 }
932 
933 static void
test_with_unhandled_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)934 test_with_unhandled_request_certificate (const gchar *name,
935                                          TestFunc     setup,
936                                          TestFunc     func,
937                                          TestFunc     teardown)
938 {
939   gchar *test_name;
940   Fixture *fixture;
941 
942   /* Unhandled implementation */
943   fixture = g_new0 (Fixture, 1);
944   fixture->request_certificate_async_func = NULL;
945   fixture->request_certificate_finish_func = NULL;
946   fixture->request_certificate_func = NULL;
947   fixture->result = G_TLS_INTERACTION_UNHANDLED;
948   test_name = g_strdup_printf ("%s/unhandled-implementation", name);
949   g_test_add (test_name, Test, fixture, setup, func, teardown);
950   g_free (test_name);
951   g_ptr_array_add (fixtures, fixture);
952 }
953 
954 static void
test_with_sync_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)955 test_with_sync_request_certificate (const gchar *name,
956                                     TestFunc     setup,
957                                     TestFunc     func,
958                                     TestFunc     teardown)
959 {
960   gchar *test_name;
961   Fixture *fixture;
962 
963   /* Sync implementation that succeeds */
964   fixture = g_new0 (Fixture, 1);
965   fixture->request_certificate_async_func = NULL;
966   fixture->request_certificate_finish_func = NULL;
967   fixture->request_certificate_func = test_interaction_request_certificate_sync_success;
968   fixture->result = G_TLS_INTERACTION_HANDLED;
969   test_name = g_strdup_printf ("%s/sync-implementation-success", name);
970   g_test_add (test_name, Test, fixture, setup, func, teardown);
971   g_free (test_name);
972   g_ptr_array_add (fixtures, fixture);
973 
974   /* Async implementation that fails */
975   fixture = g_new0 (Fixture, 1);
976   fixture->request_certificate_async_func = NULL;
977   fixture->request_certificate_finish_func = NULL;
978   fixture->request_certificate_func = test_interaction_request_certificate_sync_failure;
979   fixture->result = G_TLS_INTERACTION_FAILED;
980   fixture->error_domain = G_FILE_ERROR;
981   fixture->error_code = G_FILE_ERROR_NOENT;
982   fixture->error_message = "Another message";
983   test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
984   g_test_add (test_name, Test, fixture, setup, func, teardown);
985   g_free (test_name);
986   g_ptr_array_add (fixtures, fixture);
987 }
988 
989 static void
test_with_all_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)990 test_with_all_request_certificate (const gchar *name,
991                                    TestFunc setup,
992                                    TestFunc func,
993                                    TestFunc teardown)
994 {
995   test_with_unhandled_request_certificate (name, setup, func, teardown);
996   test_with_async_request_certificate (name, setup, func, teardown);
997   test_with_sync_request_certificate (name, setup, func, teardown);
998 }
999 int
main(int argc,char * argv[])1000 main (int   argc,
1001       char *argv[])
1002 {
1003   gint ret;
1004 
1005   g_test_init (&argc, &argv, NULL);
1006 
1007   fixtures = g_ptr_array_new_with_free_func (g_free);
1008 
1009   /* Tests for g_tls_interaction_invoke_ask_password */
1010   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-with-loop",
1011                               setup_with_thread_loop, test_invoke_ask_password, teardown_with_thread_loop);
1012   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-without-loop",
1013                               setup_without_loop, test_invoke_ask_password, teardown_without_loop);
1014   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-in-loop",
1015                                               setup_with_normal_loop, test_invoke_ask_password, teardown_with_normal_loop);
1016 
1017   /* Tests for g_tls_interaction_ask_password */
1018   test_with_unhandled_ask_password ("/tls-interaction/ask-password/sync",
1019                                     setup_without_loop, test_ask_password, teardown_without_loop);
1020   test_with_sync_ask_password ("/tls-interaction/ask-password/sync",
1021                                setup_without_loop, test_ask_password, teardown_without_loop);
1022 
1023   /* Tests for g_tls_interaction_ask_password_async */
1024   test_with_unhandled_ask_password ("/tls-interaction/ask-password/async",
1025                                     setup_with_normal_loop, test_ask_password_async, teardown_with_normal_loop);
1026   test_with_async_ask_password ("/tls-interaction/ask-password/async",
1027                                 setup_with_normal_loop, test_ask_password_async, teardown_with_normal_loop);
1028 
1029   /* Tests for g_tls_interaction_invoke_request_certificate */
1030   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-with-loop",
1031                                      setup_with_thread_loop, test_invoke_request_certificate, teardown_with_thread_loop);
1032   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-without-loop",
1033                                      setup_without_loop, test_invoke_request_certificate, teardown_without_loop);
1034   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-in-loop",
1035                               setup_with_normal_loop, test_invoke_request_certificate, teardown_with_normal_loop);
1036 
1037   /* Tests for g_tls_interaction_ask_password */
1038   test_with_unhandled_request_certificate ("/tls-interaction/request-certificate/sync",
1039                                            setup_without_loop, test_request_certificate, teardown_without_loop);
1040   test_with_sync_request_certificate ("/tls-interaction/request-certificate/sync",
1041                                       setup_without_loop, test_request_certificate, teardown_without_loop);
1042 
1043   /* Tests for g_tls_interaction_ask_password_async */
1044   test_with_unhandled_request_certificate ("/tls-interaction/request-certificate/async",
1045                                            setup_with_normal_loop, test_request_certificate_async, teardown_with_normal_loop);
1046   test_with_async_request_certificate ("/tls-interaction/request-certificate/async",
1047                                        setup_with_normal_loop, test_request_certificate_async, teardown_with_normal_loop);
1048 
1049   ret = g_test_run();
1050   g_ptr_array_free (fixtures, TRUE);
1051   return ret;
1052 }
1053