[libgnome-keyring] Add more tests of cancellation, test tweaks
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgnome-keyring] Add more tests of cancellation, test tweaks
- Date: Tue, 31 Jan 2012 12:50:24 +0000 (UTC)
commit f40819ccd588856a6b87b509a9e83b1c1fa19928
Author: Stef Walter <stefw gnome org>
Date: Tue Jan 31 13:48:36 2012 +0100
Add more tests of cancellation, test tweaks
* Add some tests of cancellation
* Update the egg-testing.[ch] files, for running tests within
a mainloop
.gitignore | 2 +
egg/egg-testing.c | 161 +++++++++++++++++++++++++--
egg/egg-testing.h | 23 ++++
library/tests/Makefile.am | 1 +
library/tests/mock-service-cancel.py | 16 +++
library/tests/mock/service.py | 12 +-
library/tests/test-cancel.c | 203 ++++++++++++++++++++++++++++++++++
library/tests/test-keyrings.c | 47 ++------
8 files changed, 414 insertions(+), 51 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 719576e..618d46d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ run-auto-test.h
*.tmp
*.prj
*.pws
+*.pyc
*.anjuta
*.tar.gz
.*project
@@ -119,6 +120,7 @@ run-auto-test.h
/library/tests/frob-default-keyring
/library/tests/frob-unlock-keyring
/library/tests/test-any-daemon
+/library/tests/test-cancel
/library/tests/test-prompting
/library/tests/test-keyrings
/library/tests/test-memory
diff --git a/egg/egg-testing.c b/egg/egg-testing.c
index 458b71f..3b9a423 100644
--- a/egg/egg-testing.c
+++ b/egg/egg-testing.c
@@ -25,30 +25,83 @@
#include "egg-testing.h"
+#include <glib-object.h>
+
+#include <valgrind/valgrind.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
static const char HEXC[] = "0123456789ABCDEF";
-static gchar*
-hex_dump (const guchar *data, gsize n_data)
+gchar *
+egg_test_escape_data (const guchar *data,
+ gsize n_data)
{
GString *result;
+ gchar c;
gsize i;
guchar j;
- g_assert (data);
+ g_assert (data != NULL);
result = g_string_sized_new (n_data * 2 + 1);
for (i = 0; i < n_data; ++i) {
- g_string_append (result, "\\x");
-
- j = data[i] >> 4 & 0xf;
- g_string_append_c (result, HEXC[j]);
- j = data[i] & 0xf;
- g_string_append_c (result, HEXC[j]);
+ c = data[i];
+ if (g_ascii_isprint (c) && !strchr ("\n\r\v", c)) {
+ g_string_append_c (result, c);
+ } else {
+ g_string_append (result, "\\x");
+ j = c >> 4 & 0xf;
+ g_string_append_c (result, HEXC[j]);
+ j = c & 0xf;
+ g_string_append_c (result, HEXC[j]);
+ }
}
return g_string_free (result, FALSE);
}
+static gboolean
+is_readable_ptr (gpointer was_object)
+{
+ static gint test_memory_fd = -1;
+
+ /* First make sure this memory is still accessible */
+ if (test_memory_fd < 0)
+ test_memory_fd = g_open ("/dev/null", O_WRONLY, 0);
+ if (write (test_memory_fd, was_object, 1) > 0)
+ return TRUE;
+ return (errno != EFAULT);
+}
+
+void
+egg_assertion_not_object (const char *domain,
+ const char *file,
+ int line,
+ const char *func,
+ const char *expr,
+ gpointer was_object)
+{
+ gchar *s;
+
+ if (RUNNING_ON_VALGRIND)
+ return;
+
+ if (!is_readable_ptr (was_object))
+ return;
+
+ if (G_IS_OBJECT (was_object)) {
+ s = g_strdup_printf ("assertion failed: %s is still referenced", expr);
+ g_assertion_message (domain, file, line, func, s);
+ g_free (s);
+ }
+}
+
void
egg_assertion_message_cmpmem (const char *domain,
const char *file,
@@ -62,11 +115,97 @@ egg_assertion_message_cmpmem (const char *domain,
gsize n_arg2)
{
char *a1, *a2, *s;
- a1 = arg1 ? hex_dump (arg1, n_arg1) : g_strdup ("NULL");
- a2 = arg2 ? hex_dump (arg2, n_arg2) : g_strdup ("NULL");
+ a1 = arg1 ? egg_test_escape_data (arg1, n_arg1) : g_strdup ("NULL");
+ a2 = arg2 ? egg_test_escape_data (arg2, n_arg2) : g_strdup ("NULL");
s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2);
g_free (a1);
g_free (a2);
g_assertion_message (domain, file, line, func, s);
g_free (s);
}
+
+static void (*wait_stop_impl) (void);
+static gboolean (*wait_until_impl) (int timeout);
+
+void
+egg_test_wait_stop (void)
+{
+ g_assert (wait_stop_impl != NULL);
+ (wait_stop_impl) ();
+}
+
+gboolean
+egg_test_wait_until (int timeout)
+{
+ g_assert (wait_until_impl != NULL);
+ return (wait_until_impl) (timeout);
+}
+
+void
+egg_test_wait_idle (void)
+{
+ GMainContext *context;
+
+ g_assert (wait_until_impl != NULL);
+
+ context = g_main_context_get_thread_default ();
+ while (g_main_context_iteration (context, FALSE));
+}
+
+static GMainLoop *wait_loop = NULL;
+
+static void
+loop_wait_stop (void)
+{
+ g_assert (wait_loop != NULL);
+ g_main_loop_quit (wait_loop);
+}
+
+static gboolean
+on_loop_wait_timeout (gpointer data)
+{
+ gboolean *timed_out = data;
+ *timed_out = TRUE;
+
+ g_assert (wait_loop != NULL);
+ g_main_loop_quit (wait_loop);
+
+ return TRUE; /* we remove this source later */
+}
+
+static gboolean
+loop_wait_until (int timeout)
+{
+ gboolean timed_out = FALSE;
+ guint source;
+
+ g_assert (wait_loop == NULL);
+ wait_loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
+
+ source = g_timeout_add (timeout, on_loop_wait_timeout, &timed_out);
+
+ g_main_loop_run (wait_loop);
+
+ g_source_remove (source);
+ g_main_loop_unref (wait_loop);
+ wait_loop = NULL;
+ return !timed_out;
+}
+
+gint
+egg_tests_run_with_loop (void)
+{
+ gint ret;
+
+ wait_stop_impl = loop_wait_stop;
+ wait_until_impl = loop_wait_until;
+
+ ret = g_test_run ();
+
+ wait_stop_impl = NULL;
+ wait_until_impl = NULL;
+
+ while (g_main_context_iteration (NULL, FALSE));
+
+ return ret;
+}
diff --git a/egg/egg-testing.h b/egg/egg-testing.h
index 14bc8e9..d94379d 100644
--- a/egg/egg-testing.h
+++ b/egg/egg-testing.h
@@ -37,10 +37,33 @@
G_STRFUNC, #a "[" #na"] " #cmp " " #b "[" #nb "]", \
__p1, __n1, #cmp, __p2, __n2); } while (0)
+#define egg_assert_not_object(p) \
+ (egg_assertion_not_object (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, #p, (p)))
+
+void egg_assertion_not_object (const char *domain,
+ const char *file,
+ int line,
+ const char *func,
+ const char *expr,
+ gpointer was_object);
+
void egg_assertion_message_cmpmem (const char *domain, const char *file,
int line, const char *func,
const char *expr, gconstpointer arg1,
gsize n_arg1, const char *cmp,
gconstpointer arg2, gsize n_arg2);
+gchar * egg_test_escape_data (const guchar *data,
+ gsize size);
+
+void egg_test_wait_stop (void);
+
+#define egg_test_wait() g_assert (egg_test_wait_until (20000) != FALSE)
+
+gboolean egg_test_wait_until (int timeout);
+
+void egg_test_wait_idle (void);
+
+gint egg_tests_run_with_loop (void);
+
#endif /* EGG_DH_H_ */
diff --git a/library/tests/Makefile.am b/library/tests/Makefile.am
index 343eae4..7b67470 100644
--- a/library/tests/Makefile.am
+++ b/library/tests/Makefile.am
@@ -27,6 +27,7 @@ LDADD = \
TEST_PROGS = \
test-memory \
test-keyrings \
+ test-cancel \
test-other
check_PROGRAMS = \
diff --git a/library/tests/mock-service-cancel.py b/library/tests/mock-service-cancel.py
new file mode 100644
index 0000000..395b1ef
--- /dev/null
+++ b/library/tests/mock-service-cancel.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+import dbus
+import mock
+import time
+
+class SecretService(mock.SecretService):
+
+ @dbus.service.method('org.freedesktop.Secret.Service')
+ def SearchItems(self, attributes):
+ time.sleep(0.02)
+ return mock.SecretService.SearchItems(self, attributes)
+
+service = SecretService()
+service.add_standard_objects()
+service.listen()
\ No newline at end of file
diff --git a/library/tests/mock/service.py b/library/tests/mock/service.py
index 0ea3801..bb9fb82 100644
--- a/library/tests/mock/service.py
+++ b/library/tests/mock/service.py
@@ -488,18 +488,18 @@ class SecretService(dbus.service.Object):
def add_standard_objects(self):
collection = SecretCollection(self, "english", label="Collection One", locked=False)
- SecretItem(collection, "item_one", label="Item One",
+ SecretItem(collection, "1", label="Item One",
attributes={ "number": "1", "string": "one", "even": "false" },
secret="111", type="org.mock.type.Store")
- SecretItem(collection, "item_two", attributes={ "number": "2", "string": "two", "even": "true" }, secret="222")
- SecretItem(collection, "item_three", attributes={ "number": "3", "string": "three", "even": "false" }, secret="3333")
+ SecretItem(collection, "2", attributes={ "number": "2", "string": "two", "even": "true" }, secret="222")
+ SecretItem(collection, "3", attributes={ "number": "3", "string": "three", "even": "false" }, secret="3333")
self.set_alias('default', collection)
collection = SecretCollection(self, "spanish", locked=True)
- SecretItem(collection, "item_one", attributes={ "number": "1", "string": "uno", "even": "false" }, secret="111")
- SecretItem(collection, "item_two", attributes={ "number": "2", "string": "dos", "even": "true" }, secret="222")
- SecretItem(collection, "item_three", attributes={ "number": "3", "string": "tres", "even": "false" }, secret="3333")
+ SecretItem(collection, "10", attributes={ "number": "1", "string": "uno", "even": "false" }, secret="111")
+ SecretItem(collection, "20", attributes={ "number": "2", "string": "dos", "even": "true" }, secret="222")
+ SecretItem(collection, "30", attributes={ "number": "3", "string": "tres", "even": "false" }, secret="3333")
collection = SecretCollection(self, "empty", locked=False)
collection = SecretCollection(self, "session", label="Session Keyring", locked=False)
diff --git a/library/tests/test-cancel.c b/library/tests/test-cancel.c
new file mode 100644
index 0000000..70931f7
--- /dev/null
+++ b/library/tests/test-cancel.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-keyrings.c: Test basic keyring functionality
+
+ Copyright (C) 2012 Red Hat Inc.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stefw gnome org>
+*/
+
+#include "config.h"
+
+#include "gnome-keyring.h"
+#include "gkr-misc.h"
+
+#include "mock-service.h"
+
+#include "egg/egg-testing.h"
+
+static void
+on_items_found (GnomeKeyringResult result,
+ GList *list,
+ gpointer data)
+{
+ GnomeKeyringResult *res = data;
+ g_assert_cmpint (result, ==, *res);
+ egg_test_wait_stop ();
+}
+
+static void
+test_immediate (void)
+{
+ GnomeKeyringAttributeList *attrs;
+ GnomeKeyringResult res = GNOME_KEYRING_RESULT_CANCELLED;
+ gpointer operation;
+
+ attrs = gnome_keyring_attribute_list_new ();
+ gnome_keyring_attribute_list_append_string (attrs, "even", "false");
+
+ operation = gnome_keyring_find_items (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ attrs, on_items_found, &res, NULL);
+ gnome_keyring_attribute_list_free (attrs);
+
+ gnome_keyring_cancel_request (operation);
+
+ egg_test_wait ();
+}
+
+static void
+test_twice (void)
+{
+ GnomeKeyringAttributeList *attrs;
+ GnomeKeyringResult res = GNOME_KEYRING_RESULT_CANCELLED;
+ gpointer operation;
+
+ attrs = gnome_keyring_attribute_list_new ();
+ gnome_keyring_attribute_list_append_string (attrs, "even", "false");
+
+ operation = gnome_keyring_find_items (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ attrs, on_items_found, &res, NULL);
+ gnome_keyring_attribute_list_free (attrs);
+
+ gnome_keyring_cancel_request (operation);
+ gnome_keyring_cancel_request (operation);
+
+ egg_test_wait ();
+}
+
+typedef struct {
+ gint which;
+ GnomeKeyringResult expect;
+ gpointer operation;
+ GHashTable *requests;
+} Request;
+
+static void
+request_free (gpointer data)
+{
+ g_slice_free (Request, data);
+}
+
+static void
+on_intense_request (GnomeKeyringResult result,
+ GList *list,
+ gpointer data)
+{
+ Request *request = data;
+ g_assert_cmpint (result, ==, request->expect);
+ g_hash_table_remove (request->requests, &request->which);
+
+ if (result == GNOME_KEYRING_RESULT_CANCELLED)
+ g_printerr ("!");
+ else if (result == GNOME_KEYRING_RESULT_OK)
+ g_printerr (".");
+ else
+ g_printerr ("E");
+}
+
+static void
+test_intense (void)
+{
+ #define ITERATIONS 200
+ GnomeKeyringAttributeList *attrs;
+ Request *request;
+ GHashTable *requests;
+ GHashTableIter iter;
+ gint *lookup;
+ gint which;
+ gint i = 0;
+
+ attrs = gnome_keyring_attribute_list_new ();
+ gnome_keyring_attribute_list_append_string (attrs, "even", "false");
+
+ requests = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, NULL);
+
+ for (;;) {
+ if (i++ < ITERATIONS) {
+ request = g_slice_new0 (Request);
+ request->which = i;
+ request->requests = requests;
+ request->expect = GNOME_KEYRING_RESULT_OK;
+ request->operation = gnome_keyring_find_items (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ attrs, on_intense_request,
+ request, request_free);
+
+ g_hash_table_insert (requests, &request->which, request);
+ which = g_random_int_range (0, MIN (i, ITERATIONS));
+
+ } else {
+ g_hash_table_iter_init (&iter, requests);
+ if (!g_hash_table_iter_next (&iter, (gpointer *)&lookup, NULL))
+ break;
+ which = *lookup;
+ }
+
+ egg_test_wait_until (g_random_int_range (2, 50));
+ g_printerr (" ");
+
+ request = g_hash_table_lookup (requests, &which);
+ if (request != NULL) {
+ request->expect = GNOME_KEYRING_RESULT_CANCELLED;
+ gnome_keyring_cancel_request (request->operation);
+ }
+ }
+
+ g_hash_table_destroy (requests);
+ gnome_keyring_attribute_list_free (attrs);
+}
+
+int
+main (int argc, char **argv)
+{
+ const gchar *address;
+ GError *error = NULL;
+ const gchar *service;
+ int ret = 0;
+
+ g_test_init (&argc, &argv, NULL);
+ g_set_prgname ("test-cancel");
+
+ /* Need to have DBUS running */
+ address = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
+ if (!address || !address[0]) {
+ g_printerr ("no DBus session available, skipping tests.");
+ return 0;
+ }
+
+ service = g_getenv ("GNOME_KEYRING_TEST_SERVICE");
+ if (service && service[0])
+ service = NULL;
+
+ g_test_add_func ("/cancel/immediate", test_immediate);
+ g_test_add_func ("/cancel/twice", test_twice);
+ if (g_test_thorough ())
+ g_test_add_func ("/cancel/intense", test_intense);
+
+ if (service) {
+ g_printerr ("running tests against secret service: %s", service);
+ gkr_service_name = service;
+
+ } else if (!mock_service_start ("mock-service-cancel.py", &error)) {
+ g_printerr ("\nCouldn't start mock secret service: %s\n\n", error->message);
+ return 1;
+ }
+
+ ret = egg_tests_run_with_loop ();
+
+ mock_service_stop ();
+ return ret;
+}
diff --git a/library/tests/test-keyrings.c b/library/tests/test-keyrings.c
index 4a15b2f..13c7fac 100644
--- a/library/tests/test-keyrings.c
+++ b/library/tests/test-keyrings.c
@@ -28,6 +28,8 @@
#include "mock-service.h"
+#include "egg/egg-testing.h"
+
#include <glib.h>
#include <stdlib.h>
@@ -45,27 +47,6 @@ static gchar *default_name = NULL;
#define DISPLAY_NAME "Item Display Name"
#define SECRET "item-secret"
-static GMainLoop *mainloop = NULL;
-
-static gboolean
-quit_loop (gpointer data)
-{
- g_main_loop_quit (data);
- return TRUE;
-}
-
-static void
-mainloop_run (int timeout)
-{
- guint id = 0;
-
- if (timeout)
- id = g_timeout_add (timeout, quit_loop, mainloop);
- g_main_loop_run (mainloop);
- if (timeout)
- g_source_remove (id);
-}
-
static void
test_remove_incomplete (void)
{
@@ -410,7 +391,7 @@ static void
done_grant_access (GnomeKeyringResult res, gpointer data)
{
grant_access_result = res;
- g_main_loop_quit (mainloop);
+ egg_test_wait_stop ();
}
static void
@@ -437,7 +418,7 @@ test_keyring_grant_access (void)
/* "callback already called" */
g_assert_cmpint (grant_access_result, ==, GNOME_KEYRING_RESULT_CANCELLED);
- mainloop_run (2000);
+ egg_test_wait ();
g_assert_cmpint (GNOME_KEYRING_RESULT_OK, ==, grant_access_result);
@@ -465,7 +446,7 @@ static void
done_store_password (GnomeKeyringResult res, gpointer data)
{
*((GnomeKeyringResult*)data) = res;
- g_main_loop_quit (mainloop);
+ egg_test_wait_stop ();
}
static void
@@ -501,7 +482,7 @@ test_store_password (void)
/* "callback already called" */
g_assert_cmpint (res, ==, GNOME_KEYRING_RESULT_CANCELLED);
- mainloop_run (2000);
+ egg_test_wait ();
g_assert_cmpint (GNOME_KEYRING_RESULT_OK, ==, res);
}
@@ -520,7 +501,7 @@ done_find_password (GnomeKeyringResult res, const gchar* password, gpointer unus
g_assert_cmpstr (password, ==, "password");
}
- g_main_loop_quit (mainloop);
+ egg_test_wait_stop ();
}
static void
@@ -558,7 +539,7 @@ test_find_password (void)
/* "callback already called" */
g_assert (find_password_result == GNOME_KEYRING_RESULT_CANCELLED);
- mainloop_run (2000);
+ egg_test_wait ();
g_assert_cmpint (GNOME_KEYRING_RESULT_OK, ==, find_password_result);
}
@@ -570,7 +551,7 @@ done_find_no_password (GnomeKeyringResult res, const gchar* password, gpointer u
{
find_no_password_result = res;
g_assert (password == NULL);
- g_main_loop_quit (mainloop);
+ egg_test_wait_stop ();
}
static void
@@ -598,7 +579,7 @@ test_find_no_password (void)
g_assert (op != NULL);
g_assert (find_no_password_result == GNOME_KEYRING_RESULT_CANCELLED);
- mainloop_run (2000);
+ egg_test_wait ();
g_assert_cmpint (GNOME_KEYRING_RESULT_NO_MATCH, ==, find_no_password_result);
}
@@ -607,7 +588,7 @@ static void
done_delete_password (GnomeKeyringResult res, gpointer data)
{
*((GnomeKeyringResult*)data) = res;
- g_main_loop_quit (mainloop);
+ egg_test_wait_stop ();
}
static void
@@ -638,7 +619,7 @@ test_delete_password (void)
/* "callback already called" */
g_assert (res == GNOME_KEYRING_RESULT_CANCELLED);
- mainloop_run (2000);
+ egg_test_wait ();
/* Should have already been deleted by the second call above */
g_assert_cmpint (GNOME_KEYRING_RESULT_OK, ==, res);
@@ -694,8 +675,6 @@ main (int argc, char **argv)
if (service && service[0])
service = NULL;
- mainloop = g_main_loop_new (NULL, FALSE);
-
g_test_add_func ("/keyrings/remove-incomplete", test_remove_incomplete);
g_test_add_func ("/keyrings/create-keyring", test_create_keyring);
g_test_add_func ("/keyrings/create-keyring-already-exists", test_create_keyring_already_exists);
@@ -729,7 +708,7 @@ main (int argc, char **argv)
}
- ret = g_test_run ();
+ ret = egg_tests_run_with_loop ();
mock_service_stop ();
return ret;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]