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 g_object_unref (test->password);
389 g_object_unref (test->interaction);
390 g_assert (!G_IS_OBJECT (test->interaction));
402 thread_loop (gpointer user_data)
404 GMainContext *context = g_main_context_default ();
405 ThreadLoop *closure = user_data;
406 Test *test = closure->test;
408 g_mutex_lock (&closure->loop_mutex);
410 g_assert (test->loop_thread == g_thread_self ());
411 g_assert (test->loop == NULL);
412 test->loop = g_main_loop_new (context, TRUE);
414 g_main_context_acquire (context);
415 closure->started = TRUE;
416 g_cond_signal (&closure->loop_started);
417 g_mutex_unlock (&closure->loop_mutex);
419 while (g_main_loop_is_running (test->loop))
420 g_main_context_iteration (context, TRUE);
422 g_main_context_release (context);
427 setup_with_thread_loop (Test *test,
428 gconstpointer user_data)
432 setup_without_loop (test, user_data);
434 g_mutex_init (&closure.loop_mutex);
435 g_cond_init (&closure.loop_started);
436 closure.started = FALSE;
439 g_mutex_lock (&closure.loop_mutex);
440 test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
441 while (!closure.started)
442 g_cond_wait (&closure.loop_started, &closure.loop_mutex);
443 g_mutex_unlock (&closure.loop_mutex);
446 * When a loop is running then interaction should always occur in the main
447 * context of that loop.
449 test->interaction_thread = test->loop_thread;
451 g_mutex_clear (&closure.loop_mutex);
452 g_cond_clear (&closure.loop_started);
456 teardown_with_thread_loop (Test *test,
457 gconstpointer unused)
461 g_assert (test->loop_thread);
462 check = g_thread_join (test->loop_thread);
463 g_assert (check == test);
464 test->loop_thread = NULL;
466 g_main_loop_unref (test->loop);
468 teardown_without_loop (test, unused);
472 setup_with_normal_loop (Test *test,
473 gconstpointer user_data)
475 GMainContext *context;
477 setup_without_loop (test, user_data);
479 context = g_main_context_default ();
480 if (!g_main_context_acquire (context))
481 g_assert_not_reached ();
483 test->loop = g_main_loop_new (context, TRUE);
484 g_assert (g_main_loop_is_running (test->loop));
488 teardown_with_normal_loop (Test *test,
489 gconstpointer unused)
491 GMainContext *context;
493 context = g_main_context_default ();
494 while (g_main_loop_is_running (test->loop))
495 g_main_context_iteration (context, TRUE);
497 g_main_context_release (context);
499 /* Run test until complete */
500 g_main_loop_unref (test->loop);
503 teardown_without_loop (test, unused);
506 typedef void (*TestFunc) (Test *test, gconstpointer data);
509 test_with_async_ask_password_implementations (const gchar *name,
518 /* Async implementation that succeeds */
519 fixture = g_new0 (Fixture, 1);
520 fixture->ask_password_async_func = test_interaction_ask_password_async_success;
521 fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
522 fixture->ask_password_func = NULL;
523 fixture->result = G_TLS_INTERACTION_HANDLED;
524 test_name = g_strdup_printf ("%s/async-implementation-success", name);
525 g_test_add (test_name, Test, fixture, setup, func, teardown);
527 g_ptr_array_add (fixtures, fixture);
529 /* Async implementation that fails */
530 fixture = g_new0 (Fixture, 1);
531 fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
532 fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
533 fixture->ask_password_func = NULL;
534 fixture->result = G_TLS_INTERACTION_FAILED;
535 fixture->error_domain = G_FILE_ERROR;
536 fixture->error_code = G_FILE_ERROR_ACCES;
537 fixture->error_message = "The message";
538 test_name = g_strdup_printf ("%s/async-implementation-failure", name);
539 g_test_add (test_name, Test, fixture, setup, func, teardown);
541 g_ptr_array_add (fixtures, fixture);
544 test_with_unhandled_ask_password_implementations (const gchar *name,
553 /* Unhandled implementation */
554 fixture = g_new0 (Fixture, 1);
555 fixture->ask_password_async_func = NULL;
556 fixture->ask_password_finish_func = NULL;
557 fixture->ask_password_func = NULL;
558 fixture->result = G_TLS_INTERACTION_UNHANDLED;
559 test_name = g_strdup_printf ("%s/unhandled-implementation", name);
560 g_test_add (test_name, Test, fixture, setup, func, teardown);
562 g_ptr_array_add (fixtures, fixture);
566 test_with_sync_ask_password_implementations (const gchar *name,
575 /* Sync implementation that succeeds */
576 fixture = g_new0 (Fixture, 1);
577 fixture->ask_password_async_func = NULL;
578 fixture->ask_password_finish_func = NULL;
579 fixture->ask_password_func = test_interaction_ask_password_sync_success;
580 fixture->result = G_TLS_INTERACTION_HANDLED;
581 test_name = g_strdup_printf ("%s/sync-implementation-success", name);
582 g_test_add (test_name, Test, fixture, setup, func, teardown);
584 g_ptr_array_add (fixtures, fixture);
586 /* Async implementation that fails */
587 fixture = g_new0 (Fixture, 1);
588 fixture->ask_password_async_func = NULL;
589 fixture->ask_password_finish_func = NULL;
590 fixture->ask_password_func = test_interaction_ask_password_sync_failure;
591 fixture->result = G_TLS_INTERACTION_FAILED;
592 fixture->error_domain = G_FILE_ERROR;
593 fixture->error_code = G_FILE_ERROR_ACCES;
594 fixture->error_message = "The message";
595 test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
596 g_test_add (test_name, Test, fixture, setup, func, teardown);
598 g_ptr_array_add (fixtures, fixture);
609 g_test_init (&argc, &argv, NULL);
611 fixtures = g_ptr_array_new_with_free_func (g_free);
613 /* Tests for g_tls_interaction_invoke_ask_password */
615 test_with_unhandled_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_async_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);
621 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-with-loop",
622 setup_with_thread_loop, test_invoke_ask_password,
623 teardown_with_thread_loop, fixtures);
625 test_with_unhandled_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_async_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
629 setup_without_loop, test_invoke_ask_password,
630 teardown_without_loop, fixtures);
631 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-without-loop",
632 setup_without_loop, test_invoke_ask_password,
633 teardown_without_loop, fixtures);
635 test_with_unhandled_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_async_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);
641 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/invoke-in-loop",
642 setup_with_normal_loop, test_invoke_ask_password,
643 teardown_with_normal_loop, fixtures);
645 /* Tests for g_tls_interaction_ask_password */
646 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/sync",
647 setup_without_loop, test_ask_password,
648 teardown_without_loop, fixtures);
649 test_with_sync_ask_password_implementations ("/tls-interaction/ask-password/sync",
650 setup_without_loop, test_ask_password,
651 teardown_without_loop, fixtures);
653 /* Tests for g_tls_interaction_ask_password_async */
654 test_with_unhandled_ask_password_implementations ("/tls-interaction/ask-password/async",
655 setup_with_normal_loop, test_ask_password_async,
656 teardown_with_normal_loop, fixtures);
657 test_with_async_ask_password_implementations ("/tls-interaction/ask-password/async",
658 setup_with_normal_loop, test_ask_password_async,
659 teardown_with_normal_loop, fixtures);
662 g_ptr_array_free (fixtures, TRUE);