1 /* GLib testing framework examples and tests
3 * Copyright (C) 2011 Collabora Ltd.
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 of the License, or (at your option) any later version.
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.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Stef Walter <stefw@collobora.co.uk>
28 /* Class virtual interaction methods */
29 gpointer ask_password_func;
30 gpointer ask_password_async_func;
31 gpointer ask_password_finish_func;
33 /* Expected results */
34 GTlsInteractionResult result;
37 const gchar *error_message;
41 GTlsInteraction *interaction;
42 GTlsPassword *password;
44 GThread *interaction_thread;
47 const Fixture *fixture;
51 GTlsInteraction parent;
56 GTlsInteractionClass parent;
57 } TestInteractionClass;
59 static GType test_interaction_get_type (void);
60 G_DEFINE_TYPE (TestInteraction, test_interaction, G_TYPE_TLS_INTERACTION);
62 #define TEST_TYPE_INTERACTION (test_interaction_get_type ())
63 #define TEST_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_INTERACTION, TestInteraction))
64 #define TEST_IS_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_INTERACTION))
67 test_interaction_init (TestInteraction *self)
73 test_interaction_class_init (TestInteractionClass *klass)
75 /* By default no virtual methods */
79 test_interaction_ask_password_async_success (GTlsInteraction *interaction,
80 GTlsPassword *password,
81 GCancellable *cancellable,
82 GAsyncReadyCallback callback,
85 GSimpleAsyncResult *res;
86 TestInteraction *self;
88 g_assert (TEST_IS_INTERACTION (interaction));
89 self = TEST_INTERACTION (interaction);
91 g_assert (g_thread_self () == self->test->interaction_thread);
93 g_assert (G_IS_TLS_PASSWORD (password));
94 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
96 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
97 test_interaction_ask_password_async_success);
99 /* Don't do this in real life. Include a null terminator for testing */
100 g_tls_password_set_value (password, (const guchar *)"the password", 13);
101 g_simple_async_result_complete_in_idle (res);
102 g_object_unref (res);
106 static GTlsInteractionResult
107 test_interaction_ask_password_finish_success (GTlsInteraction *interaction,
108 GAsyncResult *result,
111 TestInteraction *self;
113 g_assert (TEST_IS_INTERACTION (interaction));
114 self = TEST_INTERACTION (interaction);
116 g_assert (g_thread_self () == self->test->interaction_thread);
118 g_assert (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
119 test_interaction_ask_password_async_success));
120 g_assert (error != NULL);
121 g_assert (*error == NULL);
123 return G_TLS_INTERACTION_HANDLED;
127 test_interaction_ask_password_async_failure (GTlsInteraction *interaction,
128 GTlsPassword *password,
129 GCancellable *cancellable,
130 GAsyncReadyCallback callback,
133 GSimpleAsyncResult *res;
134 TestInteraction *self;
136 g_assert (TEST_IS_INTERACTION (interaction));
137 self = TEST_INTERACTION (interaction);
139 g_assert (g_thread_self () == self->test->interaction_thread);
141 g_assert (G_IS_TLS_PASSWORD (password));
142 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
144 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
145 test_interaction_ask_password_async_failure);
147 g_simple_async_result_set_error (res, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
148 g_simple_async_result_complete_in_idle (res);
149 g_object_unref (res);
152 static GTlsInteractionResult
153 test_interaction_ask_password_finish_failure (GTlsInteraction *interaction,
154 GAsyncResult *result,
157 TestInteraction *self;
159 g_assert (TEST_IS_INTERACTION (interaction));
160 self = TEST_INTERACTION (interaction);
162 g_assert (g_thread_self () == self->test->interaction_thread);
164 g_assert (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
165 test_interaction_ask_password_async_failure));
166 g_assert (error != NULL);
167 g_assert (*error == NULL);
169 if (!g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
170 g_assert_not_reached ();
171 return G_TLS_INTERACTION_FAILED;
175 static GTlsInteractionResult
176 test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
177 GTlsPassword *password,
178 GCancellable *cancellable,
181 TestInteraction *self;
183 g_assert (TEST_IS_INTERACTION (interaction));
184 self = TEST_INTERACTION (interaction);
186 g_assert (g_thread_self () == self->test->interaction_thread);
188 g_assert (G_IS_TLS_PASSWORD (password));
189 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
190 g_assert (error != NULL);
191 g_assert (*error == NULL);
193 /* Don't do this in real life. Include a null terminator for testing */
194 g_tls_password_set_value (password, (const guchar *)"the password", 13);
195 return G_TLS_INTERACTION_HANDLED;
198 static GTlsInteractionResult
199 test_interaction_ask_password_sync_failure (GTlsInteraction *interaction,
200 GTlsPassword *password,
201 GCancellable *cancellable,
204 TestInteraction *self;
206 g_assert (TEST_IS_INTERACTION (interaction));
207 self = TEST_INTERACTION (interaction);
209 g_assert (g_thread_self () == self->test->interaction_thread);
211 g_assert (G_IS_TLS_PASSWORD (password));
212 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
213 g_assert (error != NULL);
214 g_assert (*error == NULL);
216 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
217 return G_TLS_INTERACTION_FAILED;
220 /* ----------------------------------------------------------------------------
225 on_ask_password_async_call (GObject *source,
226 GAsyncResult *result,
229 Test *test = user_data;
230 GTlsInteractionResult res;
231 GError *error = NULL;
233 g_assert (G_IS_TLS_INTERACTION (source));
234 g_assert (G_TLS_INTERACTION (source) == test->interaction);
236 /* Check that this callback is being run in the right place */
237 g_assert (g_thread_self () == test->interaction_thread);
239 res = g_tls_interaction_ask_password_finish (test->interaction, result,
242 /* Check that the results match the fixture */
243 g_assert_cmpuint (test->fixture->result, ==, res);
244 switch (test->fixture->result)
246 case G_TLS_INTERACTION_HANDLED:
247 g_assert_no_error (error);
248 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
250 case G_TLS_INTERACTION_FAILED:
251 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
252 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
253 g_clear_error (&error);
255 case G_TLS_INTERACTION_UNHANDLED:
256 g_assert_no_error (error);
259 g_assert_not_reached ();
262 /* Signal the end of the test */
263 g_main_loop_quit (test->loop);
267 test_ask_password_async (Test *test,
268 gconstpointer unused)
270 /* This test only works with a main loop */
271 g_assert (test->loop);
273 g_tls_interaction_ask_password_async (test->interaction,
274 test->password, NULL,
275 on_ask_password_async_call,
278 /* teardown waits until g_main_loop_quit(). called from callback */
282 test_invoke_ask_password (Test *test,
283 gconstpointer unused)
285 GTlsInteractionResult res;
286 GError *error = NULL;
288 res = g_tls_interaction_invoke_ask_password (test->interaction, test->password,
291 /* Check that the results match the fixture */
292 g_assert_cmpuint (test->fixture->result, ==, res);
293 switch (test->fixture->result)
295 case G_TLS_INTERACTION_HANDLED:
296 g_assert_no_error (error);
297 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
299 case G_TLS_INTERACTION_FAILED:
300 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
301 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
302 g_clear_error (&error);
304 case G_TLS_INTERACTION_UNHANDLED:
305 g_assert_no_error (error);
308 g_assert_not_reached ();
311 /* This allows teardown to stop if running with loop */
313 g_main_loop_quit (test->loop);
317 test_ask_password (Test *test,
318 gconstpointer unused)
320 GTlsInteractionResult res;
321 GError *error = NULL;
323 res = g_tls_interaction_ask_password (test->interaction, test->password,
326 /* Check that the results match the fixture */
327 g_assert_cmpuint (test->fixture->result, ==, res);
328 switch (test->fixture->result)
330 case G_TLS_INTERACTION_HANDLED:
331 g_assert_no_error (error);
332 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
334 case G_TLS_INTERACTION_FAILED:
335 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
336 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
337 g_clear_error (&error);
339 case G_TLS_INTERACTION_UNHANDLED:
340 g_assert_no_error (error);
343 g_assert_not_reached ();
346 /* This allows teardown to stop if running with loop */
348 g_main_loop_quit (test->loop);
351 /* ----------------------------------------------------------------------------
356 setup_without_loop (Test *test,
357 gconstpointer user_data)
359 const Fixture *fixture = user_data;
360 GTlsInteractionClass *klass;
361 test->fixture = fixture;
363 test->interaction = g_object_new (TEST_TYPE_INTERACTION, NULL);
364 g_assert (TEST_IS_INTERACTION (test->interaction));
366 TEST_INTERACTION (test->interaction)->test = test;
368 klass = G_TLS_INTERACTION_GET_CLASS (test->interaction);
369 klass->ask_password = fixture->ask_password_func;
370 klass->ask_password_async = fixture->ask_password_async_func;
371 klass->ask_password_finish = fixture->ask_password_finish_func;
373 test->password = g_tls_password_new (0, "Description");
374 test->test_thread = g_thread_self ();
377 * If no loop is running then interaction should happen in the same
378 * thread that the tests are running in.
380 test->interaction_thread = test->test_thread;
384 teardown_without_loop (Test *test,
385 gconstpointer unused)
387 gpointer weak_pointer = test->interaction;
389 g_object_add_weak_pointer (weak_pointer, &weak_pointer);
391 g_object_unref (test->password);
393 g_object_unref (test->interaction);
395 g_assert (weak_pointer == NULL);
407 thread_loop (gpointer user_data)
409 GMainContext *context = g_main_context_default ();
410 ThreadLoop *closure = user_data;
411 Test *test = closure->test;
413 g_mutex_lock (&closure->loop_mutex);
415 g_assert (test->loop_thread == g_thread_self ());
416 g_assert (test->loop == NULL);
417 test->loop = g_main_loop_new (context, TRUE);
419 g_main_context_acquire (context);
420 closure->started = TRUE;
421 g_cond_signal (&closure->loop_started);
422 g_mutex_unlock (&closure->loop_mutex);
424 while (g_main_loop_is_running (test->loop))
425 g_main_context_iteration (context, TRUE);
427 g_main_context_release (context);
432 setup_with_thread_loop (Test *test,
433 gconstpointer user_data)
437 setup_without_loop (test, user_data);
439 g_mutex_init (&closure.loop_mutex);
440 g_cond_init (&closure.loop_started);
441 closure.started = FALSE;
444 g_mutex_lock (&closure.loop_mutex);
445 test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
446 while (!closure.started)
447 g_cond_wait (&closure.loop_started, &closure.loop_mutex);
448 g_mutex_unlock (&closure.loop_mutex);
451 * When a loop is running then interaction should always occur in the main
452 * context of that loop.
454 test->interaction_thread = test->loop_thread;
456 g_mutex_clear (&closure.loop_mutex);
457 g_cond_clear (&closure.loop_started);
461 teardown_with_thread_loop (Test *test,
462 gconstpointer unused)
466 g_assert (test->loop_thread);
467 check = g_thread_join (test->loop_thread);
468 g_assert (check == test);
469 test->loop_thread = NULL;
471 g_main_loop_unref (test->loop);
473 teardown_without_loop (test, unused);
477 setup_with_normal_loop (Test *test,
478 gconstpointer user_data)
480 GMainContext *context;
482 setup_without_loop (test, user_data);
484 context = g_main_context_default ();
485 if (!g_main_context_acquire (context))
486 g_assert_not_reached ();
488 test->loop = g_main_loop_new (context, TRUE);
489 g_assert (g_main_loop_is_running (test->loop));
493 teardown_with_normal_loop (Test *test,
494 gconstpointer unused)
496 GMainContext *context;
498 context = g_main_context_default ();
499 while (g_main_loop_is_running (test->loop))
500 g_main_context_iteration (context, TRUE);
502 g_main_context_release (context);
504 /* Run test until complete */
505 g_main_loop_unref (test->loop);
508 teardown_without_loop (test, unused);
511 typedef void (*TestFunc) (Test *test, gconstpointer data);
514 test_with_async_ask_password_implementations (const gchar *name,
523 /* Async implementation that succeeds */
524 fixture = g_new0 (Fixture, 1);
525 fixture->ask_password_async_func = test_interaction_ask_password_async_success;
526 fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
527 fixture->ask_password_func = NULL;
528 fixture->result = G_TLS_INTERACTION_HANDLED;
529 test_name = g_strdup_printf ("%s/async-implementation-success", name);
530 g_test_add (test_name, Test, fixture, setup, func, teardown);
532 g_ptr_array_add (fixtures, fixture);
534 /* Async implementation that fails */
535 fixture = g_new0 (Fixture, 1);
536 fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
537 fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
538 fixture->ask_password_func = NULL;
539 fixture->result = G_TLS_INTERACTION_FAILED;
540 fixture->error_domain = G_FILE_ERROR;
541 fixture->error_code = G_FILE_ERROR_ACCES;
542 fixture->error_message = "The message";
543 test_name = g_strdup_printf ("%s/async-implementation-failure", name);
544 g_test_add (test_name, Test, fixture, setup, func, teardown);
546 g_ptr_array_add (fixtures, fixture);
549 test_with_unhandled_ask_password_implementations (const gchar *name,
558 /* Unhandled implementation */
559 fixture = g_new0 (Fixture, 1);
560 fixture->ask_password_async_func = NULL;
561 fixture->ask_password_finish_func = NULL;
562 fixture->ask_password_func = NULL;
563 fixture->result = G_TLS_INTERACTION_UNHANDLED;
564 test_name = g_strdup_printf ("%s/unhandled-implementation", name);
565 g_test_add (test_name, Test, fixture, setup, func, teardown);
567 g_ptr_array_add (fixtures, fixture);
571 test_with_sync_ask_password_implementations (const gchar *name,
580 /* Sync implementation that succeeds */
581 fixture = g_new0 (Fixture, 1);
582 fixture->ask_password_async_func = NULL;
583 fixture->ask_password_finish_func = NULL;
584 fixture->ask_password_func = test_interaction_ask_password_sync_success;
585 fixture->result = G_TLS_INTERACTION_HANDLED;
586 test_name = g_strdup_printf ("%s/sync-implementation-success", name);
587 g_test_add (test_name, Test, fixture, setup, func, teardown);
589 g_ptr_array_add (fixtures, fixture);
591 /* Async implementation that fails */
592 fixture = g_new0 (Fixture, 1);
593 fixture->ask_password_async_func = NULL;
594 fixture->ask_password_finish_func = NULL;
595 fixture->ask_password_func = test_interaction_ask_password_sync_failure;
596 fixture->result = G_TLS_INTERACTION_FAILED;
597 fixture->error_domain = G_FILE_ERROR;
598 fixture->error_code = G_FILE_ERROR_ACCES;
599 fixture->error_message = "The message";
600 test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
601 g_test_add (test_name, Test, fixture, setup, func, teardown);
603 g_ptr_array_add (fixtures, fixture);
614 g_test_init (&argc, &argv, NULL);
616 fixtures = g_ptr_array_new_with_free_func (g_free);
618 /* Tests for g_tls_interaction_invoke_ask_password */
620 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
621 setup_with_thread_loop, test_invoke_ask_password,
622 teardown_with_thread_loop, fixtures);
623 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
624 setup_with_thread_loop, test_invoke_ask_password,
625 teardown_with_thread_loop, fixtures);
626 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
627 setup_with_thread_loop, test_invoke_ask_password,
628 teardown_with_thread_loop, fixtures);
630 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
631 setup_without_loop, test_invoke_ask_password,
632 teardown_without_loop, fixtures);
633 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
634 setup_without_loop, test_invoke_ask_password,
635 teardown_without_loop, fixtures);
636 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
637 setup_without_loop, test_invoke_ask_password,
638 teardown_without_loop, fixtures);
640 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
641 setup_with_normal_loop, test_invoke_ask_password,
642 teardown_with_normal_loop, fixtures);
643 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
644 setup_with_normal_loop, test_invoke_ask_password,
645 teardown_with_normal_loop, fixtures);
646 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
647 setup_with_normal_loop, test_invoke_ask_password,
648 teardown_with_normal_loop, fixtures);
650 /* Tests for g_tls_interaction_ask_password */
651 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/sync",
652 setup_without_loop, test_ask_password,
653 teardown_without_loop, fixtures);
654 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/sync",
655 setup_without_loop, test_ask_password,
656 teardown_without_loop, fixtures);
658 /* Tests for g_tls_interaction_ask_password_async */
659 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/async",
660 setup_with_normal_loop, test_ask_password_async,
661 teardown_with_normal_loop, fixtures);
662 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/async",
663 setup_with_normal_loop, test_ask_password_async,
664 teardown_with_normal_loop, fixtures);
667 g_ptr_array_free (fixtures, TRUE);