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 G_DEFINE_TYPE (TestInteraction, test_interaction, G_TYPE_TLS_INTERACTION);
61 #define TEST_TYPE_INTERACTION (test_interaction_get_type ())
62 #define TEST_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_INTERACTION, TestInteraction))
63 #define TEST_IS_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_INTERACTION))
66 test_interaction_init (TestInteraction *self)
72 test_interaction_class_init (TestInteractionClass *klass)
74 /* By default no virtual methods */
78 test_interaction_ask_password_async_success (GTlsInteraction *interaction,
79 GTlsPassword *password,
80 GCancellable *cancellable,
81 GAsyncReadyCallback callback,
84 GSimpleAsyncResult *res;
85 TestInteraction *self;
87 g_assert (TEST_IS_INTERACTION (interaction));
88 self = TEST_INTERACTION (interaction);
90 g_assert (g_thread_self () == self->test->interaction_thread);
92 g_assert (G_IS_TLS_PASSWORD (password));
93 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
95 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
96 test_interaction_ask_password_async_success);
98 /* Don't do this in real life. Include a null terminator for testing */
99 g_tls_password_set_value (password, (const guchar *)"the password", 13);
100 g_simple_async_result_complete_in_idle (res);
101 g_object_unref (res);
105 static GTlsInteractionResult
106 test_interaction_ask_password_finish_success (GTlsInteraction *interaction,
107 GAsyncResult *result,
110 TestInteraction *self;
112 g_assert (TEST_IS_INTERACTION (interaction));
113 self = TEST_INTERACTION (interaction);
115 g_assert (g_thread_self () == self->test->interaction_thread);
117 g_assert (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
118 test_interaction_ask_password_async_success));
119 g_assert (error != NULL);
120 g_assert (*error == NULL);
122 return G_TLS_INTERACTION_HANDLED;
126 test_interaction_ask_password_async_failure (GTlsInteraction *interaction,
127 GTlsPassword *password,
128 GCancellable *cancellable,
129 GAsyncReadyCallback callback,
132 GSimpleAsyncResult *res;
133 TestInteraction *self;
135 g_assert (TEST_IS_INTERACTION (interaction));
136 self = TEST_INTERACTION (interaction);
138 g_assert (g_thread_self () == self->test->interaction_thread);
140 g_assert (G_IS_TLS_PASSWORD (password));
141 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
143 res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
144 test_interaction_ask_password_async_failure);
146 g_simple_async_result_set_error (res, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
147 g_simple_async_result_complete_in_idle (res);
148 g_object_unref (res);
151 static GTlsInteractionResult
152 test_interaction_ask_password_finish_failure (GTlsInteraction *interaction,
153 GAsyncResult *result,
156 TestInteraction *self;
158 g_assert (TEST_IS_INTERACTION (interaction));
159 self = TEST_INTERACTION (interaction);
161 g_assert (g_thread_self () == self->test->interaction_thread);
163 g_assert (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
164 test_interaction_ask_password_async_failure));
165 g_assert (error != NULL);
166 g_assert (*error == NULL);
168 if (!g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
169 g_assert_not_reached ();
170 return G_TLS_INTERACTION_FAILED;
174 static GTlsInteractionResult
175 test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
176 GTlsPassword *password,
177 GCancellable *cancellable,
180 TestInteraction *self;
182 g_assert (TEST_IS_INTERACTION (interaction));
183 self = TEST_INTERACTION (interaction);
185 g_assert (g_thread_self () == self->test->interaction_thread);
187 g_assert (G_IS_TLS_PASSWORD (password));
188 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
189 g_assert (error != NULL);
190 g_assert (*error == NULL);
192 /* Don't do this in real life. Include a null terminator for testing */
193 g_tls_password_set_value (password, (const guchar *)"the password", 13);
194 return G_TLS_INTERACTION_HANDLED;
197 static GTlsInteractionResult
198 test_interaction_ask_password_sync_failure (GTlsInteraction *interaction,
199 GTlsPassword *password,
200 GCancellable *cancellable,
203 TestInteraction *self;
205 g_assert (TEST_IS_INTERACTION (interaction));
206 self = TEST_INTERACTION (interaction);
208 g_assert (g_thread_self () == self->test->interaction_thread);
210 g_assert (G_IS_TLS_PASSWORD (password));
211 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
212 g_assert (error != NULL);
213 g_assert (*error == NULL);
215 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
216 return G_TLS_INTERACTION_FAILED;
219 /* ----------------------------------------------------------------------------
224 on_ask_password_async_call (GObject *source,
225 GAsyncResult *result,
228 Test *test = user_data;
229 GTlsInteractionResult res;
230 GError *error = NULL;
232 g_assert (G_IS_TLS_INTERACTION (source));
233 g_assert (G_TLS_INTERACTION (source) == test->interaction);
235 /* Check that this callback is being run in the right place */
236 g_assert (g_thread_self () == test->interaction_thread);
238 res = g_tls_interaction_ask_password_finish (test->interaction, result,
241 /* Check that the results match the fixture */
242 g_assert_cmpuint (test->fixture->result, ==, res);
243 switch (test->fixture->result)
245 case G_TLS_INTERACTION_HANDLED:
246 g_assert_no_error (error);
247 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
249 case G_TLS_INTERACTION_FAILED:
250 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
251 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
252 g_clear_error (&error);
254 case G_TLS_INTERACTION_UNHANDLED:
255 g_assert_no_error (error);
258 g_assert_not_reached ();
261 /* Signal the end of the test */
262 g_main_loop_quit (test->loop);
266 test_ask_password_async (Test *test,
267 gconstpointer unused)
269 /* This test only works with a main loop */
270 g_assert (test->loop);
272 g_tls_interaction_ask_password_async (test->interaction,
273 test->password, NULL,
274 on_ask_password_async_call,
277 /* teardown waits until g_main_loop_quit(). called from callback */
281 test_invoke_ask_password (Test *test,
282 gconstpointer unused)
284 GTlsInteractionResult res;
285 GError *error = NULL;
287 res = g_tls_interaction_invoke_ask_password (test->interaction, test->password,
290 /* Check that the results match the fixture */
291 g_assert_cmpuint (test->fixture->result, ==, res);
292 switch (test->fixture->result)
294 case G_TLS_INTERACTION_HANDLED:
295 g_assert_no_error (error);
296 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
298 case G_TLS_INTERACTION_FAILED:
299 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
300 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
301 g_clear_error (&error);
303 case G_TLS_INTERACTION_UNHANDLED:
304 g_assert_no_error (error);
307 g_assert_not_reached ();
310 /* This allows teardown to stop if running with loop */
312 g_main_loop_quit (test->loop);
316 test_ask_password (Test *test,
317 gconstpointer unused)
319 GTlsInteractionResult res;
320 GError *error = NULL;
322 res = g_tls_interaction_ask_password (test->interaction, test->password,
325 /* Check that the results match the fixture */
326 g_assert_cmpuint (test->fixture->result, ==, res);
327 switch (test->fixture->result)
329 case G_TLS_INTERACTION_HANDLED:
330 g_assert_no_error (error);
331 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
333 case G_TLS_INTERACTION_FAILED:
334 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
335 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
336 g_clear_error (&error);
338 case G_TLS_INTERACTION_UNHANDLED:
339 g_assert_no_error (error);
342 g_assert_not_reached ();
345 /* This allows teardown to stop if running with loop */
347 g_main_loop_quit (test->loop);
350 /* ----------------------------------------------------------------------------
355 setup_without_loop (Test *test,
356 gconstpointer user_data)
358 const Fixture *fixture = user_data;
359 GTlsInteractionClass *klass;
360 test->fixture = fixture;
362 test->interaction = g_object_new (TEST_TYPE_INTERACTION, NULL);
363 g_assert (TEST_IS_INTERACTION (test->interaction));
365 TEST_INTERACTION (test->interaction)->test = test;
367 klass = G_TLS_INTERACTION_GET_CLASS (test->interaction);
368 klass->ask_password = fixture->ask_password_func;
369 klass->ask_password_async = fixture->ask_password_async_func;
370 klass->ask_password_finish = fixture->ask_password_finish_func;
372 test->password = g_tls_password_new (0, "Description");
373 test->test_thread = g_thread_self ();
376 * If no loop is running then interaction should happen in the same
377 * thread that the tests are running in.
379 test->interaction_thread = test->test_thread;
383 teardown_without_loop (Test *test,
384 gconstpointer unused)
386 g_object_unref (test->password);
388 g_object_unref (test->interaction);
389 g_assert (!G_IS_OBJECT (test->interaction));
400 thread_loop (gpointer user_data)
402 GMainContext *context = g_main_context_default ();
403 ThreadLoop *closure = user_data;
404 Test *test = closure->test;
406 g_mutex_lock (closure->loop_mutex);
408 g_assert (test->loop_thread == g_thread_self ());
409 g_assert (test->loop == NULL);
410 test->loop = g_main_loop_new (context, TRUE);
412 g_main_context_acquire (context);
413 g_cond_signal (closure->loop_started);
414 g_mutex_unlock (closure->loop_mutex);
416 while (g_main_loop_is_running (test->loop))
417 g_main_context_iteration (context, TRUE);
419 g_main_context_release (context);
424 setup_with_thread_loop (Test *test,
425 gconstpointer user_data)
427 GError *error = NULL;
430 setup_without_loop (test, user_data);
432 closure.loop_mutex = g_mutex_new ();
433 closure.loop_started = g_cond_new ();
436 g_mutex_lock (closure.loop_mutex);
437 test->loop_thread = g_thread_create (thread_loop, &closure, TRUE, &error);
438 g_cond_wait (closure.loop_started, closure.loop_mutex);
439 g_mutex_unlock (closure.loop_mutex);
442 * When a loop is running then interaction should always occur in the main
443 * context of that loop.
445 test->interaction_thread = test->loop_thread;
447 g_mutex_free (closure.loop_mutex);
448 g_cond_free (closure.loop_started);
452 teardown_with_thread_loop (Test *test,
453 gconstpointer unused)
457 g_assert (test->loop_thread);
458 check = g_thread_join (test->loop_thread);
459 g_assert (check == test);
460 test->loop_thread = NULL;
462 g_main_loop_unref (test->loop);
464 teardown_without_loop (test, unused);
468 setup_with_normal_loop (Test *test,
469 gconstpointer user_data)
471 GMainContext *context;
473 setup_without_loop (test, user_data);
475 context = g_main_context_default ();
476 if (!g_main_context_acquire (context))
477 g_assert_not_reached ();
479 test->loop = g_main_loop_new (context, TRUE);
480 g_assert (g_main_loop_is_running (test->loop));
484 teardown_with_normal_loop (Test *test,
485 gconstpointer unused)
487 GMainContext *context;
489 context = g_main_context_default ();
490 while (g_main_loop_is_running (test->loop))
491 g_main_context_iteration (context, TRUE);
493 g_main_context_release (context);
495 /* Run test until complete */
496 g_main_loop_unref (test->loop);
499 teardown_without_loop (test, unused);
502 typedef void (*TestFunc) (Test *test, gconstpointer data);
505 test_with_async_ask_password_implementations (const gchar *name,
514 /* Async implementation that succeeds */
515 fixture = g_new0 (Fixture, 1);
516 fixture->ask_password_async_func = test_interaction_ask_password_async_success;
517 fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
518 fixture->ask_password_func = NULL;
519 fixture->result = G_TLS_INTERACTION_HANDLED;
520 test_name = g_strdup_printf ("%s/async-implementation-success", name);
521 g_test_add (test_name, Test, fixture, setup, func, teardown);
523 g_ptr_array_add (fixtures, fixture);
525 /* Async implementation that fails */
526 fixture = g_new0 (Fixture, 1);
527 fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
528 fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
529 fixture->ask_password_func = NULL;
530 fixture->result = G_TLS_INTERACTION_FAILED;
531 fixture->error_domain = G_FILE_ERROR;
532 fixture->error_code = G_FILE_ERROR_ACCES;
533 fixture->error_message = "The message";
534 test_name = g_strdup_printf ("%s/async-implementation-failure", name);
535 g_test_add (test_name, Test, fixture, setup, func, teardown);
537 g_ptr_array_add (fixtures, fixture);
540 test_with_unhandled_ask_password_implementations (const gchar *name,
549 /* Unhandled implementation */
550 fixture = g_new0 (Fixture, 1);
551 fixture->ask_password_async_func = NULL;
552 fixture->ask_password_finish_func = NULL;
553 fixture->ask_password_func = NULL;
554 fixture->result = G_TLS_INTERACTION_UNHANDLED;
555 test_name = g_strdup_printf ("%s/unhandled-implementation", name);
556 g_test_add (test_name, Test, fixture, setup, func, teardown);
558 g_ptr_array_add (fixtures, fixture);
562 test_with_sync_ask_password_implementations (const gchar *name,
571 /* Sync implementation that succeeds */
572 fixture = g_new0 (Fixture, 1);
573 fixture->ask_password_async_func = NULL;
574 fixture->ask_password_finish_func = NULL;
575 fixture->ask_password_func = test_interaction_ask_password_sync_success;
576 fixture->result = G_TLS_INTERACTION_HANDLED;
577 test_name = g_strdup_printf ("%s/sync-implementation-success", name);
578 g_test_add (test_name, Test, fixture, setup, func, teardown);
580 g_ptr_array_add (fixtures, fixture);
582 /* Async implementation that fails */
583 fixture = g_new0 (Fixture, 1);
584 fixture->ask_password_async_func = NULL;
585 fixture->ask_password_finish_func = NULL;
586 fixture->ask_password_func = test_interaction_ask_password_sync_failure;
587 fixture->result = G_TLS_INTERACTION_FAILED;
588 fixture->error_domain = G_FILE_ERROR;
589 fixture->error_code = G_FILE_ERROR_ACCES;
590 fixture->error_message = "The message";
591 test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
592 g_test_add (test_name, Test, fixture, setup, func, teardown);
594 g_ptr_array_add (fixtures, fixture);
605 g_thread_init (NULL);
606 g_test_init (&argc, &argv, NULL);
608 fixtures = g_ptr_array_new_with_free_func (g_free);
610 /* Tests for g_tls_interaction_invoke_ask_password */
612 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
613 setup_with_thread_loop, test_invoke_ask_password,
614 teardown_with_thread_loop, fixtures);
615 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
616 setup_with_thread_loop, test_invoke_ask_password,
617 teardown_with_thread_loop, fixtures);
618 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
619 setup_with_thread_loop, test_invoke_ask_password,
620 teardown_with_thread_loop, fixtures);
622 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
623 setup_without_loop, test_invoke_ask_password,
624 teardown_without_loop, fixtures);
625 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
626 setup_without_loop, test_invoke_ask_password,
627 teardown_without_loop, fixtures);
628 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
629 setup_without_loop, test_invoke_ask_password,
630 teardown_without_loop, fixtures);
632 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
633 setup_with_normal_loop, test_invoke_ask_password,
634 teardown_with_normal_loop, fixtures);
635 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
636 setup_with_normal_loop, test_invoke_ask_password,
637 teardown_with_normal_loop, fixtures);
638 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
639 setup_with_normal_loop, test_invoke_ask_password,
640 teardown_with_normal_loop, fixtures);
642 /* Tests for g_tls_interaction_ask_password */
643 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/sync",
644 setup_without_loop, test_ask_password,
645 teardown_without_loop, fixtures);
646 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/sync",
647 setup_without_loop, test_ask_password,
648 teardown_without_loop, fixtures);
650 /* Tests for g_tls_interaction_ask_password_async */
651 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/async",
652 setup_with_normal_loop, test_ask_password_async,
653 teardown_with_normal_loop, fixtures);
654 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/async",
655 setup_with_normal_loop, test_ask_password_async,
656 teardown_with_normal_loop, fixtures);
659 g_ptr_array_free (fixtures, TRUE);