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