diff --git a/egg/egg-testing.c b/egg/egg-testing.c index 7fa2a60..5a4f3e5 100644 --- a/egg/egg-testing.c +++ b/egg/egg-testing.c @@ -29,7 +29,11 @@ #include +#include +#include + #include +#include #include static const char HEXC[] = "0123456789ABCDEF"; @@ -56,6 +60,19 @@ hex_dump (const guchar *data, gsize n_data) 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, @@ -68,6 +85,10 @@ egg_assertion_not_object (const char *domain, 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); diff --git a/library/gsecret-methods.c b/library/gsecret-methods.c index bef8e58..fdcaeca 100644 --- a/library/gsecret-methods.c +++ b/library/gsecret-methods.c @@ -1973,7 +1973,6 @@ collection_closure_free (gpointer data) CollectionClosure *closure = data; g_clear_object (&closure->cancellable); g_clear_object (&closure->prompt); - g_slice_free (CollectionClosure, closure); } @@ -2063,12 +2062,12 @@ gsecret_service_create_collection_path (GSecretService *self, res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gsecret_service_create_collection_path); - closure = g_new0 (CollectionClosure, 1); + closure = g_slice_new0 (CollectionClosure); closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; g_simple_async_result_set_op_res_gpointer (res, closure, collection_closure_free); props = _gsecret_util_variant_for_properties (properties); - params = g_variant_new ("(@a{sv}a)", props, alias); + params = g_variant_new ("(@a{sv}s)", props, alias); proxy = G_DBUS_PROXY (self); g_dbus_connection_call (g_dbus_proxy_get_connection (proxy), @@ -2095,7 +2094,7 @@ gsecret_service_create_collection_path_finish (GSecretService *self, gchar *path; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), - gsecret_collection_create), NULL); + gsecret_service_create_collection_path), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); res = G_SIMPLE_ASYNC_RESULT (result); @@ -2349,7 +2348,7 @@ gsecret_service_create_item_path_sync (GSecretService *self, g_main_loop_run (sync->loop); - path = gsecret_service_create_collection_path_finish (self, sync->result, error); + path = gsecret_service_create_item_path_finish (self, sync->result, error); g_main_context_pop_thread_default (sync->context); _gsecret_sync_free (sync); diff --git a/library/tests/mock-service-prompt.py b/library/tests/mock-service-prompt.py index 785b147..ceb4ad8 100644 --- a/library/tests/mock-service-prompt.py +++ b/library/tests/mock-service-prompt.py @@ -34,7 +34,9 @@ service.add_standard_objects() mock.SecretPrompt(service, None, "simple") mock.SecretPrompt(service, None, "delay", delay=0.5) -mock.SecretPrompt(service, None, "result", result=dbus.String("Special Result", variant_level=1)) +def prompt_callback(): + return dbus.String("Special Result", variant_level=1) +mock.SecretPrompt(service, None, "result", action=prompt_callback) ErrorPrompt(service, None, "error") VanishPrompt(service, None, "vanish") WindowPrompt(service, None, "window") diff --git a/library/tests/mock/service.py b/library/tests/mock/service.py index e15140c..3cc937d 100644 --- a/library/tests/mock/service.py +++ b/library/tests/mock/service.py @@ -109,13 +109,12 @@ class AesAlgorithm(): class SecretPrompt(dbus.service.Object): def __init__(self, service, sender, prompt_name=None, delay=0, - dismiss=False, result=dbus.String("", variant_level=1), - action=None): + dismiss=False, action=None): self.sender = sender self.service = service self.delay = 0 self.dismiss = False - self.result = result + self.result = dbus.String("", variant_level=1) self.action = action self.completed = False if prompt_name: @@ -137,7 +136,7 @@ class SecretPrompt(dbus.service.Object): @dbus.service.method('org.freedesktop.Secret.Prompt') def Prompt(self, window_id): if self.action: - self.action() + self.result = self.action() gobject.timeout_add(self.delay * 1000, self._complete) @dbus.service.method('org.freedesktop.Secret.Prompt') @@ -222,9 +221,13 @@ class SecretItem(dbus.service.Object): @dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender') def Delete(self, sender=None): + item = self + def prompt_callback(): + item.perform_delete() + return dbus.String("", variant_level=1) if self.confirm: prompt = SecretPrompt(self.collection.service, sender, - dismiss=False, action=self.perform_delete) + dismiss=False, action=prompt_callback) return dbus.ObjectPath(prompt.path) else: self.perform_delete() @@ -330,9 +333,13 @@ class SecretCollection(dbus.service.Object): @dbus.service.method('org.freedesktop.Secret.Collection', sender_keyword='sender') def Delete(self, sender=None): + collection = self + def prompt_callback(): + collection.perform_delete() + return dbus.String("", variant_level=1) if self.confirm: prompt = SecretPrompt(self.collection.service, sender, - dismiss=False, action=self.perform_delete) + dismiss=False, action=prompt_callback) return dbus.ObjectPath(prompt.path) else: self.perform_delete() @@ -459,10 +466,10 @@ class SecretService(dbus.service.Object): def prompt_callback(): for object in prompts: object.perform_xlock(lock) + return dbus.Array([o.path for o in prompts], signature='o') locked = dbus.Array(locked, signature='o') if prompts: - prompt = SecretPrompt(self, sender, dismiss=False, action=prompt_callback, - result=dbus.Array([o.path for o in prompts], signature='o')) + prompt = SecretPrompt(self, sender, dismiss=False, action=prompt_callback) return (locked, dbus.ObjectPath(prompt.path)) else: return (locked, dbus.ObjectPath("/")) @@ -480,6 +487,16 @@ class SecretService(dbus.service.Object): return self.algorithms[algorithm].negotiate(self, sender, param) + @dbus.service.method('org.freedesktop.Secret.Service', sender_keyword='sender') + def CreateCollection(self, properties, alias, sender=None): + label = properties.get("org.freedesktop.Secret.Item.Label", None) + service = self + def prompt_callback(): + collection = SecretCollection(service, next_identifier('c'), label, locked=False, confirm=True) + return dbus.ObjectPath(collection.path, variant_level=1) + prompt = SecretPrompt(self, sender, dismiss=False, action=prompt_callback) + return (dbus.ObjectPath("/"), dbus.ObjectPath(prompt.path)) + @dbus.service.method('org.freedesktop.Secret.Service') def SearchItems(self, attributes): locked = [ ] diff --git a/library/tests/test-methods.c b/library/tests/test-methods.c index 8d93614..9408064 100644 --- a/library/tests/test-methods.c +++ b/library/tests/test-methods.c @@ -819,6 +819,156 @@ test_unlock_sync (Test *test, g_object_unref (collection); } +static void +test_collection_sync (Test *test, + gconstpointer used) +{ + GHashTable *properties; + GError *error = NULL; + gchar *path; + + properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + (GDestroyNotify)g_variant_unref); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Label", + g_variant_ref_sink (g_variant_new_string ("Wheeee"))); + + path = gsecret_service_create_collection_path_sync (test->service, properties, + NULL, NULL, &error); + + g_hash_table_unref (properties); + + g_assert_no_error (error); + g_assert (path != NULL); + g_assert (g_str_has_prefix (path, "/org/freedesktop/secrets/collection/")); + + g_free (path); +} + +static void +test_collection_async (Test *test, + gconstpointer used) +{ + GAsyncResult *result = NULL; + GHashTable *properties; + GError *error = NULL; + gchar *path; + + properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + (GDestroyNotify)g_variant_unref); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Label", + g_variant_ref_sink (g_variant_new_string ("Wheeee"))); + + gsecret_service_create_collection_path (test->service, properties, + NULL, NULL, on_complete_get_result, &result); + + g_hash_table_unref (properties); + g_assert (result == NULL); + + egg_test_wait (); + + path = gsecret_service_create_collection_path_finish (test->service, result, &error); + g_object_unref (result); + + g_assert_no_error (error); + g_assert (path != NULL); + g_assert (g_str_has_prefix (path, "/org/freedesktop/secrets/collection/")); + + g_free (path); +} + +static void +test_item_sync (Test *test, + gconstpointer used) +{ + const gchar *collection_path = "/org/freedesktop/secrets/collection/english"; + GHashTable *properties; + GHashTable *attributes; + GSecretValue *value; + GError *error = NULL; + gchar *path; + + attributes = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (attributes, "even", "true"); + g_hash_table_insert (attributes, "string", "ten"); + g_hash_table_insert (attributes, "number", "10"); + + properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + (GDestroyNotify)g_variant_unref); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Label", + g_variant_ref_sink (g_variant_new_string ("Wheeee"))); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Attributes", + g_variant_ref_sink (_gsecret_util_variant_for_attributes (attributes))); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Schema", + g_variant_ref_sink (g_variant_new_string ("org.gnome.Test"))); + + g_hash_table_unref (attributes); + + value = gsecret_value_new ("andmoreandmore", -1, "text/plain"); + + path = gsecret_service_create_item_path_sync (test->service, collection_path, + properties, value, FALSE, + NULL, &error); + + gsecret_value_unref (value); + g_hash_table_unref (properties); + + g_assert_no_error (error); + g_assert (path != NULL); + g_assert (g_str_has_prefix (path, collection_path)); + + g_free (path); +} + +static void +test_item_async (Test *test, + gconstpointer used) +{ + const gchar *collection_path = "/org/freedesktop/secrets/collection/english"; + GHashTable *properties; + GHashTable *attributes; + GSecretValue *value; + GError *error = NULL; + GAsyncResult *result = NULL; + gchar *path; + + attributes = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (attributes, "even", "true"); + g_hash_table_insert (attributes, "string", "ten"); + g_hash_table_insert (attributes, "number", "10"); + + properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + (GDestroyNotify)g_variant_unref); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Label", + g_variant_ref_sink (g_variant_new_string ("Wheeee"))); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Attributes", + g_variant_ref_sink (_gsecret_util_variant_for_attributes (attributes))); + g_hash_table_insert (properties, GSECRET_COLLECTION_INTERFACE ".Schema", + g_variant_ref_sink (g_variant_new_string ("org.gnome.Test"))); + + g_hash_table_unref (attributes); + + value = gsecret_value_new ("andmoreandmore", -1, "text/plain"); + + gsecret_service_create_item_path (test->service, collection_path, + properties, value, FALSE, + NULL, on_complete_get_result, &result); + + g_assert (result == NULL); + gsecret_value_unref (value); + g_hash_table_unref (properties); + + egg_test_wait (); + + path = gsecret_service_create_item_path_finish (test->service, result, &error); + g_object_unref (result); + + g_assert_no_error (error); + g_assert (path != NULL); + g_assert (g_str_has_prefix (path, collection_path)); + + g_free (path); +} + static void test_remove_sync (Test *test, gconstpointer used) @@ -1047,7 +1197,6 @@ test_store_replace (Test *test, GError *error = NULL; gchar **paths; gboolean ret; - gsize length; ret = gsecret_service_store_sync (test->service, &STORE_SCHEMA, collection_path, "New Item Label", value, NULL, &error, @@ -1080,15 +1229,6 @@ test_store_replace (Test *test, g_assert (paths[0] != NULL); g_assert (paths[1] == NULL); - value = gsecret_service_get_secret_for_path_sync (test->service, paths[0], - NULL, &error); - g_assert_no_error (error); - - g_assert (value != NULL); - g_assert_cmpstr (gsecret_value_get (value, &length), ==, "apassword"); - g_assert_cmpuint (length, ==, 9); - - gsecret_value_unref (value); g_strfreev (paths); } @@ -1106,11 +1246,11 @@ test_store_async (Test *test, gsize length; gsecret_service_store (test->service, &STORE_SCHEMA, collection_path, - "New Item Label", value, NULL, on_complete_get_result, &result, - "even", FALSE, - "string", "seventeen", - "number", 17, - NULL); + "New Item Label", value, NULL, on_complete_get_result, &result, + "even", FALSE, + "string", "seventeen", + "number", 17, + NULL); g_assert (result == NULL); gsecret_value_unref (value); @@ -1179,6 +1319,12 @@ main (int argc, char **argv) g_test_add ("/service/unlock-prompt-sync", Test, "mock-service-lock.py", setup, test_unlock_prompt_sync, teardown); g_test_add ("/service/unlock-sync", Test, "mock-service-lock.py", setup, test_unlock_sync, teardown); + g_test_add ("/service/create-collection-sync", Test, "mock-service-normal.py", setup, test_collection_sync, teardown); + g_test_add ("/service/create-collection-async", Test, "mock-service-normal.py", setup, test_collection_async, teardown); + + g_test_add ("/service/create-item-sync", Test, "mock-service-normal.py", setup, test_item_sync, teardown); + g_test_add ("/service/create-item-async", Test, "mock-service-normal.py", setup, test_item_async, teardown); + g_test_add ("/service/lookup-sync", Test, "mock-service-normal.py", setup, test_lookup_sync, teardown); g_test_add ("/service/lookup-async", Test, "mock-service-normal.py", setup, test_lookup_async, teardown); g_test_add ("/service/lookup-locked", Test, "mock-service-normal.py", setup, test_lookup_locked, teardown);