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
27static GPtrArray *fixtures = NULL;
28
29typedef 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
45typedef 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
56typedef struct {
57 GTlsInteraction parent;
58 Test *test;
59} TestInteraction;
60
61typedef struct {
62 GTlsInteractionClass parent;
63} TestInteractionClass;
64
65static GType test_interaction_get_type (void);
66G_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
72static void
73test_interaction_init (TestInteraction *self)
74{
75
76}
77
78static void
79test_interaction_class_init (TestInteractionClass *klass)
80{
81 /* By default no virtual methods */
82}
83
84static void
85test_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 (source_object: self, cancellable, callback, callback_data: user_data);
103
104 /* Don't do this in real life. Include a null terminator for testing */
105 g_tls_password_set_value (password, value: (const guchar *)"the password", length: 13);
106 g_task_return_int (task, result: G_TLS_INTERACTION_HANDLED);
107 g_object_unref (object: task);
108}
109
110
111static GTlsInteractionResult
112test_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
130static void
131test_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 (source_object: self, cancellable, callback, callback_data: user_data);
149
150 g_task_return_new_error (task, G_FILE_ERROR, code: G_FILE_ERROR_ACCES, format: "The message");
151 g_object_unref (object: task);
152}
153
154static GTlsInteractionResult
155test_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". */
180static guchar *
181special_dup (const char *str)
182{
183 GString *buf = g_string_new (init: "BEFORE");
184 guchar *ret;
185
186 g_string_append_c (buf, '\0');
187 g_string_append (string: buf, val: str);
188 g_string_append_c (buf, '\0');
189 g_string_append (string: buf, val: "AFTER");
190 ret = (guchar *) g_string_free (string: buf, FALSE);
191 return ret + strlen (s: "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. */
197static void
198special_free (gpointer p)
199{
200 gchar *s = p;
201 gchar *buf = s - strlen (s: "BEFORE") - 1;
202
203 g_assert_cmpstr (buf, ==, "BEFORE");
204 g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER");
205 g_free (mem: buf);
206}
207
208
209static GTlsInteractionResult
210test_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, value: (const guchar *) "foo", length: 4);
231 len = 0;
232 value = g_tls_password_get_value (password, length: &len);
233 g_assert_cmpmem (value, len, "foo", 4);
234
235 g_tls_password_set_value (password, value: (const guchar *) "bar", length: -1);
236 len = 0;
237 value = g_tls_password_get_value (password, length: &len);
238 g_assert_cmpmem (value, len, "bar", 3);
239
240 g_tls_password_set_value_full (password, value: special_dup (str: "baa"), length: 4, destroy: special_free);
241 len = 0;
242 value = g_tls_password_get_value (password, length: &len);
243 g_assert_cmpmem (value, len, "baa", 4);
244
245 g_tls_password_set_value_full (password, value: special_dup (str: "baz"), length: -1, destroy: special_free);
246 len = 0;
247 value = g_tls_password_get_value (password, length: &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, value: (const guchar *)"the password", length: 13);
252 return G_TLS_INTERACTION_HANDLED;
253}
254
255static GTlsInteractionResult
256test_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 (err: error, G_FILE_ERROR, code: G_FILE_ERROR_ACCES, format: "The message");
274 return G_TLS_INTERACTION_FAILED;
275}
276
277static void
278test_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 (source_object: self, cancellable, callback, callback_data: 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), key: "chosen-certificate", data: "my-certificate");
304 g_task_return_int (task, result: G_TLS_INTERACTION_HANDLED);
305 g_object_unref (object: task);
306}
307
308static GTlsInteractionResult
309test_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
327static void
328test_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 (source_object: self, cancellable, callback, callback_data: user_data);
348
349 g_task_return_new_error (task, G_FILE_ERROR, code: G_FILE_ERROR_NOENT, format: "Another message");
350 g_object_unref (object: task);
351}
352
353static GTlsInteractionResult
354test_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
375static GTlsInteractionResult
376test_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), key: "chosen-certificate", data: "my-certificate");
399 return G_TLS_INTERACTION_HANDLED;
400}
401
402static GTlsInteractionResult
403test_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 (err: error, G_FILE_ERROR, code: G_FILE_ERROR_NOENT, format: "Another message");
423 return G_TLS_INTERACTION_FAILED;
424}
425
426/* ----------------------------------------------------------------------------
427 * ACTUAL TESTS
428 */
429
430static void
431on_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 (interaction: test->interaction, result,
446 error: &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 (err: &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 (loop: test->loop);
470}
471
472static void
473test_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 (interaction: test->interaction,
480 password: test->password, NULL,
481 callback: on_ask_password_async_call,
482 user_data: test);
483
484 /* teardown waits until g_main_loop_quit(). called from callback */
485}
486
487static void
488test_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 (interaction: test->interaction, password: test->password,
495 NULL, error: &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 (err: &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 (loop: test->loop);
520}
521
522static void
523test_ask_password (Test *test,
524 gconstpointer unused)
525{
526 GTlsInteractionResult res;
527 GError *error = NULL;
528
529 res = g_tls_interaction_ask_password (interaction: test->interaction, password: test->password,
530 NULL, error: &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 (err: &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 (loop: test->loop);
555}
556
557static void
558on_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 (interaction: test->interaction, result, error: &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 (err: &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 (loop: test->loop);
596}
597
598static void
599test_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 (interaction: test->interaction,
606 connection: test->connection, flags: 0, NULL,
607 callback: on_request_certificate_async_call,
608 user_data: test);
609
610 /* teardown waits until g_main_loop_quit(). called from callback */
611}
612
613static void
614test_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 (interaction: test->interaction,
621 connection: test->connection,
622 flags: 0, NULL, error: &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 (err: &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 (loop: test->loop);
647}
648
649static void
650test_request_certificate (Test *test,
651 gconstpointer unused)
652{
653 GTlsInteractionResult res;
654 GError *error = NULL;
655
656 res = g_tls_interaction_request_certificate (interaction: test->interaction, connection: test->connection,
657 flags: 0, NULL, error: &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 (err: &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 (loop: test->loop);
682}
683
684/* ----------------------------------------------------------------------------
685 * TEST SETUP
686 */
687
688static void
689setup_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 (object_type: g_tls_backend_get_server_connection_type (backend), NULL);
714 g_assert_no_error (error);
715 g_object_unref (object: backend);
716
717 test->password = g_tls_password_new (flags: 0, description: "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
727static void
728teardown_without_loop (Test *test,
729 gconstpointer unused)
730{
731 g_object_unref (object: test->connection);
732 g_object_unref (object: test->password);
733
734 g_assert_finalize_object (test->interaction);
735}
736
737typedef struct {
738 GMutex loop_mutex;
739 GCond loop_started;
740 gboolean started;
741 Test *test;
742} ThreadLoop;
743
744static gpointer
745thread_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 (mutex: &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 (cond: &closure->loop_started);
760 g_mutex_unlock (mutex: &closure->loop_mutex);
761
762 while (g_main_loop_is_running (loop: test->loop))
763 g_main_context_iteration (context, TRUE);
764
765 g_main_context_release (context);
766 return test;
767}
768
769static void
770setup_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 (mutex: &closure.loop_mutex);
778 g_cond_init (cond: &closure.loop_started);
779 closure.started = FALSE;
780 closure.test = test;
781
782 g_mutex_lock (mutex: &closure.loop_mutex);
783 test->loop_thread = g_thread_new (name: "loop", func: thread_loop, data: &closure);
784 while (!closure.started)
785 g_cond_wait (cond: &closure.loop_started, mutex: &closure.loop_mutex);
786 g_mutex_unlock (mutex: &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 (mutex: &closure.loop_mutex);
795 g_cond_clear (cond: &closure.loop_started);
796}
797
798static void
799teardown_with_thread_loop (Test *test,
800 gconstpointer unused)
801{
802 gpointer check;
803
804 g_assert (test->loop_thread);
805 check = g_thread_join (thread: test->loop_thread);
806 g_assert (check == test);
807 test->loop_thread = NULL;
808
809 g_main_loop_unref (loop: test->loop);
810
811 teardown_without_loop (test, unused);
812}
813
814static void
815setup_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
830static void
831teardown_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 (loop: 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 (loop: test->loop);
844 test->loop = NULL;
845
846 teardown_without_loop (test, unused);
847}
848
849typedef void (*TestFunc) (Test *test, gconstpointer data);
850
851static void
852test_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 (format: "%s/async-implementation-success", name);
867 g_test_add (test_name, Test, fixture, setup, func, teardown);
868 g_free (mem: test_name);
869 g_ptr_array_add (array: fixtures, data: 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 (format: "%s/async-implementation-failure", name);
881 g_test_add (test_name, Test, fixture, setup, func, teardown);
882 g_free (mem: test_name);
883 g_ptr_array_add (array: fixtures, data: fixture);
884}
885
886static void
887test_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 (format: "%s/unhandled-implementation", name);
902 g_test_add (test_name, Test, fixture, setup, func, teardown);
903 g_free (mem: test_name);
904 g_ptr_array_add (array: fixtures, data: fixture);
905}
906
907static void
908test_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 (format: "%s/sync-implementation-success", name);
923 g_test_add (test_name, Test, fixture, setup, func, teardown);
924 g_free (mem: test_name);
925 g_ptr_array_add (array: fixtures, data: 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 (format: "%s/sync-implementation-failure", name);
937 g_test_add (test_name, Test, fixture, setup, func, teardown);
938 g_free (mem: test_name);
939 g_ptr_array_add (array: fixtures, data: fixture);
940}
941
942static void
943test_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
953static void
954test_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 (format: "%s/async-implementation-success", name);
969 g_test_add (test_name, Test, fixture, setup, func, teardown);
970 g_free (mem: test_name);
971 g_ptr_array_add (array: fixtures, data: 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 (format: "%s/async-implementation-failure", name);
983 g_test_add (test_name, Test, fixture, setup, func, teardown);
984 g_free (mem: test_name);
985 g_ptr_array_add (array: fixtures, data: fixture);
986}
987
988static void
989test_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 (format: "%s/unhandled-implementation", name);
1004 g_test_add (test_name, Test, fixture, setup, func, teardown);
1005 g_free (mem: test_name);
1006 g_ptr_array_add (array: fixtures, data: fixture);
1007}
1008
1009static void
1010test_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 (format: "%s/sync-implementation-success", name);
1025 g_test_add (test_name, Test, fixture, setup, func, teardown);
1026 g_free (mem: test_name);
1027 g_ptr_array_add (array: fixtures, data: 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 (format: "%s/sync-implementation-failure", name);
1039 g_test_add (test_name, Test, fixture, setup, func, teardown);
1040 g_free (mem: test_name);
1041 g_ptr_array_add (array: fixtures, data: fixture);
1042}
1043
1044static void
1045test_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}
1054int
1055main (int argc,
1056 char *argv[])
1057{
1058 gint ret;
1059
1060 g_test_init (argc: &argc, argv: &argv, NULL);
1061
1062 fixtures = g_ptr_array_new_with_free_func (element_free_func: g_free);
1063
1064 /* Tests for g_tls_interaction_invoke_ask_password */
1065 test_with_all_ask_password (name: "/tls-interaction/ask-password/invoke-with-loop",
1066 setup: setup_with_thread_loop, func: test_invoke_ask_password, teardown: teardown_with_thread_loop);
1067 test_with_all_ask_password (name: "/tls-interaction/ask-password/invoke-without-loop",
1068 setup: setup_without_loop, func: test_invoke_ask_password, teardown: teardown_without_loop);
1069 test_with_all_ask_password (name: "/tls-interaction/ask-password/invoke-in-loop",
1070 setup: setup_with_normal_loop, func: test_invoke_ask_password, teardown: teardown_with_normal_loop);
1071
1072 /* Tests for g_tls_interaction_ask_password */
1073 test_with_unhandled_ask_password (name: "/tls-interaction/ask-password/sync",
1074 setup: setup_without_loop, func: test_ask_password, teardown: teardown_without_loop);
1075 test_with_sync_ask_password (name: "/tls-interaction/ask-password/sync",
1076 setup: setup_without_loop, func: test_ask_password, teardown: teardown_without_loop);
1077
1078 /* Tests for g_tls_interaction_ask_password_async */
1079 test_with_unhandled_ask_password (name: "/tls-interaction/ask-password/async",
1080 setup: setup_with_normal_loop, func: test_ask_password_async, teardown: teardown_with_normal_loop);
1081 test_with_async_ask_password (name: "/tls-interaction/ask-password/async",
1082 setup: setup_with_normal_loop, func: test_ask_password_async, teardown: teardown_with_normal_loop);
1083
1084 /* Tests for g_tls_interaction_invoke_request_certificate */
1085 test_with_all_request_certificate (name: "/tls-interaction/request-certificate/invoke-with-loop",
1086 setup: setup_with_thread_loop, func: test_invoke_request_certificate, teardown: teardown_with_thread_loop);
1087 test_with_all_request_certificate (name: "/tls-interaction/request-certificate/invoke-without-loop",
1088 setup: setup_without_loop, func: test_invoke_request_certificate, teardown: teardown_without_loop);
1089 test_with_all_request_certificate (name: "/tls-interaction/request-certificate/invoke-in-loop",
1090 setup: setup_with_normal_loop, func: test_invoke_request_certificate, teardown: teardown_with_normal_loop);
1091
1092 /* Tests for g_tls_interaction_ask_password */
1093 test_with_unhandled_request_certificate (name: "/tls-interaction/request-certificate/sync",
1094 setup: setup_without_loop, func: test_request_certificate, teardown: teardown_without_loop);
1095 test_with_sync_request_certificate (name: "/tls-interaction/request-certificate/sync",
1096 setup: setup_without_loop, func: test_request_certificate, teardown: teardown_without_loop);
1097
1098 /* Tests for g_tls_interaction_ask_password_async */
1099 test_with_unhandled_request_certificate (name: "/tls-interaction/request-certificate/async",
1100 setup: setup_with_normal_loop, func: test_request_certificate_async, teardown: teardown_with_normal_loop);
1101 test_with_async_request_certificate (name: "/tls-interaction/request-certificate/async",
1102 setup: setup_with_normal_loop, func: test_request_certificate_async, teardown: teardown_with_normal_loop);
1103
1104 ret = g_test_run();
1105 g_ptr_array_free (array: fixtures, TRUE);
1106 return ret;
1107}
1108

source code of gtk/subprojects/glib/gio/tests/tls-interaction.c