From d797ef2ba358a98a48d7965b6ac6047fdeb2c6fb Mon Sep 17 00:00:00 2001 From: Stef Walter <stefw@gnome.org> Date: Mon, 30 Jan 2012 17:49:22 +0100 Subject: [PATCH] Testing item stuff, and fixing bugs --- egg/egg-testing.c | 28 +++--- egg/egg-testing.h | 3 + library/gsecret-item.c | 1 + library/org.freedesktop.Secrets.xml | 2 + library/tests/mock/service.py | 32 +++++-- library/tests/test-collection.c | 74 +++++++++++++--- library/tests/test-item.c | 133 +++++++++++++++++++++++++++- 7 files changed, 238 insertions(+), 35 deletions(-) diff --git a/egg/egg-testing.c b/egg/egg-testing.c index 5a4f3e5..3b9a423 100644 --- a/egg/egg-testing.c +++ b/egg/egg-testing.c @@ -38,23 +38,29 @@ 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); @@ -109,8 +115,8 @@ 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); diff --git a/egg/egg-testing.h b/egg/egg-testing.h index 3ed8081..d94379d 100644 --- a/egg/egg-testing.h +++ b/egg/egg-testing.h @@ -53,6 +53,9 @@ void egg_assertion_message_cmpmem (const char *domain, const char * 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) diff --git a/library/gsecret-item.c b/library/gsecret-item.c index 2f2bcb6..b49dc66 100644 --- a/library/gsecret-item.c +++ b/library/gsecret-item.c @@ -962,6 +962,7 @@ gsecret_item_set_secret (GSecretItem *self, user_data, gsecret_item_set_secret); closure = g_slice_new0 (SetClosure); closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + closure->value = gsecret_value_ref (value); g_simple_async_result_set_op_res_gpointer (res, closure, set_closure_free); gsecret_service_ensure_session (self->pv->service, cancellable, diff --git a/library/org.freedesktop.Secrets.xml b/library/org.freedesktop.Secrets.xml index 8182df4..7472ff6 100644 --- a/library/org.freedesktop.Secrets.xml +++ b/library/org.freedesktop.Secrets.xml @@ -119,6 +119,8 @@ <property name="Modified" type="t" access="read"/> + <property name="Schema" type="s" access="read"/> + <method name="Delete"> <arg name="Prompt" type="o" direction="out"/> </method> diff --git a/library/tests/mock/service.py b/library/tests/mock/service.py index 3cc937d..fa205fa 100644 --- a/library/tests/mock/service.py +++ b/library/tests/mock/service.py @@ -179,11 +179,13 @@ class SecretSession(dbus.service.Object): class SecretItem(dbus.service.Object): def __init__(self, collection, identifier, label="Item", attributes={ }, - secret="", confirm=False, content_type="text/plain"): + secret="", confirm=False, content_type="text/plain", + schema="org.freedesktop.Secret.Generic"): self.collection = collection self.identifier = identifier - self.label = label + self.label = label or "Unnamed item" self.secret = secret + self.schema = schema self.attributes = attributes self.content_type = content_type self.path = "%s/%s" % (collection.path, identifier) @@ -219,6 +221,15 @@ class SecretItem(dbus.service.Object): raise IsLocked("secret is locked: %s" % self.path) return session.encode_secret(self.secret, self.content_type) + @dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender', byte_arrays=True) + def SetSecret(self, secret, sender=None): + session = objects.get(secret[0], None) + if not session or session.sender != sender: + raise InvalidArgs("session invalid: %s" % secret[0]) + if self.get_locked(): + raise IsLocked("secret is locked: %s" % self.path) + (self.secret, self.content_type) = session.decode_secret(secret) + @dbus.service.method('org.freedesktop.Secret.Item', sender_keyword='sender') def Delete(self, sender=None): item = self @@ -242,10 +253,11 @@ class SecretItem(dbus.service.Object): if interface_name == 'org.freedesktop.Secret.Item': return { 'Locked': self.get_locked(), - 'Attributes': dbus.Dictionary(self.attributes, signature='ss'), + 'Attributes': dbus.Dictionary(self.attributes, signature='ss', variant_level=1), 'Label': self.label, 'Created': dbus.UInt64(self.created), - 'Modified': dbus.UInt64(self.modified) + 'Modified': dbus.UInt64(self.modified), + 'Schema': self.schema } else: raise InvalidArgs('Unknown %s interface' % interface_name) @@ -271,7 +283,7 @@ class SecretCollection(dbus.service.Object): def __init__(self, service, identifier, label="Collection", locked=False, confirm=False): self.service = service self.identifier = identifier - self.label = label + self.label = label or "Unnamed collection" self.locked = locked self.items = { } self.confirm = confirm @@ -357,7 +369,7 @@ class SecretCollection(dbus.service.Object): 'Label': self.label, 'Created': dbus.UInt64(self.created), 'Modified': dbus.UInt64(self.modified), - 'Items': dbus.Array([dbus.ObjectPath(i.path) for i in self.items.values()], signature='o') + 'Items': dbus.Array([dbus.ObjectPath(i.path) for i in self.items.values()], signature='o', variant_level=1) } else: raise InvalidArgs('Unknown %s interface' % interface_name) @@ -405,7 +417,9 @@ 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", attributes={ "number": "1", "string": "one", "even": "false" }, secret="111") + SecretItem(collection, "item_one", label="Item One", + attributes={ "number": "1", "string": "one", "even": "false" }, + secret="111", schema="org.mock.schema.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") @@ -489,7 +503,7 @@ class SecretService(dbus.service.Object): @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) + label = properties.get("org.freedesktop.Secret.Collection.Label", None) service = self def prompt_callback(): collection = SecretCollection(service, next_identifier('c'), label, locked=False, confirm=True) @@ -530,7 +544,7 @@ class SecretService(dbus.service.Object): def GetAll(self, interface_name): if interface_name == 'org.freedesktop.Secret.Service': return { - 'Collections': dbus.Array([dbus.ObjectPath(c.path) for c in self.collections.values()], signature='o') + 'Collections': dbus.Array([dbus.ObjectPath(c.path) for c in self.collections.values()], signature='o', variant_level=1) } else: raise InvalidArgs('Unknown %s interface' % interface_name) diff --git a/library/tests/test-collection.c b/library/tests/test-collection.c index 13e3c58..001c539 100644 --- a/library/tests/test-collection.c +++ b/library/tests/test-collection.c @@ -97,19 +97,6 @@ test_new_sync (Test *test, egg_assert_not_object (collection); } -static void -test_new_sync_noexist (Test *test, - gconstpointer unused) -{ - const gchar *collection_path = "/org/freedesktop/secrets/collection/nonexistant"; - GError *error = NULL; - GSecretCollection *collection; - - collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error); - g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); - g_assert (collection == NULL); -} - static void test_new_async (Test *test, gconstpointer unused) @@ -134,6 +121,19 @@ test_new_async (Test *test, egg_assert_not_object (collection); } +static void +test_new_sync_noexist (Test *test, + gconstpointer unused) +{ + const gchar *collection_path = "/org/freedesktop/secrets/collection/nonexistant"; + GError *error = NULL; + GSecretCollection *collection; + + collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error); + g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD); + g_assert (collection == NULL); +} + static void test_new_async_noexist (Test *test, gconstpointer unused) @@ -154,6 +154,50 @@ test_new_async_noexist (Test *test, g_object_unref (result); } + +static void +test_create_sync (Test *test, + gconstpointer unused) +{ + GError *error = NULL; + GSecretCollection *collection; + + collection = gsecret_collection_create_sync (test->service, "Train", NULL, NULL, &error); + g_assert_no_error (error); + + g_assert (g_str_has_prefix (g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection)), "/org/freedesktop/secrets/collection")); + g_assert_cmpstr (gsecret_collection_get_label (collection), ==, "Train"); + g_assert (gsecret_collection_get_locked (collection) == FALSE); + + g_object_unref (collection); + egg_assert_not_object (collection); +} + +static void +test_create_async (Test *test, + gconstpointer unused) +{ + GError *error = NULL; + GSecretCollection *collection; + GAsyncResult *result = NULL; + + gsecret_collection_create (test->service, "Train", NULL, NULL, on_async_result, &result); + g_assert (result == NULL); + + egg_test_wait (); + + collection = gsecret_collection_create_finish (result, &error); + g_assert_no_error (error); + g_object_unref (result); + + g_assert (g_str_has_prefix (g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection)), "/org/freedesktop/secrets/collection")); + g_assert_cmpstr (gsecret_collection_get_label (collection), ==, "Train"); + g_assert (gsecret_collection_get_locked (collection) == FALSE); + + g_object_unref (collection); + egg_assert_not_object (collection); +} + static void test_properties (Test *test, gconstpointer unused) @@ -466,9 +510,11 @@ main (int argc, char **argv) g_type_init (); g_test_add ("/collection/new-sync", Test, "mock-service-normal.py", setup, test_new_sync, teardown); - g_test_add ("/collection/new-sync-noexist", Test, "mock-service-normal.py", setup, test_new_sync_noexist, teardown); g_test_add ("/collection/new-async", Test, "mock-service-normal.py", setup, test_new_async, teardown); + g_test_add ("/collection/new-sync-noexist", Test, "mock-service-normal.py", setup, test_new_sync_noexist, teardown); g_test_add ("/collection/new-async-noexist", Test, "mock-service-normal.py", setup, test_new_async_noexist, teardown); + g_test_add ("/collection/create-sync", Test, "mock-service-normal.py", setup, test_create_sync, teardown); + g_test_add ("/collection/create-async", Test, "mock-service-normal.py", setup, test_create_async, teardown); g_test_add ("/collection/properties", Test, "mock-service-normal.py", setup, test_properties, teardown); g_test_add ("/collection/items", Test, "mock-service-normal.py", setup, test_items, teardown); g_test_add ("/collection/items-empty", Test, "mock-service-normal.py", setup, test_items_empty, teardown); diff --git a/library/tests/test-item.c b/library/tests/test-item.c index 49e664f..c5ab05e 100644 --- a/library/tests/test-item.c +++ b/library/tests/test-item.c @@ -15,6 +15,7 @@ #include "config.h" +#include "gsecret-collection.h" #include "gsecret-item.h" #include "gsecret-service.h" #include "gsecret-private.h" @@ -152,6 +153,89 @@ test_new_async_noexist (Test *test, g_object_unref (result); } +static void +test_create_sync (Test *test, + gconstpointer unused) +{ + const gchar *collection_path = "/org/freedesktop/secrets/collection/english"; + GSecretCollection *collection; + GError *error = NULL; + GSecretItem *item; + GHashTable *attributes; + GSecretValue *value; + + collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error); + g_assert_no_error (error); + + 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"); + + value = gsecret_value_new ("Hoohah", -1, "text/plain"); + + item = gsecret_item_create_sync (collection, "org.mock.Schema", "Tunnel", + attributes, value, FALSE, NULL, &error); + g_assert_no_error (error); + + g_hash_table_unref (attributes); + g_object_unref (collection); + gsecret_value_unref (value); + + g_assert (g_str_has_prefix (g_dbus_proxy_get_object_path (G_DBUS_PROXY (item)), collection_path)); + g_assert_cmpstr (gsecret_item_get_label (item), ==, "Tunnel"); + g_assert (gsecret_item_get_locked (item) == FALSE); + g_assert_cmpstr (gsecret_item_get_schema (item), ==, "org.freedesktop.Secret.Generic"); + + g_object_unref (item); + egg_assert_not_object (item); +} + +static void +test_create_async (Test *test, + gconstpointer unused) +{ + const gchar *collection_path = "/org/freedesktop/secrets/collection/english"; + GSecretCollection *collection; + GAsyncResult *result = NULL; + GError *error = NULL; + GSecretItem *item; + GHashTable *attributes; + GSecretValue *value; + + collection = gsecret_collection_new_sync (test->service, collection_path, NULL, &error); + g_assert_no_error (error); + + 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"); + + value = gsecret_value_new ("Hoohah", -1, "text/plain"); + + gsecret_item_create (collection, "org.mock.Schema", "Tunnel", + attributes, value, FALSE, NULL, on_async_result, &result); + g_assert_no_error (error); + + g_hash_table_unref (attributes); + g_object_unref (collection); + gsecret_value_unref (value); + + egg_test_wait (); + + item = gsecret_item_create_finish (result, &error); + g_assert_no_error (error); + g_object_unref (result); + + g_assert (g_str_has_prefix (g_dbus_proxy_get_object_path (G_DBUS_PROXY (item)), collection_path)); + g_assert_cmpstr (gsecret_item_get_label (item), ==, "Tunnel"); + g_assert (gsecret_item_get_locked (item) == FALSE); + g_assert_cmpstr (gsecret_item_get_schema (item), ==, "org.freedesktop.Secret.Generic"); + + g_object_unref (item); + egg_assert_not_object (item); +} + static void test_properties (Test *test, gconstpointer unused) @@ -164,6 +248,7 @@ test_properties (Test *test, guint64 created; guint64 modified; gboolean locked; + gchar *schema; gchar *label; item = gsecret_item_new_sync (test->service, item_path, NULL, &error); @@ -173,6 +258,10 @@ test_properties (Test *test, g_assert_cmpuint (gsecret_item_get_created (item), <=, time (NULL)); g_assert_cmpuint (gsecret_item_get_modified (item), <=, time (NULL)); + schema = gsecret_item_get_schema (item); + g_assert_cmpstr (schema, ==, "org.mock.schema.Store"); + g_free (schema); + label = gsecret_item_get_label (item); g_assert_cmpstr (label, ==, "Item One"); g_free (label); @@ -189,6 +278,7 @@ test_properties (Test *test, "created", &created, "modified", &modified, "label", &label, + "schema", &schema, "attributes", &attributes, "service", &service, NULL); @@ -200,6 +290,9 @@ test_properties (Test *test, g_assert_cmpstr (label, ==, "Item One"); g_free (label); + g_assert_cmpstr (schema, ==, "org.mock.schema.Store"); + g_free (schema); + g_assert_cmpstr (g_hash_table_lookup (attributes, "string"), ==, "one"); g_assert_cmpstr (g_hash_table_lookup (attributes, "number"), ==, "1"); g_assert_cmpstr (g_hash_table_lookup (attributes, "even"), ==, "false"); @@ -484,6 +577,41 @@ test_get_secret_async (Test *test, g_object_unref (item); } +static void +test_set_secret_sync (Test *test, + gconstpointer unused) +{ + const gchar *item_path = "/org/freedesktop/secrets/collection/english/item_one"; + GError *error = NULL; + GSecretItem *item; + gconstpointer data; + GSecretValue *value; + gsize length; + gboolean ret; + + value = gsecret_value_new ("Sinking", -1, "strange/content-type"); + + item = gsecret_item_new_sync (test->service, item_path, NULL, &error); + g_assert_no_error (error); + + ret = gsecret_item_set_secret_sync (item, value, NULL, &error); + g_assert_no_error (error); + g_assert (ret == TRUE); + + gsecret_value_unref (value); + + value = gsecret_item_get_secret_sync (item, NULL, &error); + g_assert_no_error (error); + g_assert (value != NULL); + + data = gsecret_value_get (value, &length); + egg_assert_cmpmem (data, length, ==, "Sinking", 7); + g_assert_cmpstr (gsecret_value_get_content_type (value), ==, "strange/content-type"); + + gsecret_value_unref (value); + g_object_unref (item); +} + static void test_delete_sync (Test *test, gconstpointer unused) @@ -544,9 +672,11 @@ main (int argc, char **argv) g_type_init (); g_test_add ("/item/new-sync", Test, "mock-service-normal.py", setup, test_new_sync, teardown); - g_test_add ("/item/new-sync-noexist", Test, "mock-service-normal.py", setup, test_new_sync_noexist, teardown); g_test_add ("/item/new-async", Test, "mock-service-normal.py", setup, test_new_async, teardown); + g_test_add ("/item/new-sync-noexist", Test, "mock-service-normal.py", setup, test_new_sync_noexist, teardown); g_test_add ("/item/new-async-noexist", Test, "mock-service-normal.py", setup, test_new_async_noexist, teardown); + g_test_add ("/item/create-sync", Test, "mock-service-normal.py", setup, test_create_sync, teardown); + g_test_add ("/item/create-async", Test, "mock-service-normal.py", setup, test_create_async, teardown); g_test_add ("/item/properties", Test, "mock-service-normal.py", setup, test_properties, teardown); g_test_add ("/item/set-label-sync", Test, "mock-service-normal.py", setup, test_set_label_sync, teardown); g_test_add ("/item/set-label-async", Test, "mock-service-normal.py", setup, test_set_label_async, teardown); @@ -556,6 +686,7 @@ main (int argc, char **argv) g_test_add ("/item/set-attributes-prop", Test, "mock-service-normal.py", setup, test_set_attributes_prop, teardown); g_test_add ("/item/get-secret-sync", Test, "mock-service-normal.py", setup, test_get_secret_sync, teardown); g_test_add ("/item/get-secret-async", Test, "mock-service-normal.py", setup, test_get_secret_async, teardown); + g_test_add ("/item/set-secret-sync", Test, "mock-service-normal.py", setup, test_set_secret_sync, teardown); g_test_add ("/item/delete-sync", Test, "mock-service-normal.py", setup, test_delete_sync, teardown); g_test_add ("/item/delete-async", Test, "mock-service-normal.py", setup, test_delete_async, teardown);