Complete javascript testing of password functionality

* And fix bugs, nullable collection_path
This commit is contained in:
Stef Walter 2012-03-11 13:35:43 +01:00
parent e202ac9d19
commit 2bc2140d43
9 changed files with 266 additions and 26 deletions

2
.gitignore vendored
View File

@ -65,4 +65,6 @@ stamp*
/library/secret-enum-types.[ch] /library/secret-enum-types.[ch]
/library/tests/test-* /library/tests/test-*
!/library/tests/test-*.c !/library/tests/test-*.c
!/library/tests/test-*.js
!/library/tests/test-*.py

View File

@ -1659,7 +1659,7 @@ secret_service_unlock_sync (SecretService *self,
* secret_service_store: * secret_service_store:
* @self: the secret service * @self: the secret service
* @schema: the schema to for attributes * @schema: the schema to for attributes
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @value: the secret value * @value: the secret value
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -1677,6 +1677,10 @@ secret_service_unlock_sync (SecretService *self,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is not specified, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method will return immediately and complete asynchronously. * This method will return immediately and complete asynchronously.
*/ */
void void
@ -1695,7 +1699,6 @@ secret_service_store (SecretService *self,
g_return_if_fail (SECRET_IS_SERVICE (self)); g_return_if_fail (SECRET_IS_SERVICE (self));
g_return_if_fail (schema != NULL); g_return_if_fail (schema != NULL);
g_return_if_fail (collection_path != NULL);
g_return_if_fail (label != NULL); g_return_if_fail (label != NULL);
g_return_if_fail (value != NULL); g_return_if_fail (value != NULL);
@ -1704,7 +1707,7 @@ secret_service_store (SecretService *self,
va_end (va); va_end (va);
secret_service_storev (self, schema, attributes, collection_path, secret_service_storev (self, schema, attributes, collection_path,
label, value, cancellable, callback, user_data); label, value, cancellable, callback, user_data);
g_hash_table_unref (attributes); g_hash_table_unref (attributes);
} }
@ -1714,7 +1717,7 @@ secret_service_store (SecretService *self,
* @self: the secret service * @self: the secret service
* @schema: the schema to for attributes * @schema: the schema to for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values * @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @value: the secret value * @value: the secret value
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -1728,6 +1731,10 @@ secret_service_store (SecretService *self,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is not specified, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method will return immediately and complete asynchronously. * This method will return immediately and complete asynchronously.
*/ */
void void
@ -1747,7 +1754,6 @@ secret_service_storev (SecretService *self,
g_return_if_fail (SECRET_IS_SERVICE (self)); g_return_if_fail (SECRET_IS_SERVICE (self));
g_return_if_fail (schema != NULL); g_return_if_fail (schema != NULL);
g_return_if_fail (attributes != NULL); g_return_if_fail (attributes != NULL);
g_return_if_fail (collection_path != NULL);
g_return_if_fail (label != NULL); g_return_if_fail (label != NULL);
g_return_if_fail (value != NULL); g_return_if_fail (value != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
@ -1775,7 +1781,7 @@ secret_service_storev (SecretService *self,
g_variant_ref_sink (propval)); g_variant_ref_sink (propval));
secret_service_create_item_path (self, collection_path, properties, value, secret_service_create_item_path (self, collection_path, properties, value,
TRUE, cancellable, callback, user_data); TRUE, cancellable, callback, user_data);
g_hash_table_unref (properties); g_hash_table_unref (properties);
} }
@ -1810,7 +1816,7 @@ secret_service_store_finish (SecretService *self,
* secret_service_store_sync: * secret_service_store_sync:
* @self: the secret service * @self: the secret service
* @schema: the schema to for attributes * @schema: the schema to for attributes
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @value: the secret value * @value: the secret value
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -1827,6 +1833,10 @@ secret_service_store_finish (SecretService *self,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method may block indefinitely and should not be used in user interface * This method may block indefinitely and should not be used in user interface
* threads. * threads.
* *
@ -1848,7 +1858,6 @@ secret_service_store_sync (SecretService *self,
g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE); g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
g_return_val_if_fail (schema != NULL, FALSE); g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (collection_path != NULL, FALSE);
g_return_val_if_fail (label != NULL, FALSE); g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
@ -1859,7 +1868,7 @@ secret_service_store_sync (SecretService *self,
va_end (va); va_end (va);
ret = secret_service_storev_sync (self, schema, attributes, collection_path, ret = secret_service_storev_sync (self, schema, attributes, collection_path,
label, value, cancellable, error); label, value, cancellable, error);
g_hash_table_unref (attributes); g_hash_table_unref (attributes);
@ -1871,7 +1880,7 @@ secret_service_store_sync (SecretService *self,
* @self: the secret service * @self: the secret service
* @schema: the schema to for attributes * @schema: the schema to for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values * @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @value: the secret value * @value: the secret value
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -1884,6 +1893,10 @@ secret_service_store_sync (SecretService *self,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method may block indefinitely and should not be used in user interface * This method may block indefinitely and should not be used in user interface
* threads. * threads.
* *
@ -1905,7 +1918,6 @@ secret_service_storev_sync (SecretService *self,
g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE); g_return_val_if_fail (SECRET_IS_SERVICE (self), FALSE);
g_return_val_if_fail (schema != NULL, FALSE); g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (attributes != NULL, FALSE); g_return_val_if_fail (attributes != NULL, FALSE);
g_return_val_if_fail (collection_path != NULL, FALSE);
g_return_val_if_fail (label != NULL, FALSE); g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
@ -1919,7 +1931,7 @@ secret_service_storev_sync (SecretService *self,
g_main_context_push_thread_default (sync->context); g_main_context_push_thread_default (sync->context);
secret_service_storev (self, schema, attributes, collection_path, secret_service_storev (self, schema, attributes, collection_path,
label, value, cancellable, _secret_sync_on_result, sync); label, value, cancellable, _secret_sync_on_result, sync);
g_main_loop_run (sync->loop); g_main_loop_run (sync->loop);
@ -3137,7 +3149,7 @@ on_create_item_session (GObject *source,
/** /**
* secret_service_create_item_path: * secret_service_create_item_path:
* @self: a secret service object * @self: a secret service object
* @collection_path: dbus path to collection in which to create item * @collection_path: (allow-none): dbus path to collection in which to create item
* @properties: hash table of properties for the new collection * @properties: hash table of properties for the new collection
* @value: the secret value to store in the item * @value: the secret value to store in the item
* @replace: whether to replace an item with the matching attributes * @replace: whether to replace an item with the matching attributes
@ -3159,6 +3171,10 @@ on_create_item_session (GObject *source,
* <literal>org.freedesktop.Secret.Item.Label</literal>. The values * <literal>org.freedesktop.Secret.Item.Label</literal>. The values
* in the hash table should be #GVariant values of the properties. * in the hash table should be #GVariant values of the properties.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method will return immediately and complete asynchronously. The secret * This method will return immediately and complete asynchronously. The secret
* service may prompt the user. secret_service_prompt() will be used to handle * service may prompt the user. secret_service_prompt() will be used to handle
* any prompts that are required. * any prompts that are required.
@ -3181,6 +3197,9 @@ secret_service_create_item_path (SecretService *self,
g_return_if_fail (value != NULL); g_return_if_fail (value != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
if (collection_path == NULL)
collection_path = SECRET_COLLECTION_DEFAULT;
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
secret_service_create_item_path); secret_service_create_item_path);
closure = g_slice_new0 (ItemClosure); closure = g_slice_new0 (ItemClosure);
@ -3238,7 +3257,7 @@ secret_service_create_item_path_finish (SecretService *self,
/** /**
* secret_service_create_item_path_sync: * secret_service_create_item_path_sync:
* @self: a secret service object * @self: a secret service object
* @collection_path: dbus path to collection in which to create item * @collection_path: (allow-none): dbus path to collection in which to create item
* @properties: hash table of properties for the new collection * @properties: hash table of properties for the new collection
* @value: the secret value to store in the item * @value: the secret value to store in the item
* @replace: whether to replace an item with the matching attributes * @replace: whether to replace an item with the matching attributes

View File

@ -110,7 +110,7 @@ on_store_connected (GObject *source,
/** /**
* secret_password_store: * secret_password_store:
* @schema: the schema for attributes * @schema: the schema for attributes
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @password: the null-terminated password to store * @password: the null-terminated password to store
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -128,6 +128,10 @@ on_store_connected (GObject *source,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method will return immediately and complete asynchronously. * This method will return immediately and complete asynchronously.
*/ */
void void
@ -144,7 +148,6 @@ secret_password_store (const SecretSchema *schema,
va_list va; va_list va;
g_return_if_fail (schema != NULL); g_return_if_fail (schema != NULL);
g_return_if_fail (collection_path != NULL);
g_return_if_fail (label != NULL); g_return_if_fail (label != NULL);
g_return_if_fail (password != NULL); g_return_if_fail (password != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
@ -163,7 +166,7 @@ secret_password_store (const SecretSchema *schema,
* secret_password_storev: * secret_password_storev:
* @schema: the schema for attributes * @schema: the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values * @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @password: the null-terminated password to store * @password: the null-terminated password to store
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -177,6 +180,10 @@ secret_password_store (const SecretSchema *schema,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method will return immediately and complete asynchronously. * This method will return immediately and complete asynchronously.
* *
* Rename to: secret_password_store * Rename to: secret_password_store
@ -195,7 +202,6 @@ secret_password_storev (const SecretSchema *schema,
StoreClosure *closure; StoreClosure *closure;
g_return_if_fail (schema != NULL); g_return_if_fail (schema != NULL);
g_return_if_fail (collection_path != NULL);
g_return_if_fail (label != NULL); g_return_if_fail (label != NULL);
g_return_if_fail (password != NULL); g_return_if_fail (password != NULL);
g_return_if_fail (attributes != NULL); g_return_if_fail (attributes != NULL);
@ -254,7 +260,7 @@ secret_password_store_finish (GAsyncResult *result,
/** /**
* secret_password_store_sync: * secret_password_store_sync:
* @schema: the schema for attributes * @schema: the schema for attributes
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @password: the null-terminated password to store * @password: the null-terminated password to store
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -271,6 +277,10 @@ secret_password_store_finish (GAsyncResult *result,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method may block indefinitely and should not be used in user interface * This method may block indefinitely and should not be used in user interface
* threads. * threads.
* *
@ -310,7 +320,7 @@ secret_password_store_sync (const SecretSchema *schema,
* secret_password_storev_sync: * secret_password_storev_sync:
* @schema: the schema for attributes * @schema: the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values * @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection_path: the dbus path to the collection where to store the secret * @collection_path: (allow-none): the dbus path to the collection where to store the secret
* @label: label for the secret * @label: label for the secret
* @password: the null-terminated password to store * @password: the null-terminated password to store
* @cancellable: optional cancellation object * @cancellable: optional cancellation object
@ -323,6 +333,10 @@ secret_password_store_sync (const SecretSchema *schema,
* If the attributes match a secret item already stored in the collection, then * If the attributes match a secret item already stored in the collection, then
* the item will be updated with these new values. * the item will be updated with these new values.
* *
* If @collection_path is %NULL, then the default collection will be
* used. Use #SECRET_COLLECTION_SESSION to store the password in the session
* collection, which doesn't get stored across login sessions.
*
* This method may block indefinitely and should not be used in user interface * This method may block indefinitely and should not be used in user interface
* threads. * threads.
* *
@ -343,7 +357,6 @@ secret_password_storev_sync (const SecretSchema *schema,
gboolean ret; gboolean ret;
g_return_val_if_fail (schema != NULL, FALSE); g_return_val_if_fail (schema != NULL, FALSE);
g_return_val_if_fail (collection_path != NULL, FALSE);
g_return_val_if_fail (label != NULL, FALSE); g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (password != NULL, FALSE); g_return_val_if_fail (password != NULL, FALSE);
g_return_val_if_fail (attributes != NULL, FALSE); g_return_val_if_fail (attributes != NULL, FALSE);

View File

@ -35,6 +35,10 @@ typedef struct _SecretPrompt SecretPrompt;
typedef struct _SecretService SecretService; typedef struct _SecretService SecretService;
typedef struct _SecretValue SecretValue; typedef struct _SecretValue SecretValue;
#define SECRET_COLLECTION_DEFAULT "/org/freedesktop/secrets/aliases/default"
#define SECRET_COLLECTION_SESSION "/org/freedesktop/secrets/aliases/session"
G_END_DECLS G_END_DECLS
#endif /* __G_SERVICE_H___ */ #endif /* __G_SERVICE_H___ */

View File

@ -56,12 +56,22 @@ EXTRA_DIST = \
mock-service-prompt.py \ mock-service-prompt.py \
$(NULL) $(NULL)
test: $(TEST_PROGS) JS_TESTS = \
gtester --verbose -m $(TEST_MODE) --g-fatal-warnings $(TEST_PROGS) test-lookup-password.js \
test-remove-password.js \
test-store-password.js
test-javascript: JS_ENV = \
LD_LIBRARY_PATH=$(builddir)/.libs GI_TYPELIB_PATH=$(builddir)/..:$(builddir) \ LD_LIBRARY_PATH=$(builddir)/.libs \
gjs test-lookup-password.js GI_TYPELIB_PATH=$(builddir)/..:$(builddir)
test: test-c test-js
test-c: $(TEST_PROGS)
@gtester --verbose -m $(TEST_MODE) --g-fatal-warnings $(TEST_PROGS)
test-js:
@for js in $(JS_TESTS); do echo "TEST: $$js"; $(JS_ENV) gjs $$js; done
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# INTROSPECTION # INTROSPECTION

View File

@ -0,0 +1,14 @@
const Mock = imports.gi.MockService;
const Secret = imports.gi.Secret;
Mock.start("mock-service-normal.py");
var schema = new Secret.Schema.new("org.test",
Secret.SchemaFlags.NONE,
{ "blah": Secret.SchemaAttributeType.STRING });
log(schema.identifier);
log(schema.flags);
/* log(schema.attributes); */
Mock.stop();

View File

@ -0,0 +1,52 @@
const Mock = imports.gi.MockService;
const Secret = imports.gi.Secret;
const GLib = imports.gi.GLib;
const JsUnit = imports.jsUnit;
const assertEquals = JsUnit.assertEquals;
const assertRaises = JsUnit.assertRaises;
const assertTrue = JsUnit.assertTrue;
Mock.start("mock-service-normal.py");
const STORE_SCHEMA = new Secret.Schema.new("org.mock.type.Store",
Secret.SchemaFlags.NONE,
{
"number": Secret.SchemaAttributeType.INTEGER,
"string": Secret.SchemaAttributeType.STRING,
"even": Secret.SchemaAttributeType.BOOLEAN,
}
);
/* Synchronous */
var password = Secret.password_lookup_sync (STORE_SCHEMA, { "number": "1", "even": "false" }, null);
assertEquals("111", password);
var password = Secret.password_lookup_sync (STORE_SCHEMA, { "number": "5", "even": "true" }, null);
assertEquals(null, password);
/* Asynchronous */
var loop = new GLib.MainLoop.new(null, false);
Secret.password_lookup (STORE_SCHEMA, { "number": "2", "string": "two" },
null, function(source, result) {
loop.quit();
var password = Secret.password_lookup_finish(result);
assertEquals("222", password);
});
loop.run();
Secret.password_lookup (STORE_SCHEMA, { "number": "7", "string": "five" },
null, function(source, result) {
loop.quit();
var password = Secret.password_lookup_finish(result);
assertEquals(null, password);
});
loop.run();
Mock.stop();

View File

@ -0,0 +1,68 @@
const Mock = imports.gi.MockService;
const Secret = imports.gi.Secret;
const GLib = imports.gi.GLib;
const JsUnit = imports.jsUnit;
const assertEquals = JsUnit.assertEquals;
const assertRaises = JsUnit.assertRaises;
const assertTrue = JsUnit.assertTrue;
Mock.start("mock-service-normal.py");
const STORE_SCHEMA = new Secret.Schema.new("org.mock.type.Store",
Secret.SchemaFlags.NONE,
{
"number": Secret.SchemaAttributeType.INTEGER,
"string": Secret.SchemaAttributeType.STRING,
"even": Secret.SchemaAttributeType.BOOLEAN,
}
);
/* Synchronous */
var attributes = { "number": "1", "string": "one", "even": "false" };
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals("111", password);
var deleted = Secret.password_remove_sync (STORE_SCHEMA, attributes, null);
assertEquals(true, deleted);
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals(null, password);
var deleted = Secret.password_remove_sync (STORE_SCHEMA, attributes, null);
assertEquals(false, deleted);
/* Asynchronous */
var attributes = { "number": "2", "string": "two", "even": "true" };
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals("222", password);
var loop = new GLib.MainLoop.new(null, false);
Secret.password_remove (STORE_SCHEMA, attributes,
null, function(source, result) {
loop.quit();
var deleted = Secret.password_remove_finish(result);
assertEquals(true, deleted);
});
loop.run();
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals(null, password);
Secret.password_remove (STORE_SCHEMA, attributes,
null, function(source, result) {
loop.quit();
var deleted = Secret.password_remove_finish(result);
assertEquals(false, deleted);
});
loop.run();
Mock.stop();

View File

@ -0,0 +1,58 @@
const Mock = imports.gi.MockService;
const Secret = imports.gi.Secret;
const GLib = imports.gi.GLib;
const JsUnit = imports.jsUnit;
const assertEquals = JsUnit.assertEquals;
const assertRaises = JsUnit.assertRaises;
const assertTrue = JsUnit.assertTrue;
Mock.start("mock-service-normal.py");
const STORE_SCHEMA = new Secret.Schema.new("org.mock.type.Store",
Secret.SchemaFlags.NONE,
{
"number": Secret.SchemaAttributeType.INTEGER,
"string": Secret.SchemaAttributeType.STRING,
"even": Secret.SchemaAttributeType.BOOLEAN,
}
);
/* Synchronous */
var attributes = { "number": "9", "string": "nine", "even": "false" };
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals(null, password);
var stored = Secret.password_store_sync (STORE_SCHEMA, attributes, Secret.COLLECTION_DEFAULT,
"The number nine", "999", null);
assertEquals(true, stored);
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals("999", password);
/* Asynchronous */
var attributes = { "number": "888", "string": "eight", "even": "true" };
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals(null, password);
var loop = new GLib.MainLoop.new(null, false);
Secret.password_store (STORE_SCHEMA, attributes, null, "The number eight", "888",
null, function(source, result) {
loop.quit();
var stored = Secret.password_store_finish(result);
assertEquals(true, stored);
});
loop.run();
var password = Secret.password_lookup_sync (STORE_SCHEMA, attributes, null);
assertEquals("888", password);
Mock.stop();