[gnome-keyring/dbus-api] [secret-store] Complete implementation of GckSecretObject.



commit e0b6b8ffaf1550628772855322e72d05fd50c90d
Author: Stef Walter <stef memberwebs com>
Date:   Mon Aug 10 00:50:31 2009 +0000

    [secret-store] Complete implementation of GckSecretObject.
    
    Complete missing functions in GckSecretObject, and add tests.
    Add test module functionality, so we can run unit-tests on things
    that require a module/session.

 pkcs11/secret-store/gck-secret-module.c            |   11 +
 pkcs11/secret-store/gck-secret-object.c            |   99 +++++---
 pkcs11/secret-store/gck-secret-object.h            |    5 -
 pkcs11/secret-store/tests/Makefile.am              |    4 +-
 pkcs11/secret-store/tests/test-secret-module.c     |  105 ++++++++
 pkcs11/secret-store/tests/test-secret-module.h     |   43 +++
 .../secret-store/tests/unit-test-secret-object.c   |  269 ++++++++++++++++++++
 7 files changed, 489 insertions(+), 47 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-module.c b/pkcs11/secret-store/gck-secret-module.c
index 17d609f..1090d66 100644
--- a/pkcs11/secret-store/gck-secret-module.c
+++ b/pkcs11/secret-store/gck-secret-module.c
@@ -69,6 +69,8 @@ static const CK_TOKEN_INFO gck_secret_module_token_info = {
 
 G_DEFINE_TYPE (GckSecretModule, gck_secret_module, GCK_TYPE_MODULE);
 
+GckModule*  _gck_secret_store_get_module_for_testing (void);
+
 /* -----------------------------------------------------------------------------
  * ACTUAL PKCS#11 Module Implementation 
  */
@@ -108,10 +110,13 @@ file_load (GckFileTracker *tracker, const gchar *path, GckSecretModule *self)
 
 	if (collection == NULL) {
 		created = TRUE;
+		g_assert ("unimplemented");
+#if 0
 		collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
 		                           "module", self,
 		                           "identifier", basename,
 		                           NULL);
+#endif
 	}
 
 	if (gck_serializable_load (GCK_SERIALIZABLE (collection), NULL, data, n_data)) {
@@ -258,3 +263,9 @@ gck_secret_store_get_functions (void)
 	gck_crypto_initialize ();
 	return gck_secret_module_function_list;
 }
+
+GckModule*
+_gck_secret_store_get_module_for_testing (void)
+{
+	return pkcs11_module;
+}
diff --git a/pkcs11/secret-store/gck-secret-object.c b/pkcs11/secret-store/gck-secret-object.c
index 6aac774..7b29c0c 100644
--- a/pkcs11/secret-store/gck-secret-object.c
+++ b/pkcs11/secret-store/gck-secret-object.c
@@ -53,16 +53,6 @@ G_DEFINE_TYPE (GckSecretObject, gck_secret_object, GCK_TYPE_OBJECT);
  */
 
 static gboolean
-complete_lock (GckTransaction *transaction, GObject *obj, gpointer user_data)
-{
-	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
-	g_return_val_if_fail (GCK_IS_SESSION (user_data), FALSE);
-	gck_secret_object_lock (self, GCK_SESSION (user_data));
-	g_object_unref (user_data);
-	return TRUE;
-}
-
-static gboolean
 complete_set_label (GckTransaction *transaction, GObject *obj, gpointer user_data)
 {
 	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
@@ -125,12 +115,11 @@ gck_secret_object_set_attribute (GckObject *base, GckSession *session,
                                  GckTransaction *transaction, CK_ATTRIBUTE_PTR attr)
 {
 	GckSecretObject *self = GCK_SECRET_OBJECT (base);
-	gboolean locked;
 	gchar *label;
 	CK_RV rv;
 	
 	/* Check that the object is not locked */
-	if (!gck_secret_object_is_locked (self, session)) {
+	if (gck_secret_object_is_locked (self, session)) {
 		gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
 		return;
 	}
@@ -144,21 +133,18 @@ gck_secret_object_set_attribute (GckObject *base, GckSession *session,
 		else
 			begin_set_label (self, transaction, label);
 		return;
-		
-	case CKA_G_LOCKED:
-		rv = gck_attribute_get_bool (attr, &locked);
-		if (rv != CKR_OK)
-			gck_transaction_fail (transaction, rv);
-		else if (!locked)
-			gck_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
-		else /* Not strictly correct, according to transaction semantics... */
-			gck_transaction_add (transaction, self, complete_lock, g_object_ref (session));
-		return;
 	}
 	
 	GCK_OBJECT_CLASS (gck_secret_object_parent_class)->set_attribute (base, session, transaction, attr);
 }
 
+static gboolean
+gck_secret_object_real_is_locked (GckSecretObject *self, GckSession *session)
+{
+	/* Derived classes override us */
+	return FALSE;
+}
+
 static void
 gck_secret_object_init (GckSecretObject *self)
 {
@@ -169,7 +155,10 @@ static GObject*
 gck_secret_object_constructor (GType type, guint n_props, GObjectConstructParam *props) 
 {
 	GckSecretObject *self = GCK_SECRET_OBJECT (G_OBJECT_CLASS (gck_secret_object_parent_class)->constructor(type, n_props, props));
-	g_return_val_if_fail (self, NULL);	
+	g_return_val_if_fail (self, NULL);
+
+	/* Must be created with an identifier */
+	g_return_val_if_fail (self->pv->identifier, NULL);
 
 	return G_OBJECT (self);
 }
@@ -190,14 +179,10 @@ gck_secret_object_set_property (GObject *obj, guint prop_id, const GValue *value
 		g_return_if_fail (self->pv->identifier);
 		break;
 	case PROP_CREATED:
-		g_return_if_fail (!self->pv->created);
-		self->pv->created = g_value_get_long (value);
-		g_return_if_fail (self->pv->created);
+		gck_secret_object_set_created (self, g_value_get_long (value));
 		break;
 	case PROP_MODIFIED:
-		g_return_if_fail (!self->pv->modified);
-		self->pv->modified = g_value_get_long (value);
-		g_return_if_fail (self->pv->modified);
+		gck_secret_object_set_modified (self, g_value_get_long (value));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -271,14 +256,16 @@ gck_secret_object_class_init (GckSecretObjectClass *klass)
 
 	gck_class->get_attribute = gck_secret_object_get_attribute;
 	gck_class->set_attribute = gck_secret_object_set_attribute;
-	
+
+	klass->is_locked = gck_secret_object_real_is_locked;
+
 	g_object_class_install_property (gobject_class, PROP_IDENTIFIER,
 	           g_param_spec_string ("identifier", "Identifier", "Object Identifier", 
-	                                "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	                                NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 	
 	g_object_class_install_property (gobject_class, PROP_LABEL,
 	           g_param_spec_string ("label", "Label", "Object Label", 
-	                                "", G_PARAM_READWRITE));
+	                                "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 	
 	g_object_class_install_property (gobject_class, PROP_CREATED,
 	           g_param_spec_long ("created", "Created", "Object Create Time",
@@ -307,11 +294,32 @@ gck_secret_object_get_label (GckSecretObject *self)
 	return self->pv->label;	
 }
 
+void
+gck_secret_object_set_label (GckSecretObject *self, const gchar *label)
+{
+	g_return_if_fail (GCK_IS_SECRET_OBJECT (self));
+
+	if (self->pv->label == label)
+		return;
+
+	g_free (self->pv->label);
+	self->pv->label = g_strdup (label);
+	g_object_notify (G_OBJECT (self), "label");
+}
+
 glong
 gck_secret_object_get_created (GckSecretObject *self)
 {
 	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), 0);
-	return self->pv->created;		
+	return self->pv->created;
+}
+
+void
+gck_secret_object_set_created (GckSecretObject *self, glong when)
+{
+	g_return_if_fail (GCK_IS_SECRET_OBJECT (self));
+	self->pv->created = when;
+	g_object_notify (G_OBJECT (self), "created");
 }
 
 glong
@@ -321,18 +329,27 @@ gck_secret_object_get_modified (GckSecretObject *self)
 	return self->pv->modified;
 }
 
-gboolean
-gck_secret_object_is_locked (GckSecretObject *self, GckSession *session)
+void
+gck_secret_object_set_modified (GckSecretObject *self, glong when)
 {
-	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), TRUE);
-	g_return_val_if_fail (GCK_SECRET_OBJECT_GET_CLASS (self)->is_locked, TRUE);
-	return GCK_SECRET_OBJECT_GET_CLASS (self)->is_locked (self, session);
+	g_return_if_fail (GCK_IS_SECRET_OBJECT (self));
+	self->pv->modified = when;
+	g_object_notify (G_OBJECT (self), "modified");
 }
 
 void
-gck_secret_object_lock (GckSecretObject *self, GckSession *session)
+gck_secret_object_was_modified (GckSecretObject *self)
 {
+	GTimeVal tv;
 	g_return_if_fail (GCK_IS_SECRET_OBJECT (self));
-	g_return_if_fail (GCK_SECRET_OBJECT_GET_CLASS (self)->lock);
-	GCK_SECRET_OBJECT_GET_CLASS (self)->lock (self, session);	
+	g_get_current_time (&tv);
+	gck_secret_object_set_modified (self, tv.tv_sec);
+}
+
+gboolean
+gck_secret_object_is_locked (GckSecretObject *self, GckSession *session)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), TRUE);
+	g_return_val_if_fail (GCK_SECRET_OBJECT_GET_CLASS (self)->is_locked, TRUE);
+	return GCK_SECRET_OBJECT_GET_CLASS (self)->is_locked (self, session);
 }
diff --git a/pkcs11/secret-store/gck-secret-object.h b/pkcs11/secret-store/gck-secret-object.h
index f8c2262..106961e 100644
--- a/pkcs11/secret-store/gck-secret-object.h
+++ b/pkcs11/secret-store/gck-secret-object.h
@@ -45,8 +45,6 @@ struct _GckSecretObject {
 struct _GckSecretObjectClass {
 	GckObjectClass parent_class;
 	
-	CK_RV (*lock) (GckSecretObject *self, GckSession *session);
-
 	gboolean (*is_locked) (GckSecretObject *self, GckSession *session);
 };
 
@@ -74,7 +72,4 @@ void                 gck_secret_object_was_modified    (GckSecretObject *self);
 gboolean             gck_secret_object_is_locked       (GckSecretObject *self,
                                                         GckSession *session);
 
-void                 gck_secret_object_lock            (GckSecretObject *self,
-                                                        GckSession *session);
-
 #endif /* __GCK_SECRET_OBJECT_H__ */
diff --git a/pkcs11/secret-store/tests/Makefile.am b/pkcs11/secret-store/tests/Makefile.am
index 5ccc28b..18a90e3 100644
--- a/pkcs11/secret-store/tests/Makefile.am
+++ b/pkcs11/secret-store/tests/Makefile.am
@@ -1,6 +1,8 @@
 UNIT_AUTO = \
 	unit-test-secret-compat.c \
-	unit-test-secret-data.c
+	unit-test-secret-data.c \
+	unit-test-secret-object.c \
+	test-secret-module.c test-secret-module.h
 
 UNIT_PROMPT = 
 
diff --git a/pkcs11/secret-store/tests/test-secret-module.c b/pkcs11/secret-store/tests/test-secret-module.c
new file mode 100644
index 0000000..c020fc4
--- /dev/null
+++ b/pkcs11/secret-store/tests/test-secret-module.c
@@ -0,0 +1,105 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-secret-module.c: A test PKCS#11 module implementation
+
+   Copyright (C) 2009 Stefan Walter
+
+   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 <stef memberwebs com>
+*/
+
+#include "config.h"
+#include "test-secret-module.h"
+
+#include "gck/gck-module.h"
+
+#include "secret-store/gck-secret-store.h"
+
+static GMutex *mutex = NULL;
+
+GckModule*  _gck_secret_store_get_module_for_testing (void);
+GMutex* _gck_module_get_scary_mutex_that_you_should_not_touch (GckModule *module);
+
+GckModule*
+test_secret_module_initialize_and_enter (void)
+{
+	CK_FUNCTION_LIST_PTR funcs;
+	GckModule *module;
+	CK_RV rv;
+
+	funcs = gck_secret_store_get_functions ();
+	rv = (funcs->C_Initialize) (NULL);
+	g_return_val_if_fail (rv == CKR_OK, NULL);
+
+	module = _gck_secret_store_get_module_for_testing ();
+	g_return_val_if_fail (module, NULL);
+
+	mutex = _gck_module_get_scary_mutex_that_you_should_not_touch (module);
+	test_secret_module_enter ();
+
+	return module;
+}
+
+void
+test_secret_module_leave_and_finalize (void)
+{
+	CK_FUNCTION_LIST_PTR funcs;
+	CK_RV rv;
+
+	test_secret_module_leave ();
+
+	funcs = gck_secret_store_get_functions ();
+	rv = (funcs->C_Finalize) (NULL);
+	g_return_if_fail (rv == CKR_OK);
+}
+
+void
+test_secret_module_leave (void)
+{
+	g_assert (mutex);
+	g_mutex_unlock (mutex);
+}
+
+void
+test_secret_module_enter (void)
+{
+	g_assert (mutex);
+	g_mutex_lock (mutex);
+}
+
+GckSession*
+test_secret_module_open_session (gboolean writable)
+{
+	CK_ULONG flags = CKF_SERIAL_SESSION;
+	CK_SESSION_HANDLE handle;
+	GckModule *module;
+	GckSession *session;
+	CK_RV rv;
+
+	module = _gck_secret_store_get_module_for_testing ();
+	g_return_val_if_fail (module, NULL);
+
+	if (writable)
+		flags |= CKF_RW_SESSION;
+
+	rv = gck_module_C_OpenSession (module, 1, flags, NULL, NULL, &handle);
+	g_assert (rv == CKR_OK);
+
+	session = gck_module_lookup_session (module, handle);
+	g_assert (session);
+
+	return session;
+}
diff --git a/pkcs11/secret-store/tests/test-secret-module.h b/pkcs11/secret-store/tests/test-secret-module.h
new file mode 100644
index 0000000..60d8b9f
--- /dev/null
+++ b/pkcs11/secret-store/tests/test-secret-module.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-secret-module.h: A test PKCS#11 module implementation
+
+   Copyright (C) 2009 Stefan Walter
+
+   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 <stef memberwebs com>
+*/
+
+#ifndef TEST_SECRET_MODULE_H_
+#define TEST_SECRET_MODULE_H_
+
+#include <glib.h>
+
+#include "gck/gck-types.h"
+
+#include "pkcs11.h"
+
+void                   test_secret_module_leave                    (void);
+
+void                   test_secret_module_enter                    (void);
+
+GckModule*             test_secret_module_initialize_and_enter     (void);
+
+void                   test_secret_module_leave_and_finalize       (void);
+
+GckSession*            test_secret_module_open_session             (gboolean writable);
+
+#endif /* TEST_SECRET_MODULE_H_ */
diff --git a/pkcs11/secret-store/tests/unit-test-secret-object.c b/pkcs11/secret-store/tests/unit-test-secret-object.c
new file mode 100644
index 0000000..13afa30
--- /dev/null
+++ b/pkcs11/secret-store/tests/unit-test-secret-object.c
@@ -0,0 +1,269 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-secret-collection.c: Test the collection keyring
+
+   Copyright (C) 2009 Stefan Walter
+
+   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 <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+#include "test-secret-module.h"
+
+#include "gck-secret-object.h"
+
+#include "gck/gck-transaction.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static GckModule *module = NULL;
+static GckSession *session = NULL;
+static GckSecretObject *object = NULL;
+
+DEFINE_SETUP(secret_object)
+{
+	module = test_secret_module_initialize_and_enter ();
+	session = test_secret_module_open_session (TRUE);
+
+	object = g_object_new (GCK_TYPE_SECRET_OBJECT,
+	                       "module", module,
+	                       "identifier", "my-identifier",
+	                       NULL);
+
+	g_assert (GCK_IS_SECRET_OBJECT (object));
+}
+
+DEFINE_TEARDOWN(secret_object)
+{
+	g_object_unref (object);
+	object = NULL;
+
+	test_secret_module_leave_and_finalize ();
+	module = NULL;
+	session = NULL;
+}
+
+DEFINE_TEST(secret_object_is_locked)
+{
+	/* Plain GckSecretObject is never locked */
+	g_assert (!gck_secret_object_is_locked (object, session));
+}
+
+DEFINE_TEST(secret_object_identifier_prop)
+{
+	const gchar *identifier;
+	identifier = gck_secret_object_get_identifier (object);
+	g_assert_cmpstr (identifier, ==, "my-identifier");
+}
+
+static void
+was_notified (GObject *obj, GParamSpec *pspec, gpointer user_data)
+{
+	gboolean* notified = user_data;
+	g_assert (GCK_SECRET_OBJECT (obj) == object);
+	g_assert (user_data);
+	*notified = TRUE;
+}
+
+DEFINE_TEST(secret_object_created_prop)
+{
+	glong created;
+
+	/* Monitor for changes */
+	gboolean notified = FALSE;
+	g_signal_connect (object, "notify::created", G_CALLBACK (was_notified), &notified);
+
+	/* Default value */
+	created = gck_secret_object_get_created (object);
+	g_assert (created == 0);
+
+	/* Set a new value */
+	gck_secret_object_set_created (object, 1247930171);
+	g_assert (notified);
+	created = gck_secret_object_get_created (object);
+	g_assert (created == 1247930171);
+}
+
+DEFINE_TEST(secret_object_modified_prop)
+{
+	glong modified;
+
+	/* Monitor for changes */
+	gboolean notified = FALSE;
+	g_signal_connect (object, "notify::modified", G_CALLBACK (was_notified), &notified);
+
+	/* Default value */
+	modified = gck_secret_object_get_modified (object);
+	g_assert (modified == 0);
+
+	/* Set a new value */
+	gck_secret_object_set_modified (object, 1247930171);
+	g_assert (notified);
+	modified = gck_secret_object_get_modified (object);
+	g_assert (modified == 1247930171);
+}
+
+DEFINE_TEST(secret_object_was_modified)
+{
+	GTimeVal tv;
+	g_get_current_time (&tv);
+	gck_secret_object_was_modified (object);
+	g_assert (tv.tv_sec == gck_secret_object_get_modified (object));
+}
+
+DEFINE_TEST(secret_object_label_prop)
+{
+	const gchar *label;
+
+	/* Monitor for changes */
+	gboolean notified = FALSE;
+	g_signal_connect (object, "notify::label", G_CALLBACK (was_notified), &notified);
+
+	/* Default value */
+	label = gck_secret_object_get_label (object);
+	g_assert_cmpstr (label, ==, "");
+
+	/* Set a new value */
+	gck_secret_object_set_label (object, "hello");
+	g_assert (notified);
+	label = gck_secret_object_get_label (object);
+	g_assert_cmpstr (label, ==, "hello");
+}
+
+DEFINE_TEST(secret_object_identifier_get_attr)
+{
+	gchar buffer[32];
+	CK_ATTRIBUTE attr = { CKA_ID, buffer, 32 };
+	CK_RV rv;
+
+	rv = gck_object_get_attribute (GCK_OBJECT (object), session, &attr);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 13);
+	g_assert (memcmp (buffer, "my-identifier", 13) == 0);
+}
+
+DEFINE_TEST(secret_object_label_get_attr)
+{
+	gchar buffer[32];
+	CK_ATTRIBUTE attr = { CKA_LABEL, buffer, 32 };
+	CK_RV rv;
+
+	gck_secret_object_set_label (object, "hello");
+	rv = gck_object_get_attribute (GCK_OBJECT (object), session, &attr);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 5);
+	g_assert (memcmp (buffer, "hello", 5) == 0);
+}
+
+DEFINE_TEST(secret_object_label_set_attr)
+{
+	CK_ATTRIBUTE attr = { CKA_LABEL, "hello", 5 };
+	GckTransaction *transaction = gck_transaction_new ();
+
+	/* Monitor for changes */
+	gboolean notified = FALSE;
+	g_signal_connect (object, "notify::label", G_CALLBACK (was_notified), &notified);
+
+	gck_object_set_attribute (GCK_OBJECT (object), session, transaction, &attr);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (!notified); /* Not notified yet */
+
+	g_assert_cmpstr (gck_secret_object_get_label (object), ==, "hello");
+
+	gck_transaction_complete (transaction);
+	g_assert_cmpstr (gck_secret_object_get_label (object), ==, "hello");
+	g_assert (notified); /* Notified after transaction complete */
+
+	g_object_unref (transaction);
+}
+
+DEFINE_TEST(secret_object_label_set_attr_fail)
+{
+	CK_ATTRIBUTE attr = { CKA_LABEL, "hello", 5 };
+	GckTransaction *transaction = gck_transaction_new ();
+	gboolean notified = FALSE;
+
+	/* Set an old value */
+	gck_secret_object_set_label (object, "old");
+
+	/* Monitor for changes */
+	g_signal_connect (object, "notify::label", G_CALLBACK (was_notified), &notified);
+
+	/* Set a new value */
+	gck_object_set_attribute (GCK_OBJECT (object), session, transaction, &attr);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (!notified); /* Not notified yet */
+
+	/* Temporarily has new value */
+	g_assert_cmpstr (gck_secret_object_get_label (object), ==, "hello");
+
+	/* Fail and complete transaction */
+	gck_transaction_fail (transaction, CKR_CANCEL);
+	gck_transaction_complete (transaction);
+
+	/* Back to old value */
+	g_assert_cmpstr (gck_secret_object_get_label (object), ==, "old");
+	g_assert (!notified); /* Should never have notified */
+
+	g_object_unref (transaction);
+}
+
+DEFINE_TEST(secret_object_modified_get_attr)
+{
+	gchar buffer[32];
+	CK_ATTRIBUTE attr = { CKA_G_MODIFIED, buffer, 32 };
+	CK_RV rv;
+
+	gck_secret_object_set_modified (object, 1247930171);
+	rv = gck_object_get_attribute (GCK_OBJECT (object), session, &attr);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 16);
+	g_assert (memcmp (buffer, "2009071815161100", 16) == 0);
+}
+
+DEFINE_TEST(secret_object_created_get_attr)
+{
+	gchar buffer[32];
+	CK_ATTRIBUTE attr = { CKA_G_CREATED, buffer, 32 };
+	CK_RV rv;
+
+	gck_secret_object_set_created (object, 1247930171);
+	rv = gck_object_get_attribute (GCK_OBJECT (object), session, &attr);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 16);
+	g_assert (memcmp (buffer, "2009071815161100", 16) == 0);
+}
+
+DEFINE_TEST(secret_object_locked_get_attr)
+{
+	gchar buffer[32];
+	CK_ATTRIBUTE attr = { CKA_G_LOCKED, buffer, 32 };
+	CK_RV rv;
+
+	rv = gck_object_get_attribute (GCK_OBJECT (object), session, &attr);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 1);
+	g_assert (memcmp (buffer, "\0", 1) == 0);
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]