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