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,
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 task = g_task_new (self, cancellable, callback, user_data);
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_task_return_int (task, G_TLS_INTERACTION_HANDLED);
101 g_object_unref (task);
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_task_is_valid (result, interaction));
118 g_assert (error != NULL);
119 g_assert (*error == NULL);
121 return g_task_propagate_int (G_TASK (result), error);
125 test_interaction_ask_password_async_failure (GTlsInteraction *interaction,
126 GTlsPassword *password,
127 GCancellable *cancellable,
128 GAsyncReadyCallback callback,
132 TestInteraction *self;
134 g_assert (TEST_IS_INTERACTION (interaction));
135 self = TEST_INTERACTION (interaction);
137 g_assert (g_thread_self () == self->test->interaction_thread);
139 g_assert (G_IS_TLS_PASSWORD (password));
140 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
142 task = g_task_new (self, cancellable, callback, user_data);
144 g_task_return_new_error (task, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
145 g_object_unref (task);
148 static GTlsInteractionResult
149 test_interaction_ask_password_finish_failure (GTlsInteraction *interaction,
150 GAsyncResult *result,
153 TestInteraction *self;
155 g_assert (TEST_IS_INTERACTION (interaction));
156 self = TEST_INTERACTION (interaction);
158 g_assert (g_thread_self () == self->test->interaction_thread);
160 g_assert (g_task_is_valid (result, interaction));
161 g_assert (error != NULL);
162 g_assert (*error == NULL);
164 if (g_task_propagate_int (G_TASK (result), error) != -1)
165 g_assert_not_reached ();
167 return G_TLS_INTERACTION_FAILED;
171 static GTlsInteractionResult
172 test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
173 GTlsPassword *password,
174 GCancellable *cancellable,
177 TestInteraction *self;
179 g_assert (TEST_IS_INTERACTION (interaction));
180 self = TEST_INTERACTION (interaction);
182 g_assert (g_thread_self () == self->test->interaction_thread);
184 g_assert (G_IS_TLS_PASSWORD (password));
185 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
186 g_assert (error != NULL);
187 g_assert (*error == NULL);
189 /* Don't do this in real life. Include a null terminator for testing */
190 g_tls_password_set_value (password, (const guchar *)"the password", 13);
191 return G_TLS_INTERACTION_HANDLED;
194 static GTlsInteractionResult
195 test_interaction_ask_password_sync_failure (GTlsInteraction *interaction,
196 GTlsPassword *password,
197 GCancellable *cancellable,
200 TestInteraction *self;
202 g_assert (TEST_IS_INTERACTION (interaction));
203 self = TEST_INTERACTION (interaction);
205 g_assert (g_thread_self () == self->test->interaction_thread);
207 g_assert (G_IS_TLS_PASSWORD (password));
208 g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
209 g_assert (error != NULL);
210 g_assert (*error == NULL);
212 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, "The message");
213 return G_TLS_INTERACTION_FAILED;
216 /* ----------------------------------------------------------------------------
221 on_ask_password_async_call (GObject *source,
222 GAsyncResult *result,
225 Test *test = user_data;
226 GTlsInteractionResult res;
227 GError *error = NULL;
229 g_assert (G_IS_TLS_INTERACTION (source));
230 g_assert (G_TLS_INTERACTION (source) == test->interaction);
232 /* Check that this callback is being run in the right place */
233 g_assert (g_thread_self () == test->interaction_thread);
235 res = g_tls_interaction_ask_password_finish (test->interaction, result,
238 /* Check that the results match the fixture */
239 g_assert_cmpuint (test->fixture->result, ==, res);
240 switch (test->fixture->result)
242 case G_TLS_INTERACTION_HANDLED:
243 g_assert_no_error (error);
244 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
246 case G_TLS_INTERACTION_FAILED:
247 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
248 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
249 g_clear_error (&error);
251 case G_TLS_INTERACTION_UNHANDLED:
252 g_assert_no_error (error);
255 g_assert_not_reached ();
258 /* Signal the end of the test */
259 g_main_loop_quit (test->loop);
263 test_ask_password_async (Test *test,
264 gconstpointer unused)
266 /* This test only works with a main loop */
267 g_assert (test->loop);
269 g_tls_interaction_ask_password_async (test->interaction,
270 test->password, NULL,
271 on_ask_password_async_call,
274 /* teardown waits until g_main_loop_quit(). called from callback */
278 test_invoke_ask_password (Test *test,
279 gconstpointer unused)
281 GTlsInteractionResult res;
282 GError *error = NULL;
284 res = g_tls_interaction_invoke_ask_password (test->interaction, test->password,
287 /* Check that the results match the fixture */
288 g_assert_cmpuint (test->fixture->result, ==, res);
289 switch (test->fixture->result)
291 case G_TLS_INTERACTION_HANDLED:
292 g_assert_no_error (error);
293 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
295 case G_TLS_INTERACTION_FAILED:
296 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
297 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
298 g_clear_error (&error);
300 case G_TLS_INTERACTION_UNHANDLED:
301 g_assert_no_error (error);
304 g_assert_not_reached ();
307 /* This allows teardown to stop if running with loop */
309 g_main_loop_quit (test->loop);
313 test_ask_password (Test *test,
314 gconstpointer unused)
316 GTlsInteractionResult res;
317 GError *error = NULL;
319 res = g_tls_interaction_ask_password (test->interaction, test->password,
322 /* Check that the results match the fixture */
323 g_assert_cmpuint (test->fixture->result, ==, res);
324 switch (test->fixture->result)
326 case G_TLS_INTERACTION_HANDLED:
327 g_assert_no_error (error);
328 g_assert_cmpstr ((const gchar *)g_tls_password_get_value (test->password, NULL), ==, "the password");
330 case G_TLS_INTERACTION_FAILED:
331 g_assert_error (error, test->fixture->error_domain, test->fixture->error_code);
332 g_assert_cmpstr (error->message, ==, test->fixture->error_message);
333 g_clear_error (&error);
335 case G_TLS_INTERACTION_UNHANDLED:
336 g_assert_no_error (error);
339 g_assert_not_reached ();
342 /* This allows teardown to stop if running with loop */
344 g_main_loop_quit (test->loop);
347 /* ----------------------------------------------------------------------------
352 setup_without_loop (Test *test,
353 gconstpointer user_data)
355 const Fixture *fixture = user_data;
356 GTlsInteractionClass *klass;
357 test->fixture = fixture;
359 test->interaction = g_object_new (TEST_TYPE_INTERACTION, NULL);
360 g_assert (TEST_IS_INTERACTION (test->interaction));
362 TEST_INTERACTION (test->interaction)->test = test;
364 klass = G_TLS_INTERACTION_GET_CLASS (test->interaction);
365 klass->ask_password = fixture->ask_password_func;
366 klass->ask_password_async = fixture->ask_password_async_func;
367 klass->ask_password_finish = fixture->ask_password_finish_func;
369 test->password = g_tls_password_new (0, "Description");
370 test->test_thread = g_thread_self ();
373 * If no loop is running then interaction should happen in the same
374 * thread that the tests are running in.
376 test->interaction_thread = test->test_thread;
380 teardown_without_loop (Test *test,
381 gconstpointer unused)
383 gpointer weak_pointer = test->interaction;
385 g_object_add_weak_pointer (weak_pointer, &weak_pointer);
387 g_object_unref (test->password);
389 g_object_unref (test->interaction);
391 g_assert (weak_pointer == NULL);
403 thread_loop (gpointer user_data)
405 GMainContext *context = g_main_context_default ();
406 ThreadLoop *closure = user_data;
407 Test *test = closure->test;
409 g_mutex_lock (&closure->loop_mutex);
411 g_assert (test->loop_thread == g_thread_self ());
412 g_assert (test->loop == NULL);
413 test->loop = g_main_loop_new (context, TRUE);
415 g_main_context_acquire (context);
416 closure->started = TRUE;
417 g_cond_signal (&closure->loop_started);
418 g_mutex_unlock (&closure->loop_mutex);
420 while (g_main_loop_is_running (test->loop))
421 g_main_context_iteration (context, TRUE);
423 g_main_context_release (context);
428 setup_with_thread_loop (Test *test,
429 gconstpointer user_data)
433 setup_without_loop (test, user_data);
435 g_mutex_init (&closure.loop_mutex);
436 g_cond_init (&closure.loop_started);
437 closure.started = FALSE;
440 g_mutex_lock (&closure.loop_mutex);
441 test->loop_thread = g_thread_new ("loop", thread_loop, &closure);
442 while (!closure.started)
443 g_cond_wait (&closure.loop_started, &closure.loop_mutex);
444 g_mutex_unlock (&closure.loop_mutex);
447 * When a loop is running then interaction should always occur in the main
448 * context of that loop.
450 test->interaction_thread = test->loop_thread;
452 g_mutex_clear (&closure.loop_mutex);
453 g_cond_clear (&closure.loop_started);
457 teardown_with_thread_loop (Test *test,
458 gconstpointer unused)
462 g_assert (test->loop_thread);
463 check = g_thread_join (test->loop_thread);
464 g_assert (check == test);
465 test->loop_thread = NULL;
467 g_main_loop_unref (test->loop);
469 teardown_without_loop (test, unused);
473 setup_with_normal_loop (Test *test,
474 gconstpointer user_data)
476 GMainContext *context;
478 setup_without_loop (test, user_data);
480 context = g_main_context_default ();
481 if (!g_main_context_acquire (context))
482 g_assert_not_reached ();
484 test->loop = g_main_loop_new (context, TRUE);
485 g_assert (g_main_loop_is_running (test->loop));
489 teardown_with_normal_loop (Test *test,
490 gconstpointer unused)
492 GMainContext *context;
494 context = g_main_context_default ();
495 while (g_main_loop_is_running (test->loop))
496 g_main_context_iteration (context, TRUE);
498 g_main_context_release (context);
500 /* Run test until complete */
501 g_main_loop_unref (test->loop);
504 teardown_without_loop (test, unused);
507 typedef void (*TestFunc) (Test *test, gconstpointer data);
510 test_with_async_ask_password_implementations (const gchar *name,
519 /* Async implementation that succeeds */
520 fixture = g_new0 (Fixture, 1);
521 fixture->ask_password_async_func = test_interaction_ask_password_async_success;
522 fixture->ask_password_finish_func = test_interaction_ask_password_finish_success;
523 fixture->ask_password_func = NULL;
524 fixture->result = G_TLS_INTERACTION_HANDLED;
525 test_name = g_strdup_printf ("%s/async-implementation-success", name);
526 g_test_add (test_name, Test, fixture, setup, func, teardown);
528 g_ptr_array_add (fixtures, fixture);
530 /* Async implementation that fails */
531 fixture = g_new0 (Fixture, 1);
532 fixture->ask_password_async_func = test_interaction_ask_password_async_failure;
533 fixture->ask_password_finish_func = test_interaction_ask_password_finish_failure;
534 fixture->ask_password_func = NULL;
535 fixture->result = G_TLS_INTERACTION_FAILED;
536 fixture->error_domain = G_FILE_ERROR;
537 fixture->error_code = G_FILE_ERROR_ACCES;
538 fixture->error_message = "The message";
539 test_name = g_strdup_printf ("%s/async-implementation-failure", name);
540 g_test_add (test_name, Test, fixture, setup, func, teardown);
542 g_ptr_array_add (fixtures, fixture);
545 test_with_unhandled_ask_password_implementations (const gchar *name,
554 /* Unhandled implementation */
555 fixture = g_new0 (Fixture, 1);
556 fixture->ask_password_async_func = NULL;
557 fixture->ask_password_finish_func = NULL;
558 fixture->ask_password_func = NULL;
559 fixture->result = G_TLS_INTERACTION_UNHANDLED;
560 test_name = g_strdup_printf ("%s/unhandled-implementation", name);
561 g_test_add (test_name, Test, fixture, setup, func, teardown);
563 g_ptr_array_add (fixtures, fixture);
567 test_with_sync_ask_password_implementations (const gchar *name,
576 /* Sync implementation that succeeds */
577 fixture = g_new0 (Fixture, 1);
578 fixture->ask_password_async_func = NULL;
579 fixture->ask_password_finish_func = NULL;
580 fixture->ask_password_func = test_interaction_ask_password_sync_success;
581 fixture->result = G_TLS_INTERACTION_HANDLED;
582 test_name = g_strdup_printf ("%s/sync-implementation-success", name);
583 g_test_add (test_name, Test, fixture, setup, func, teardown);
585 g_ptr_array_add (fixtures, fixture);
587 /* Async implementation that fails */
588 fixture = g_new0 (Fixture, 1);
589 fixture->ask_password_async_func = NULL;
590 fixture->ask_password_finish_func = NULL;
591 fixture->ask_password_func = test_interaction_ask_password_sync_failure;
592 fixture->result = G_TLS_INTERACTION_FAILED;
593 fixture->error_domain = G_FILE_ERROR;
594 fixture->error_code = G_FILE_ERROR_ACCES;
595 fixture->error_message = "The message";
596 test_name = g_strdup_printf ("%s/sync-implementation-failure", name);
597 g_test_add (test_name, Test, fixture, setup, func, teardown);
599 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);