[gnome-keyring/dbus-api] [secret-store] Implement tests for gck_secret_fields_().



commit 2023490dc208bc6eb2ab98e3f094550c5b336aad
Author: Stef Walter <stef memberwebs com>
Date:   Fri Aug 14 03:41:27 2009 +0000

    [secret-store] Implement tests for gck_secret_fields_().
    
    Implement tests for fields code, and fix bugs found.

 pkcs11/secret-store/gck-secret-fields.c            |   87 +++--
 pkcs11/secret-store/tests/Makefile.am              |    1 +
 .../secret-store/tests/unit-test-secret-fields.c   |  383 ++++++++++++++++++++
 3 files changed, 435 insertions(+), 36 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-fields.c b/pkcs11/secret-store/gck-secret-fields.c
index f87ec54..6d27ba6 100644
--- a/pkcs11/secret-store/gck-secret-fields.c
+++ b/pkcs11/secret-store/gck-secret-fields.c
@@ -125,11 +125,16 @@ compat_hash_value_as_string (const gchar *value)
 GType
 gck_secret_fields_boxed_type (void)
 {
+	static volatile gsize type_inited = 0;
 	static GType type = 0;
-	if (!type) 
+
+	if (g_once_init_enter (&type_inited)) {
 		type = g_boxed_type_register_static ("GHashTable_Fields", 
 		                                     (GBoxedCopyFunc)g_hash_table_ref,
 		                                     (GBoxedFreeFunc)g_hash_table_unref);
+		g_once_init_leave (&type_inited, 1);
+	}
+
 	return type;
 }
 
@@ -177,9 +182,11 @@ gck_secret_fields_parse (CK_ATTRIBUTE_PTR attr, GHashTable **fields)
 		value = ++ptr;
 		ptr = memchr (ptr, 0, last - ptr);
 		
-		/* The last value */
-		if (ptr == NULL)
-			ptr = last;
+		/* Missing null terminator on value */
+		if (ptr == NULL) {
+			g_hash_table_unref (result);
+			return CKR_ATTRIBUTE_VALUE_INVALID;
+		}
 		
 		n_value = ptr - value;
 		++ptr;
@@ -268,6 +275,7 @@ gck_secret_fields_match (GHashTable *haystack, GHashTable *needle)
 			match = string_ptr_equal (hay, value);
 			if (!match)
 				return FALSE;
+			continue;
 		}
 
 		/* Try to find a hashed value? */
@@ -275,31 +283,31 @@ gck_secret_fields_match (GHashTable *haystack, GHashTable *needle)
 		match = g_hash_table_lookup_extended (haystack, other_key, NULL, (gpointer*)&hay);
 		g_free (other_key);
 
-		if (match) {
-
-			/*
-			 * Now since the old keyring code would hash in two different
-			 * ways depending on whether it was a uint32 or string,
-			 * we need to do the same here.
-			 */
-
-			other_key = make_compat_uint32_name (key);
-			if (g_hash_table_lookup (haystack, other_key)) {
-				hashed = NULL;
-				if (compat_hash_value_as_uint32 (value, &number))
-					hashed = format_uint32 (number);
-			} else {
-				hashed = compat_hash_value_as_string (value);
-			}
-			g_free (other_key);
+		if (!match)
+			return FALSE;
+
+		/*
+		 * Now since the old keyring code would hash in two different
+		 * ways depending on whether it was a uint32 or string,
+		 * we need to do the same here.
+		 */
+
+		other_key = make_compat_uint32_name (key);
+		if (g_hash_table_lookup (haystack, other_key)) {
+			hashed = NULL;
+			if (compat_hash_value_as_uint32 (value, &number))
+				hashed = format_uint32 (number);
+		} else {
+			hashed = compat_hash_value_as_string (value);
+		}
+		g_free (other_key);
 
-			/* Does the incoming hashed value match our hashed value? */
-			match = string_ptr_equal (hay, hashed);
-			g_free (hashed);
+		/* Does the incoming hashed value match our hashed value? */
+		match = string_ptr_equal (hay, hashed);
+		g_free (hashed);
 
-			if (!match)
-				return FALSE;
-		}
+		if (!match)
+			return FALSE;
 	}
 	
 	return TRUE;
@@ -364,7 +372,7 @@ gck_secret_fields_add_compat_uint32 (GHashTable *fields, const gchar *name,
 	g_return_if_fail (name);
 	g_return_if_fail (!is_compat_name (name));
 	g_hash_table_replace (fields, g_strdup (name), format_uint32 (value));
-	g_hash_table_replace (fields, make_compat_uint32_name (name), g_strdup (name));
+	g_hash_table_replace (fields, make_compat_uint32_name (name), g_strdup (""));
 }
 
 gboolean
@@ -417,7 +425,7 @@ gck_secret_fields_get_compat_hashed_string (GHashTable *fields, const gchar *nam
 		*value = compat_hash_value_as_string (val);
 		return TRUE;
 	}
-	
+
 	/* See if we already have it hashed */
 	other_key = make_compat_hashed_name (name);
 	ret = g_hash_table_lookup_extended (fields, other_key, NULL, (gpointer*)&val);
@@ -446,24 +454,31 @@ gck_secret_fields_get_compat_hashed_uint32 (GHashTable *fields, const gchar *nam
 	const gchar *val;
 	gchar *other_key;
 	gboolean ret;
-	
+
 	g_return_val_if_fail (fields, FALSE);
 	g_return_val_if_fail (name, FALSE);
 	g_return_val_if_fail (value, FALSE);
 	g_return_val_if_fail (!is_compat_name (name), FALSE);
-	
+
 	/* Even though this is more expensive, it's far more common */
+
+	/* Check if it's a uint32 */
 	other_key = make_compat_uint32_name (name);
-	ret = g_hash_table_lookup_extended (fields, other_key, NULL, (gpointer*)&val);
+	ret = g_hash_table_lookup_extended (fields, other_key, NULL, NULL);
 	g_free (other_key);
-	if (ret && compat_hash_value_as_uint32 (val, value))
-		return TRUE;
-	
+
+	/* It is a uint32 */
+	if (ret == TRUE) {
+		val = g_hash_table_lookup (fields, name);
+		if (val && compat_hash_value_as_uint32 (val, value))
+			return TRUE;
+	}
+
 	/* See if we already have it hashed */
 	other_key = make_compat_hashed_name (name);
 	ret = g_hash_table_lookup_extended (fields, other_key, NULL, (gpointer*)&val);
 	g_free (other_key);
 	if (ret)
 		ret = parse_uint32 (val, value);
-	return ret;	
+	return ret;
 }
diff --git a/pkcs11/secret-store/tests/Makefile.am b/pkcs11/secret-store/tests/Makefile.am
index bec3662..4a491bf 100644
--- a/pkcs11/secret-store/tests/Makefile.am
+++ b/pkcs11/secret-store/tests/Makefile.am
@@ -2,6 +2,7 @@ UNIT_AUTO = \
 	unit-test-secret-collection.c \
 	unit-test-secret-compat.c \
 	unit-test-secret-data.c \
+	unit-test-secret-fields.c \
 	unit-test-secret-item.c \
 	unit-test-secret-object.c \
 	test-secret-module.c test-secret-module.h
diff --git a/pkcs11/secret-store/tests/unit-test-secret-fields.c b/pkcs11/secret-store/tests/unit-test-secret-fields.c
new file mode 100644
index 0000000..9952370
--- /dev/null
+++ b/pkcs11/secret-store/tests/unit-test-secret-fields.c
@@ -0,0 +1,383 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-secret-fields.c: Test secret fields
+
+   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 "gck-secret-fields.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+DEFINE_TEST(fields_new)
+{
+	GHashTable *fields = gck_secret_fields_new ();
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_boxed)
+{
+	GType boxed = gck_secret_fields_boxed_type ();
+	GType check = gck_secret_fields_boxed_type ();
+	g_assert (boxed == check);
+}
+
+DEFINE_TEST(fields_add_get_values)
+{
+	GHashTable *fields = gck_secret_fields_new ();
+	const gchar *value;
+
+	gck_secret_fields_add (fields, "one", "value1");
+	gck_secret_fields_add (fields, "two", "value2");
+
+	value = gck_secret_fields_get (fields, "one");
+	g_assert_cmpstr (value, ==, "value1");
+
+	value = gck_secret_fields_get (fields, "two");
+	g_assert_cmpstr (value, ==, "value2");
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_parse)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, "one\0value1\0two\0value2\0three\0value3\0", 35 };
+	GHashTable *fields;
+	const gchar *value;
+	CK_RV rv;
+
+	rv = gck_secret_fields_parse (&attr, &fields);
+	g_assert (rv == CKR_OK);
+
+	g_assert_cmpuint (g_hash_table_size (fields), ==, 3);
+	value = g_hash_table_lookup (fields, "one");
+	g_assert_cmpstr (value, ==, "value1");
+	value = g_hash_table_lookup (fields, "two");
+	g_assert_cmpstr (value, ==, "value2");
+	value = g_hash_table_lookup (fields, "three");
+	g_assert_cmpstr (value, ==, "value3");
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_parse_empty)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, "", 0 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	rv = gck_secret_fields_parse (&attr, &fields);
+	g_assert (rv == CKR_OK);
+
+	g_assert_cmpuint (g_hash_table_size (fields), == , 0);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_parse_null_invalid)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, NULL, 5 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	rv = gck_secret_fields_parse (&attr, &fields);
+	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+DEFINE_TEST(fields_parse_missing_value)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, "one", 3 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	rv = gck_secret_fields_parse (&attr, &fields);
+	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+DEFINE_TEST(fields_parse_missing_terminator)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, "one\0value", 9 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	rv = gck_secret_fields_parse (&attr, &fields);
+	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+DEFINE_TEST(fields_parse_not_utf8)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, "one\0not\234utf8\0", 13 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	rv = gck_secret_fields_parse (&attr, &fields);
+	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+DEFINE_TEST(fields_serialize)
+{
+	gchar buffer[32];
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, buffer, 32 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add (fields, "one", "value1");
+
+	rv = gck_secret_fields_serialize (&attr, fields);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 11);
+	g_assert (memcmp (buffer, "one\0value1\0", 11) == 0);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_serialize_length)
+{
+	CK_ATTRIBUTE attr = { CKA_G_FIELDS, NULL, 0 };
+	GHashTable *fields;
+	CK_RV rv;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add (fields, "one", "value1");
+
+	rv = gck_secret_fields_serialize (&attr, fields);
+	g_assert (rv == CKR_OK);
+	g_assert (attr.ulValueLen == 11);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_add_get_compat_uint32)
+{
+	GHashTable *fields;
+	gboolean ret;
+	guint32 value;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add_compat_uint32 (fields, "field", 992);
+
+	ret = gck_secret_fields_get_compat_uint32 (fields, "field", &value);
+	g_assert (ret == TRUE);
+	g_assert_cmpuint (value, ==, 992);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_get_compat_uint32_fail)
+{
+	GHashTable *fields;
+	gboolean ret;
+	guint32 value;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add (fields, "test", "value");
+
+	ret = gck_secret_fields_get_compat_uint32 (fields, "test", &value);
+	g_assert (ret == FALSE);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_get_compat_hashed_string)
+{
+	GHashTable *fields;
+	gboolean ret;
+	gchar *value;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add (fields, "test", "value");
+
+	ret = gck_secret_fields_get_compat_hashed_string (fields, "test", &value);
+	g_assert (ret == TRUE); /* Must be the same as the old gnome-keyring code */
+	g_assert_cmpstr (value, ==, "2063c1608d6e0baf80249c42e2be5804");
+	g_free (value);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_get_compat_hashed_already)
+{
+	GHashTable *fields;
+	gboolean ret;
+	gchar *value;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add_compat_hashed_string (fields, "test", "e991664529cd0caeb6e9fce8fac3d611");
+
+	ret = gck_secret_fields_get_compat_hashed_string (fields, "test", &value);
+	g_assert (ret == TRUE); /* What went in comes out */
+	g_assert_cmpstr (value, ==, "e991664529cd0caeb6e9fce8fac3d611");
+	g_free (value);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_get_compat_hashed_uint32)
+{
+	GHashTable *fields;
+	gboolean ret;
+	guint32 value;
+	guint32 val = 992;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add_compat_uint32 (fields, "test", val);
+
+	ret = gck_secret_fields_get_compat_hashed_uint32 (fields, "test", &value);
+	g_assert (ret == TRUE); /* Must be the same as the old gnome-keyring code */
+	g_assert_cmpuint (value, ==, 0x18273645 ^ val ^ (val << 16 | val >> 16));
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_get_compat_hashed_uint32_already)
+{
+	GHashTable *fields;
+	gboolean ret;
+	guint32 value;
+	guint32 val = 0x1bc735a5;
+
+	fields = gck_secret_fields_new ();
+	gck_secret_fields_add_compat_hashed_uint32 (fields, "test", val);
+
+	ret = gck_secret_fields_get_compat_hashed_uint32 (fields, "test", &value);
+	g_assert (ret == TRUE); /* What went in comes out */
+	g_assert_cmpuint (value, ==, val);
+
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_get_names)
+{
+	GHashTable *fields;
+	GList *names, *l;
+
+	fields = gck_secret_fields_new ();
+
+	gck_secret_fields_add (fields, "one", "11111");
+	gck_secret_fields_add_compat_uint32 (fields, "two", 2);
+	gck_secret_fields_add_compat_hashed_string (fields, "test", "2063c1608d6e0baf80249c42e2be5804");
+
+	names = gck_secret_fields_get_names (fields);
+	g_assert_cmpuint (g_list_length (names), ==, 3);
+
+	for (l = names; l; l = g_list_next (l)) {
+		g_assert (l->data);
+		if (!g_str_equal (l->data, "one") &&
+		    !g_str_equal (l->data, "two") &&
+		    !g_str_equal (l->data, "test"))
+			g_assert_not_reached ();
+	}
+
+	g_list_free (names);
+	g_hash_table_unref (fields);
+}
+
+DEFINE_TEST(fields_match)
+{
+	GHashTable *haystack;
+	GHashTable *needle;
+	gboolean ret;
+
+	haystack = gck_secret_fields_new ();
+	gck_secret_fields_add (haystack, "one", "11111");
+	gck_secret_fields_add_compat_uint32 (haystack, "two", 2);
+	gck_secret_fields_add_compat_hashed_string (haystack, "test", "2063c1608d6e0baf80249c42e2be5804"); /* Hashed 'value' */
+	gck_secret_fields_add_compat_hashed_uint32 (haystack, "number", 0x1bc735a5); /* Hashed 992 */
+	gck_secret_fields_add (haystack, "extra", "an extra value");
+
+	needle = gck_secret_fields_new ();
+	gck_secret_fields_add (needle, "one", "11111");
+	gck_secret_fields_add (needle, "two", "2");
+	gck_secret_fields_add (needle, "test", "value");
+	gck_secret_fields_add (needle, "number", "992");
+
+	ret = gck_secret_fields_match (haystack, needle);
+	g_assert (ret == TRUE);
+
+	g_hash_table_unref (haystack);
+	g_hash_table_unref (needle);
+}
+
+DEFINE_TEST(fields_match_mismatch_value)
+{
+	GHashTable *haystack;
+	GHashTable *needle;
+	gboolean ret;
+
+	haystack = gck_secret_fields_new ();
+	gck_secret_fields_add (haystack, "field", "value");
+
+	needle = gck_secret_fields_new ();
+	gck_secret_fields_add (needle, "field", "another");
+
+	ret = gck_secret_fields_match (haystack, needle);
+	g_assert (ret == FALSE);
+
+	g_hash_table_unref (haystack);
+	g_hash_table_unref (needle);
+}
+
+DEFINE_TEST(fields_match_mismatch_field)
+{
+	GHashTable *haystack;
+	GHashTable *needle;
+	gboolean ret;
+
+	haystack = gck_secret_fields_new ();
+	gck_secret_fields_add (haystack, "test", "value");
+
+	needle = gck_secret_fields_new ();
+	gck_secret_fields_add (needle, "field", "value");
+
+	ret = gck_secret_fields_match (haystack, needle);
+	g_assert (ret == FALSE);
+
+	g_hash_table_unref (haystack);
+	g_hash_table_unref (needle);
+}
+
+DEFINE_TEST(fields_match_wrong_hashed)
+{
+	GHashTable *haystack;
+	GHashTable *needle;
+	gboolean ret;
+
+	haystack = gck_secret_fields_new ();
+	gck_secret_fields_add_compat_hashed_uint32 (haystack, "number", 0x1bc735a5); /* Hashed 992 */
+
+	needle = gck_secret_fields_new ();
+	gck_secret_fields_add (needle, "number", "1000");
+
+	ret = gck_secret_fields_match (haystack, needle);
+	g_assert (ret == FALSE);
+
+	g_hash_table_unref (haystack);
+	g_hash_table_unref (needle);
+}



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