• 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 /* Return a copy of @str that is allocated in a silly way, to exercise
178  * custom free-functions. The returned pointer points to a copy of @str
179  * in a buffer of the form "BEFORE \0 str \0 AFTER". */
180 static guchar *
special_dup(const char * str)181 special_dup (const char *str)
182 {
183   GString *buf = g_string_new ("BEFORE");
184   guchar *ret;
185 
186   g_string_append_c (buf, '\0');
187   g_string_append (buf, str);
188   g_string_append_c (buf, '\0');
189   g_string_append (buf, "AFTER");
190   ret = (guchar *) g_string_free (buf, FALSE);
191   return ret + strlen ("BEFORE") + 1;
192 }
193 
194 
195 /* Free a copy of @str that was made with special_dup(), after asserting
196  * that it has not been corrupted. */
197 static void
special_free(gpointer p)198 special_free (gpointer p)
199 {
200   gchar *s = p;
201   gchar *buf = s - strlen ("BEFORE") - 1;
202 
203   g_assert_cmpstr (buf, ==, "BEFORE");
204   g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER");
205   g_free (buf);
206 }
207 
208 
209 static GTlsInteractionResult
test_interaction_ask_password_sync_success(GTlsInteraction * interaction,GTlsPassword * password,GCancellable * cancellable,GError ** error)210 test_interaction_ask_password_sync_success (GTlsInteraction    *interaction,
211                                             GTlsPassword       *password,
212                                             GCancellable       *cancellable,
213                                             GError            **error)
214 {
215   TestInteraction *self;
216   const guchar *value;
217   gsize len;
218 
219   g_assert (TEST_IS_INTERACTION (interaction));
220   self = TEST_INTERACTION (interaction);
221 
222   g_assert (g_thread_self () == self->test->interaction_thread);
223 
224   g_assert (G_IS_TLS_PASSWORD (password));
225   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
226   g_assert (error != NULL);
227   g_assert (*error == NULL);
228 
229   /* Exercise different ways to set the value */
230   g_tls_password_set_value (password, (const guchar *) "foo", 4);
231   len = 0;
232   value = g_tls_password_get_value (password, &len);
233   g_assert_cmpmem (value, len, "foo", 4);
234 
235   g_tls_password_set_value (password, (const guchar *) "bar", -1);
236   len = 0;
237   value = g_tls_password_get_value (password, &len);
238   g_assert_cmpmem (value, len, "bar", 3);
239 
240   g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free);
241   len = 0;
242   value = g_tls_password_get_value (password, &len);
243   g_assert_cmpmem (value, len, "baa", 4);
244 
245   g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free);
246   len = 0;
247   value = g_tls_password_get_value (password, &len);
248   g_assert_cmpmem (value, len, "baz", 3);
249 
250   /* Don't do this in real life. Include a null terminator for testing */
251   g_tls_password_set_value (password, (const guchar *)"the password", 13);
252   return G_TLS_INTERACTION_HANDLED;
253 }
254 
255 static GTlsInteractionResult
test_interaction_ask_password_sync_failure(GTlsInteraction * interaction,GTlsPassword * password,GCancellable * cancellable,GError ** error)256 test_interaction_ask_password_sync_failure (GTlsInteraction    *interaction,
257                                             GTlsPassword       *password,
258                                             GCancellable       *cancellable,
259                                             GError            **error)
260 {
261   TestInteraction *self;
262 
263   g_assert (TEST_IS_INTERACTION (interaction));
264   self = TEST_INTERACTION (interaction);
265 
266   g_assert (g_thread_self () == self->test->interaction_thread);
267 
268   g_assert (G_IS_TLS_PASSWORD (password));
269   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
270   g_assert (error != NULL);
271   g_assert (*error == NULL);
272 
273   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
274   return G_TLS_INTERACTION_FAILED;
275 }
276 
277 static void
test_interaction_request_certificate_async_success(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)278 test_interaction_request_certificate_async_success (GTlsInteraction    *interaction,
279                                                     GTlsConnection     *connection,
280                                                     gint                unused_flags,
281                                                     GCancellable       *cancellable,
282                                                     GAsyncReadyCallback callback,
283                                                     gpointer            user_data)
284 {
285   GTask *task;
286   TestInteraction *self;
287 
288   g_assert (TEST_IS_INTERACTION (interaction));
289   self = TEST_INTERACTION (interaction);
290 
291   g_assert (g_thread_self () == self->test->interaction_thread);
292 
293   g_assert (G_IS_TLS_CONNECTION (connection));
294   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
295   g_assert (unused_flags == 0);
296 
297   task = g_task_new (self, cancellable, callback, user_data);
298 
299   /*
300    * IRL would call g_tls_connection_set_certificate(). But here just touch
301    * the connection in a detectable way.
302    */
303   g_object_set_data (G_OBJECT (connection), "chosen-certificate", "my-certificate");
304   g_task_return_int (task, G_TLS_INTERACTION_HANDLED);
305   g_object_unref (task);
306 }
307 
308 static GTlsInteractionResult
test_interaction_request_certificate_finish_success(GTlsInteraction * interaction,GAsyncResult * result,GError ** error)309 test_interaction_request_certificate_finish_success (GTlsInteraction    *interaction,
310                                                      GAsyncResult       *result,
311                                                      GError            **error)
312 {
313   TestInteraction *self;
314 
315   g_assert (TEST_IS_INTERACTION (interaction));
316   self = TEST_INTERACTION (interaction);
317 
318   g_assert (g_thread_self () == self->test->interaction_thread);
319 
320   g_assert (g_task_is_valid (result, interaction));
321   g_assert (error != NULL);
322   g_assert (*error == NULL);
323 
324   return g_task_propagate_int (G_TASK (result), error);
325 }
326 
327 static void
test_interaction_request_certificate_async_failure(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)328 test_interaction_request_certificate_async_failure (GTlsInteraction    *interaction,
329                                                     GTlsConnection     *connection,
330                                                     gint                unused_flags,
331                                                     GCancellable       *cancellable,
332                                                     GAsyncReadyCallback callback,
333                                                     gpointer            user_data)
334 {
335   GTask *task;
336   TestInteraction *self;
337 
338   g_assert (TEST_IS_INTERACTION (interaction));
339   self = TEST_INTERACTION (interaction);
340 
341   g_assert (g_thread_self () == self->test->interaction_thread);
342 
343   g_assert (G_IS_TLS_CONNECTION (connection));
344   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
345   g_assert (unused_flags == 0);
346 
347   task = g_task_new (self, cancellable, callback, user_data);
348 
349   g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Another message");
350   g_object_unref (task);
351 }
352 
353 static GTlsInteractionResult
test_interaction_request_certificate_finish_failure(GTlsInteraction * interaction,GAsyncResult * result,GError ** error)354 test_interaction_request_certificate_finish_failure (GTlsInteraction    *interaction,
355                                                      GAsyncResult       *result,
356                                                      GError            **error)
357 {
358   TestInteraction *self;
359 
360   g_assert (TEST_IS_INTERACTION (interaction));
361   self = TEST_INTERACTION (interaction);
362 
363   g_assert (g_thread_self () == self->test->interaction_thread);
364 
365   g_assert (g_task_is_valid (result, interaction));
366   g_assert (error != NULL);
367   g_assert (*error == NULL);
368 
369   if (g_task_propagate_int (G_TASK (result), error) != -1)
370     g_assert_not_reached ();
371 
372   return G_TLS_INTERACTION_FAILED;
373 }
374 
375 static GTlsInteractionResult
test_interaction_request_certificate_sync_success(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GError ** error)376 test_interaction_request_certificate_sync_success (GTlsInteraction    *interaction,
377                                                    GTlsConnection      *connection,
378                                                    gint                 unused_flags,
379                                                    GCancellable        *cancellable,
380                                                    GError             **error)
381 {
382   TestInteraction *self;
383 
384   g_assert (TEST_IS_INTERACTION (interaction));
385   self = TEST_INTERACTION (interaction);
386 
387   g_assert (g_thread_self () == self->test->interaction_thread);
388 
389   g_assert (G_IS_TLS_CONNECTION (connection));
390   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
391   g_assert (error != NULL);
392   g_assert (*error == NULL);
393 
394   /*
395    * IRL would call g_tls_connection_set_certificate(). But here just touch
396    * the connection in a detectable way.
397    */
398   g_object_set_data (G_OBJECT (connection), "chosen-certificate", "my-certificate");
399   return G_TLS_INTERACTION_HANDLED;
400 }
401 
402 static GTlsInteractionResult
test_interaction_request_certificate_sync_failure(GTlsInteraction * interaction,GTlsConnection * connection,gint unused_flags,GCancellable * cancellable,GError ** error)403 test_interaction_request_certificate_sync_failure (GTlsInteraction    *interaction,
404                                                    GTlsConnection     *connection,
405                                                    gint                unused_flags,
406                                                    GCancellable       *cancellable,
407                                                    GError            **error)
408 {
409   TestInteraction *self;
410 
411   g_assert (TEST_IS_INTERACTION (interaction));
412   self = TEST_INTERACTION (interaction);
413 
414   g_assert (g_thread_self () == self->test->interaction_thread);
415 
416   g_assert (G_IS_TLS_CONNECTION (connection));
417   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
418   g_assert (unused_flags == 0);
419   g_assert (error != NULL);
420   g_assert (*error == NULL);
421 
422   g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Another message");
423   return G_TLS_INTERACTION_FAILED;
424 }
425 
426 /* ----------------------------------------------------------------------------
427  * ACTUAL TESTS
428  */
429 
430 static void
on_ask_password_async_call(GObject * source,GAsyncResult * result,gpointer user_data)431 on_ask_password_async_call (GObject      *source,
432                             GAsyncResult *result,
433                             gpointer      user_data)
434 {
435   Test *test = user_data;
436   GTlsInteractionResult res;
437   GError *error = NULL;
438 
439   g_assert (G_IS_TLS_INTERACTION (source));
440   g_assert (G_TLS_INTERACTION (source) == test->interaction);
441 
442   /* Check that this callback is being run in the right place */
443   g_assert (g_thread_self () == test->interaction_thread);
444 
445   res = g_tls_interaction_ask_password_finish (test->interaction, result,
446                                                &error);
447 
448   /* Check that the results match the fixture */
449   g_assert_cmpuint (test->fixture->result, ==, res);
450   switch (test->fixture->result)
451     {
452       case G_TLS_INTERACTION_HANDLED:
453         g_assert_no_error (error);
454         g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
455         break;
456       case G_TLS_INTERACTION_FAILED:
457         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
458         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
459         g_clear_error (&error);
460         break;
461       case G_TLS_INTERACTION_UNHANDLED:
462         g_assert_no_error (error);
463         break;
464       default:
465         g_assert_not_reached ();
466     }
467 
468   /* Signal the end of the test */
469   g_main_loop_quit (test->loop);
470 }
471 
472 static void
test_ask_password_async(Test * test,gconstpointer unused)473 test_ask_password_async (Test            *test,
474                          gconstpointer    unused)
475 {
476   /* This test only works with a main loop */
477   g_assert (test->loop);
478 
479   g_tls_interaction_ask_password_async (test->interaction,
480                                         test->password, NULL,
481                                         on_ask_password_async_call,
482                                         test);
483 
484   /* teardown waits until g_main_loop_quit(). called from callback */
485 }
486 
487 static void
test_invoke_ask_password(Test * test,gconstpointer unused)488 test_invoke_ask_password (Test         *test,
489                           gconstpointer unused)
490 {
491   GTlsInteractionResult res;
492   GError *error = NULL;
493 
494   res = g_tls_interaction_invoke_ask_password (test->interaction, test->password,
495                                                NULL, &error);
496 
497   /* Check that the results match the fixture */
498   g_assert_cmpuint (test->fixture->result, ==, res);
499   switch (test->fixture->result)
500     {
501       case G_TLS_INTERACTION_HANDLED:
502         g_assert_no_error (error);
503         g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
504         break;
505       case G_TLS_INTERACTION_FAILED:
506         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
507         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
508         g_clear_error (&error);
509         break;
510       case G_TLS_INTERACTION_UNHANDLED:
511         g_assert_no_error (error);
512         break;
513       default:
514         g_assert_not_reached ();
515     }
516 
517   /* This allows teardown to stop if running with loop */
518   if (test->loop)
519     g_main_loop_quit (test->loop);
520 }
521 
522 static void
test_ask_password(Test * test,gconstpointer unused)523 test_ask_password (Test         *test,
524                    gconstpointer unused)
525 {
526   GTlsInteractionResult res;
527   GError *error = NULL;
528 
529   res = g_tls_interaction_ask_password (test->interaction, test->password,
530                                         NULL, &error);
531 
532   /* Check that the results match the fixture */
533   g_assert_cmpuint (test->fixture->result, ==, res);
534   switch (test->fixture->result)
535     {
536       case G_TLS_INTERACTION_HANDLED:
537         g_assert_no_error (error);
538         g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
539         break;
540       case G_TLS_INTERACTION_FAILED:
541         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
542         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
543         g_clear_error (&error);
544         break;
545       case G_TLS_INTERACTION_UNHANDLED:
546         g_assert_no_error (error);
547         break;
548       default:
549         g_assert_not_reached ();
550     }
551 
552   /* This allows teardown to stop if running with loop */
553   if (test->loop)
554     g_main_loop_quit (test->loop);
555 }
556 
557 static void
on_request_certificate_async_call(GObject * source,GAsyncResult * result,gpointer user_data)558 on_request_certificate_async_call (GObject      *source,
559                                    GAsyncResult *result,
560                                    gpointer      user_data)
561 {
562   Test *test = user_data;
563   GTlsInteractionResult res;
564   GError *error = NULL;
565 
566   g_assert (G_IS_TLS_INTERACTION (source));
567   g_assert (G_TLS_INTERACTION (source) == test->interaction);
568 
569   /* Check that this callback is being run in the right place */
570   g_assert (g_thread_self () == test->interaction_thread);
571 
572   res = g_tls_interaction_request_certificate_finish (test->interaction, result, &error);
573 
574   /* Check that the results match the fixture */
575   g_assert_cmpuint (test->fixture->result, ==, res);
576   switch (test->fixture->result)
577     {
578       case G_TLS_INTERACTION_HANDLED:
579         g_assert_no_error (error);
580         g_assert_cmpstr (g_object_get_data (G_OBJECT (test->connection), "chosen-certificate"), ==, "my-certificate");
581         break;
582       case G_TLS_INTERACTION_FAILED:
583         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
584         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
585         g_clear_error (&error);
586         break;
587       case G_TLS_INTERACTION_UNHANDLED:
588         g_assert_no_error (error);
589         break;
590       default:
591         g_assert_not_reached ();
592     }
593 
594   /* Signal the end of the test */
595   g_main_loop_quit (test->loop);
596 }
597 
598 static void
test_request_certificate_async(Test * test,gconstpointer unused)599 test_request_certificate_async (Test            *test,
600                                 gconstpointer    unused)
601 {
602   /* This test only works with a main loop */
603   g_assert (test->loop);
604 
605   g_tls_interaction_request_certificate_async (test->interaction,
606                                                test->connection, 0, NULL,
607                                                on_request_certificate_async_call,
608                                                test);
609 
610   /* teardown waits until g_main_loop_quit(). called from callback */
611 }
612 
613 static void
test_invoke_request_certificate(Test * test,gconstpointer unused)614 test_invoke_request_certificate (Test         *test,
615                                  gconstpointer unused)
616 {
617   GTlsInteractionResult res;
618   GError *error = NULL;
619 
620   res = g_tls_interaction_invoke_request_certificate (test->interaction,
621                                                       test->connection,
622                                                       0, NULL, &error);
623 
624   /* Check that the results match the fixture */
625   g_assert_cmpuint (test->fixture->result, ==, res);
626   switch (test->fixture->result)
627     {
628       case G_TLS_INTERACTION_HANDLED:
629         g_assert_no_error (error);
630         g_assert_cmpstr (g_object_get_data (G_OBJECT (test->connection), "chosen-certificate"), ==, "my-certificate");
631         break;
632       case G_TLS_INTERACTION_FAILED:
633         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
634         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
635         g_clear_error (&error);
636         break;
637       case G_TLS_INTERACTION_UNHANDLED:
638         g_assert_no_error (error);
639         break;
640       default:
641         g_assert_not_reached ();
642     }
643 
644   /* This allows teardown to stop if running with loop */
645   if (test->loop)
646     g_main_loop_quit (test->loop);
647 }
648 
649 static void
test_request_certificate(Test * test,gconstpointer unused)650 test_request_certificate (Test         *test,
651                           gconstpointer unused)
652 {
653   GTlsInteractionResult res;
654   GError *error = NULL;
655 
656   res = g_tls_interaction_request_certificate (test->interaction, test->connection,
657                                                0, NULL, &error);
658 
659   /* Check that the results match the fixture */
660   g_assert_cmpuint (test->fixture->result, ==, res);
661   switch (test->fixture->result)
662     {
663       case G_TLS_INTERACTION_HANDLED:
664         g_assert_no_error (error);
665         g_assert_cmpstr (g_object_get_data (G_OBJECT (test->connection), "chosen-certificate"), ==, "my-certificate");
666         break;
667       case G_TLS_INTERACTION_FAILED:
668         g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
669         g_assert_cmpstr (error->message, ==, test->fixture->error_message);
670         g_clear_error (&error);
671         break;
672       case G_TLS_INTERACTION_UNHANDLED:
673         g_assert_no_error (error);
674         break;
675       default:
676         g_assert_not_reached ();
677     }
678 
679   /* This allows teardown to stop if running with loop */
680   if (test->loop)
681     g_main_loop_quit (test->loop);
682 }
683 
684 /* ----------------------------------------------------------------------------
685  * TEST SETUP
686  */
687 
688 static void
setup_without_loop(Test * test,gconstpointer user_data)689 setup_without_loop (Test           *test,
690                     gconstpointer   user_data)
691 {
692   const Fixture *fixture = user_data;
693   GTlsInteractionClass *klass;
694   GTlsBackend *backend;
695   GError *error = NULL;
696 
697   test->fixture = fixture;
698 
699   test->interaction = g_object_new (TEST_TYPE_INTERACTION, NULL);
700   g_assert (TEST_IS_INTERACTION (test->interaction));
701 
702   TEST_INTERACTION (test->interaction)->test = test;
703 
704   klass =  G_TLS_INTERACTION_GET_CLASS (test->interaction);
705   klass->ask_password = fixture->ask_password_func;
706   klass->ask_password_async = fixture->ask_password_async_func;
707   klass->ask_password_finish = fixture->ask_password_finish_func;
708   klass->request_certificate = fixture->request_certificate_func;
709   klass->request_certificate_async = fixture->request_certificate_async_func;
710   klass->request_certificate_finish = fixture->request_certificate_finish_func;
711 
712   backend = g_object_new (G_TYPE_TEST_TLS_BACKEND, NULL);
713   test->connection = g_object_new (g_tls_backend_get_server_connection_type (backend), NULL);
714   g_assert_no_error (error);
715   g_object_unref (backend);
716 
717   test->password = g_tls_password_new (0, "Description");
718   test->test_thread = g_thread_self ();
719 
720   /*
721    * If no loop is running then interaction should happen in the same
722    * thread that the tests are running in.
723    */
724   test->interaction_thread = test->test_thread;
725 }
726 
727 static void
teardown_without_loop(Test * test,gconstpointer unused)728 teardown_without_loop (Test            *test,
729                        gconstpointer    unused)
730 {
731   g_object_unref (test->connection);
732   g_object_unref (test->password);
733 
734   g_assert_finalize_object (test->interaction);
735 }
736 
737 typedef struct {
738   GMutex loop_mutex;
739   GCond loop_started;
740   gboolean started;
741   Test *test;
742 } ThreadLoop;
743 
744 static gpointer
thread_loop(gpointer user_data)745 thread_loop (gpointer user_data)
746 {
747   GMainContext *context = g_main_context_default ();
748   ThreadLoop *closure = user_data;
749   Test *test = closure->test;
750 
751   g_mutex_lock (&closure->loop_mutex);
752 
753   g_assert (test->loop_thread == g_thread_self ());
754   g_assert (test->loop == NULL);
755   test->loop = g_main_loop_new (context, TRUE);
756 
757   g_main_context_acquire (context);
758   closure->started = TRUE;
759   g_cond_signal (&closure->loop_started);
760   g_mutex_unlock (&closure->loop_mutex);
761 
762   while (g_main_loop_is_running (test->loop))
763     g_main_context_iteration (context, TRUE);
764 
765   g_main_context_release (context);
766   return test;
767 }
768 
769 static void
setup_with_thread_loop(Test * test,gconstpointer user_data)770 setup_with_thread_loop (Test            *test,
771                         gconstpointer    user_data)
772 {
773   ThreadLoop closure;
774 
775   setup_without_loop (test, user_data);
776 
777   g_mutex_init (&closure.loop_mutex);
778   g_cond_init (&closure.loop_started);
779   closure.started = FALSE;
780   closure.test = test;
781 
782   g_mutex_lock (&closure.loop_mutex);
783   test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
784   while (!closure.started)
785     g_cond_wait (&closure.loop_started, &closure.loop_mutex);
786   g_mutex_unlock (&closure.loop_mutex);
787 
788   /*
789    * When a loop is running then interaction should always occur in the main
790    * context of that loop.
791    */
792   test->interaction_thread = test->loop_thread;
793 
794   g_mutex_clear (&closure.loop_mutex);
795   g_cond_clear (&closure.loop_started);
796 }
797 
798 static void
teardown_with_thread_loop(Test * test,gconstpointer unused)799 teardown_with_thread_loop (Test            *test,
800                            gconstpointer    unused)
801 {
802   gpointer check;
803 
804   g_assert (test->loop_thread);
805   check = g_thread_join (test->loop_thread);
806   g_assert (check == test);
807   test->loop_thread = NULL;
808 
809   g_main_loop_unref (test->loop);
810 
811   teardown_without_loop (test, unused);
812 }
813 
814 static void
setup_with_normal_loop(Test * test,gconstpointer user_data)815 setup_with_normal_loop (Test            *test,
816                         gconstpointer    user_data)
817 {
818   GMainContext *context;
819 
820   setup_without_loop (test, user_data);
821 
822   context = g_main_context_default ();
823   if (!g_main_context_acquire (context))
824     g_assert_not_reached ();
825 
826   test->loop = g_main_loop_new (context, TRUE);
827   g_assert (g_main_loop_is_running (test->loop));
828 }
829 
830 static void
teardown_with_normal_loop(Test * test,gconstpointer unused)831 teardown_with_normal_loop (Test            *test,
832                            gconstpointer    unused)
833 {
834   GMainContext *context;
835 
836   context = g_main_context_default ();
837   while (g_main_loop_is_running (test->loop))
838     g_main_context_iteration (context, TRUE);
839 
840   g_main_context_release (context);
841 
842   /* Run test until complete */
843   g_main_loop_unref (test->loop);
844   test->loop = NULL;
845 
846   teardown_without_loop (test, unused);
847 }
848 
849 typedef void (*TestFunc) (Test *test, gconstpointer data);
850 
851 static void
test_with_async_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)852 test_with_async_ask_password (const gchar *name,
853                               TestFunc     setup,
854                               TestFunc     func,
855                               TestFunc     teardown)
856 {
857   gchar *test_name;
858   Fixture *fixture;
859 
860   /* Async implementation that succeeds */
861   fixture = g_new0 (Fixture, 1);
862   fixture->ask_password_async_func = test_interaction_ask_password_async_success;
863   fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
864   fixture->ask_password_func = NULL;
865   fixture->result = G_TLS_INTERACTION_HANDLED;
866   test_name = g_strdup_printf ("%s/async-implementation-success", name);
867   g_test_add (test_name, Test, fixture, setup, func, teardown);
868   g_free (test_name);
869   g_ptr_array_add (fixtures, fixture);
870 
871   /* Async implementation that fails */
872   fixture = g_new0 (Fixture, 1);
873   fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
874   fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
875   fixture->ask_password_func = NULL;
876   fixture->result = G_TLS_INTERACTION_FAILED;
877   fixture->error_domain = G_FILE_ERROR;
878   fixture->error_code = G_FILE_ERROR_ACCES;
879   fixture->error_message = "The message";
880   test_name = g_strdup_printf ("%s/async-implementation-failure", name);
881   g_test_add (test_name, Test, fixture, setup, func, teardown);
882   g_free (test_name);
883   g_ptr_array_add (fixtures, fixture);
884 }
885 
886 static void
test_with_unhandled_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)887 test_with_unhandled_ask_password (const gchar *name,
888                                   TestFunc     setup,
889                                   TestFunc     func,
890                                   TestFunc     teardown)
891 {
892   gchar *test_name;
893   Fixture *fixture;
894 
895   /* Unhandled implementation */
896   fixture = g_new0 (Fixture, 1);
897   fixture->ask_password_async_func = NULL;
898   fixture->ask_password_finish_func = NULL;
899   fixture->ask_password_func = NULL;
900   fixture->result = G_TLS_INTERACTION_UNHANDLED;
901   test_name = g_strdup_printf ("%s/unhandled-implementation", name);
902   g_test_add (test_name, Test, fixture, setup, func, teardown);
903   g_free (test_name);
904   g_ptr_array_add (fixtures, fixture);
905 }
906 
907 static void
test_with_sync_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)908 test_with_sync_ask_password (const gchar *name,
909                                              TestFunc     setup,
910                                              TestFunc     func,
911                                              TestFunc     teardown)
912 {
913   gchar *test_name;
914   Fixture *fixture;
915 
916   /* Sync implementation that succeeds */
917   fixture = g_new0 (Fixture, 1);
918   fixture->ask_password_async_func = NULL;
919   fixture->ask_password_finish_func = NULL;
920   fixture->ask_password_func = test_interaction_ask_password_sync_success;
921   fixture->result = G_TLS_INTERACTION_HANDLED;
922   test_name = g_strdup_printf ("%s/sync-implementation-success", name);
923   g_test_add (test_name, Test, fixture, setup, func, teardown);
924   g_free (test_name);
925   g_ptr_array_add (fixtures, fixture);
926 
927   /* Async implementation that fails */
928   fixture = g_new0 (Fixture, 1);
929   fixture->ask_password_async_func = NULL;
930   fixture->ask_password_finish_func = NULL;
931   fixture->ask_password_func = test_interaction_ask_password_sync_failure;
932   fixture->result = G_TLS_INTERACTION_FAILED;
933   fixture->error_domain = G_FILE_ERROR;
934   fixture->error_code = G_FILE_ERROR_ACCES;
935   fixture->error_message = "The message";
936   test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
937   g_test_add (test_name, Test, fixture, setup, func, teardown);
938   g_free (test_name);
939   g_ptr_array_add (fixtures, fixture);
940 }
941 
942 static void
test_with_all_ask_password(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)943 test_with_all_ask_password (const gchar *name,
944                             TestFunc setup,
945                             TestFunc func,
946                             TestFunc teardown)
947 {
948   test_with_unhandled_ask_password (name, setup, func, teardown);
949   test_with_async_ask_password (name, setup, func, teardown);
950   test_with_sync_ask_password (name, setup, func, teardown);
951 }
952 
953 static void
test_with_async_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)954 test_with_async_request_certificate (const gchar *name,
955                                      TestFunc     setup,
956                                      TestFunc     func,
957                                      TestFunc     teardown)
958 {
959   gchar *test_name;
960   Fixture *fixture;
961 
962   /* Async implementation that succeeds */
963   fixture = g_new0 (Fixture, 1);
964   fixture->request_certificate_async_func = test_interaction_request_certificate_async_success;
965   fixture->request_certificate_finish_func = test_interaction_request_certificate_finish_success;
966   fixture->request_certificate_func = NULL;
967   fixture->result = G_TLS_INTERACTION_HANDLED;
968   test_name = g_strdup_printf ("%s/async-implementation-success", name);
969   g_test_add (test_name, Test, fixture, setup, func, teardown);
970   g_free (test_name);
971   g_ptr_array_add (fixtures, fixture);
972 
973   /* Async implementation that fails */
974   fixture = g_new0 (Fixture, 1);
975   fixture->request_certificate_async_func = test_interaction_request_certificate_async_failure;
976   fixture->request_certificate_finish_func = test_interaction_request_certificate_finish_failure;
977   fixture->request_certificate_func = NULL;
978   fixture->result = G_TLS_INTERACTION_FAILED;
979   fixture->error_domain = G_FILE_ERROR;
980   fixture->error_code = G_FILE_ERROR_NOENT;
981   fixture->error_message = "Another message";
982   test_name = g_strdup_printf ("%s/async-implementation-failure", name);
983   g_test_add (test_name, Test, fixture, setup, func, teardown);
984   g_free (test_name);
985   g_ptr_array_add (fixtures, fixture);
986 }
987 
988 static void
test_with_unhandled_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)989 test_with_unhandled_request_certificate (const gchar *name,
990                                          TestFunc     setup,
991                                          TestFunc     func,
992                                          TestFunc     teardown)
993 {
994   gchar *test_name;
995   Fixture *fixture;
996 
997   /* Unhandled implementation */
998   fixture = g_new0 (Fixture, 1);
999   fixture->request_certificate_async_func = NULL;
1000   fixture->request_certificate_finish_func = NULL;
1001   fixture->request_certificate_func = NULL;
1002   fixture->result = G_TLS_INTERACTION_UNHANDLED;
1003   test_name = g_strdup_printf ("%s/unhandled-implementation", name);
1004   g_test_add (test_name, Test, fixture, setup, func, teardown);
1005   g_free (test_name);
1006   g_ptr_array_add (fixtures, fixture);
1007 }
1008 
1009 static void
test_with_sync_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)1010 test_with_sync_request_certificate (const gchar *name,
1011                                     TestFunc     setup,
1012                                     TestFunc     func,
1013                                     TestFunc     teardown)
1014 {
1015   gchar *test_name;
1016   Fixture *fixture;
1017 
1018   /* Sync implementation that succeeds */
1019   fixture = g_new0 (Fixture, 1);
1020   fixture->request_certificate_async_func = NULL;
1021   fixture->request_certificate_finish_func = NULL;
1022   fixture->request_certificate_func = test_interaction_request_certificate_sync_success;
1023   fixture->result = G_TLS_INTERACTION_HANDLED;
1024   test_name = g_strdup_printf ("%s/sync-implementation-success", name);
1025   g_test_add (test_name, Test, fixture, setup, func, teardown);
1026   g_free (test_name);
1027   g_ptr_array_add (fixtures, fixture);
1028 
1029   /* Async implementation that fails */
1030   fixture = g_new0 (Fixture, 1);
1031   fixture->request_certificate_async_func = NULL;
1032   fixture->request_certificate_finish_func = NULL;
1033   fixture->request_certificate_func = test_interaction_request_certificate_sync_failure;
1034   fixture->result = G_TLS_INTERACTION_FAILED;
1035   fixture->error_domain = G_FILE_ERROR;
1036   fixture->error_code = G_FILE_ERROR_NOENT;
1037   fixture->error_message = "Another message";
1038   test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
1039   g_test_add (test_name, Test, fixture, setup, func, teardown);
1040   g_free (test_name);
1041   g_ptr_array_add (fixtures, fixture);
1042 }
1043 
1044 static void
test_with_all_request_certificate(const gchar * name,TestFunc setup,TestFunc func,TestFunc teardown)1045 test_with_all_request_certificate (const gchar *name,
1046                                    TestFunc setup,
1047                                    TestFunc func,
1048                                    TestFunc teardown)
1049 {
1050   test_with_unhandled_request_certificate (name, setup, func, teardown);
1051   test_with_async_request_certificate (name, setup, func, teardown);
1052   test_with_sync_request_certificate (name, setup, func, teardown);
1053 }
1054 int
main(int argc,char * argv[])1055 main (int   argc,
1056       char *argv[])
1057 {
1058   gint ret;
1059 
1060   g_test_init (&argc, &argv, NULL);
1061 
1062   fixtures = g_ptr_array_new_with_free_func (g_free);
1063 
1064   /* Tests for g_tls_interaction_invoke_ask_password */
1065   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-with-loop",
1066                               setup_with_thread_loop, test_invoke_ask_password, teardown_with_thread_loop);
1067   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-without-loop",
1068                               setup_without_loop, test_invoke_ask_password, teardown_without_loop);
1069   test_with_all_ask_password ("/tls-interaction/ask-password/invoke-in-loop",
1070                                               setup_with_normal_loop, test_invoke_ask_password, teardown_with_normal_loop);
1071 
1072   /* Tests for g_tls_interaction_ask_password */
1073   test_with_unhandled_ask_password ("/tls-interaction/ask-password/sync",
1074                                     setup_without_loop, test_ask_password, teardown_without_loop);
1075   test_with_sync_ask_password ("/tls-interaction/ask-password/sync",
1076                                setup_without_loop, test_ask_password, teardown_without_loop);
1077 
1078   /* Tests for g_tls_interaction_ask_password_async */
1079   test_with_unhandled_ask_password ("/tls-interaction/ask-password/async",
1080                                     setup_with_normal_loop, test_ask_password_async, teardown_with_normal_loop);
1081   test_with_async_ask_password ("/tls-interaction/ask-password/async",
1082                                 setup_with_normal_loop, test_ask_password_async, teardown_with_normal_loop);
1083 
1084   /* Tests for g_tls_interaction_invoke_request_certificate */
1085   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-with-loop",
1086                                      setup_with_thread_loop, test_invoke_request_certificate, teardown_with_thread_loop);
1087   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-without-loop",
1088                                      setup_without_loop, test_invoke_request_certificate, teardown_without_loop);
1089   test_with_all_request_certificate ("/tls-interaction/request-certificate/invoke-in-loop",
1090                               setup_with_normal_loop, test_invoke_request_certificate, teardown_with_normal_loop);
1091 
1092   /* Tests for g_tls_interaction_ask_password */
1093   test_with_unhandled_request_certificate ("/tls-interaction/request-certificate/sync",
1094                                            setup_without_loop, test_request_certificate, teardown_without_loop);
1095   test_with_sync_request_certificate ("/tls-interaction/request-certificate/sync",
1096                                       setup_without_loop, test_request_certificate, teardown_without_loop);
1097 
1098   /* Tests for g_tls_interaction_ask_password_async */
1099   test_with_unhandled_request_certificate ("/tls-interaction/request-certificate/async",
1100                                            setup_with_normal_loop, test_request_certificate_async, teardown_with_normal_loop);
1101   test_with_async_request_certificate ("/tls-interaction/request-certificate/async",
1102                                        setup_with_normal_loop, test_request_certificate_async, teardown_with_normal_loop);
1103 
1104   ret = g_test_run();
1105   g_ptr_array_free (fixtures, TRUE);
1106   return ret;
1107 }
1108