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));
401 thread_loop (gpointer user_data)
403 GMainContext *context = g_main_context_default ();
404 ThreadLoop *closure = user_data;
405 Test *test = closure->test;
407 g_mutex_lock (&closure->loop_mutex);
409 g_assert (test->loop_thread == g_thread_self ());
410 g_assert (test->loop == NULL);
411 test->loop = g_main_loop_new (context, TRUE);
413 g_main_context_acquire (context);
414 closure->started = TRUE;
415 g_cond_signal (&closure->loop_started);
416 g_mutex_unlock (&closure->loop_mutex);
418 while (g_main_loop_is_running (test->loop))
419 g_main_context_iteration (context, TRUE);
421 g_main_context_release (context);
426 setup_with_thread_loop (Test *test,
427 gconstpointer user_data)
431 setup_without_loop (test, user_data);
433 g_mutex_init (&closure.loop_mutex);
434 g_cond_init (&closure.loop_started);
435 closure.started = FALSE;
438 g_mutex_lock (&closure.loop_mutex);
439 test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
440 while (!closure.started)
441 g_cond_wait (&closure.loop_started, &closure.loop_mutex);
442 g_mutex_unlock (&closure.loop_mutex);
445 * When a loop is running then interaction should always occur in the main
446 * context of that loop.
448 test->interaction_thread = test->loop_thread;
450 g_mutex_clear (&closure.loop_mutex);
451 g_cond_clear (&closure.loop_started);
455 teardown_with_thread_loop (Test *test,
456 gconstpointer unused)
460 g_assert (test->loop_thread);
461 check = g_thread_join (test->loop_thread);
462 g_assert (check == test);
463 test->loop_thread = NULL;
465 g_main_loop_unref (test->loop);
467 teardown_without_loop (test, unused);
471 setup_with_normal_loop (Test *test,
472 gconstpointer user_data)
474 GMainContext *context;
476 setup_without_loop (test, user_data);
478 context = g_main_context_default ();
479 if (!g_main_context_acquire (context))
480 g_assert_not_reached ();
482 test->loop = g_main_loop_new (context, TRUE);
483 g_assert (g_main_loop_is_running (test->loop));
487 teardown_with_normal_loop (Test *test,
488 gconstpointer unused)
490 GMainContext *context;
492 context = g_main_context_default ();
493 while (g_main_loop_is_running (test->loop))
494 g_main_context_iteration (context, TRUE);
496 g_main_context_release (context);
498 /* Run test until complete */
499 g_main_loop_unref (test->loop);
502 teardown_without_loop (test, unused);
505 typedef void (*TestFunc) (Test *test, gconstpointer data);
508 test_with_async_ask_password_implementations (const gchar *name,
517 /* Async implementation that succeeds */
518 fixture = g_new0 (Fixture, 1);
519 fixture->ask_password_async_func = test_interaction_ask_password_async_success;
520 fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
521 fixture->ask_password_func = NULL;
522 fixture->result = G_TLS_INTERACTION_HANDLED;
523 test_name = g_strdup_printf ("%s/async-implementation-success", name);
524 g_test_add (test_name, Test, fixture, setup, func, teardown);
526 g_ptr_array_add (fixtures, fixture);
528 /* Async implementation that fails */
529 fixture = g_new0 (Fixture, 1);
530 fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
531 fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
532 fixture->ask_password_func = NULL;
533 fixture->result = G_TLS_INTERACTION_FAILED;
534 fixture->error_domain = G_FILE_ERROR;
535 fixture->error_code = G_FILE_ERROR_ACCES;
536 fixture->error_message = "The message";
537 test_name = g_strdup_printf ("%s/async-implementation-failure", name);
538 g_test_add (test_name, Test, fixture, setup, func, teardown);
540 g_ptr_array_add (fixtures, fixture);
543 test_with_unhandled_ask_password_implementations (const gchar *name,
552 /* Unhandled implementation */
553 fixture = g_new0 (Fixture, 1);
554 fixture->ask_password_async_func = NULL;
555 fixture->ask_password_finish_func = NULL;
556 fixture->ask_password_func = NULL;
557 fixture->result = G_TLS_INTERACTION_UNHANDLED;
558 test_name = g_strdup_printf ("%s/unhandled-implementation", name);
559 g_test_add (test_name, Test, fixture, setup, func, teardown);
561 g_ptr_array_add (fixtures, fixture);
565 test_with_sync_ask_password_implementations (const gchar *name,
574 /* Sync implementation that succeeds */
575 fixture = g_new0 (Fixture, 1);
576 fixture->ask_password_async_func = NULL;
577 fixture->ask_password_finish_func = NULL;
578 fixture->ask_password_func = test_interaction_ask_password_sync_success;
579 fixture->result = G_TLS_INTERACTION_HANDLED;
580 test_name = g_strdup_printf ("%s/sync-implementation-success", name);
581 g_test_add (test_name, Test, fixture, setup, func, teardown);
583 g_ptr_array_add (fixtures, fixture);
585 /* Async implementation that fails */
586 fixture = g_new0 (Fixture, 1);
587 fixture->ask_password_async_func = NULL;
588 fixture->ask_password_finish_func = NULL;
589 fixture->ask_password_func = test_interaction_ask_password_sync_failure;
590 fixture->result = G_TLS_INTERACTION_FAILED;
591 fixture->error_domain = G_FILE_ERROR;
592 fixture->error_code = G_FILE_ERROR_ACCES;
593 fixture->error_message = "The message";
594 test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
595 g_test_add (test_name, Test, fixture, setup, func, teardown);
597 g_ptr_array_add (fixtures, fixture);
608 g_test_init (&argc, &argv, NULL);
610 fixtures = g_ptr_array_new_with_free_func (g_free);
612 /* Tests for g_tls_interaction_invoke_ask_password */
614 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
615 setup_with_thread_loop, test_invoke_ask_password,
616 teardown_with_thread_loop, fixtures);
617 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
618 setup_with_thread_loop, test_invoke_ask_password,
619 teardown_with_thread_loop, fixtures);
620 test_with_sync_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);
624 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
625 setup_without_loop, test_invoke_ask_password,
626 teardown_without_loop, fixtures);
627 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
628 setup_without_loop, test_invoke_ask_password,
629 teardown_without_loop, fixtures);
630 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
631 setup_without_loop, test_invoke_ask_password,
632 teardown_without_loop, fixtures);
634 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
635 setup_with_normal_loop, test_invoke_ask_password,
636 teardown_with_normal_loop, fixtures);
637 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
638 setup_with_normal_loop, test_invoke_ask_password,
639 teardown_with_normal_loop, fixtures);
640 test_with_sync_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);
644 /* Tests for g_tls_interaction_ask_password */
645 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/sync",
646 setup_without_loop, test_ask_password,
647 teardown_without_loop, fixtures);
648 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/sync",
649 setup_without_loop, test_ask_password,
650 teardown_without_loop, fixtures);
652 /* Tests for g_tls_interaction_ask_password_async */
653 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/async",
654 setup_with_normal_loop, test_ask_password_async,
655 teardown_with_normal_loop, fixtures);
656 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/async",
657 setup_with_normal_loop, test_ask_password_async,
658 teardown_with_normal_loop, fixtures);
661 g_ptr_array_free (fixtures, TRUE);