summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-03-06 19:12:28 +0100
committerStef Walter <stefw@gnome.org>2013-03-15 17:21:49 +0100
commitd2128c263ea77e4f99bccc6ac46964ad419ec2d1 (patch)
tree15cb1d23477b6e6df689e9c60c5ec8abcfd0a638
parent86e60637394340ef2fa3b3db6b451dac1d73052b (diff)
downloadp11-kit-d2128c263ea77e4f99bccc6ac46964ad419ec2d1.tar.gz
dict: Allow removal of current item in a p11_dict iteration
* This was already possible to do safely before * Document and test this behavior https://bugs.freedesktop.org/show_bug.cgi?id=61499
-rw-r--r--common/dict.h2
-rw-r--r--common/tests/test-dict.c60
2 files changed, 62 insertions, 0 deletions
diff --git a/common/dict.h b/common/dict.h
index e13c5d6..080f6b8 100644
--- a/common/dict.h
+++ b/common/dict.h
@@ -141,6 +141,8 @@ void p11_dict_iterate (p11_dict *dict,
* p11_dict_next: Enumerate through hash table
* - sets key and value to key and/or value
* - returns whether there was another entry
+ * - p11_dict_remove or p11_dict_steal is safe to use on
+ * the current key.
*/
bool p11_dict_next (p11_dictiter *iter,
void **key,
diff --git a/common/tests/test-dict.c b/common/tests/test-dict.c
index 00b64c5..316d9f5 100644
--- a/common/tests/test-dict.c
+++ b/common/tests/test-dict.c
@@ -143,6 +143,65 @@ test_iterate (CuTest *tc)
p11_dict_free (map);
}
+static int
+compar_pointers (const void *one,
+ const void *two)
+{
+ char **p1 = (char **)one;
+ char **p2 = (char **)two;
+ return *p1 - *p2;
+}
+
+static void
+test_iterate_remove (CuTest *tc)
+{
+ p11_dict *map;
+ p11_dictiter iter;
+ char *keys[] = { "one", "two", "three" };
+ char *values[] = { "four", "eight", "twelve" };
+ void *okeys[3];
+ void *ovalues[3];
+ bool ret;
+ int i;
+
+ map = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal, NULL, NULL);
+ CuAssertPtrNotNull (tc, map);
+
+ for (i = 0; i < 3; i++) {
+ if (!p11_dict_set (map, keys[i], values[i]))
+ CuFail (tc, "should not be reached");
+ }
+
+ p11_dict_iterate (map, &iter);
+
+ ret = p11_dict_next (&iter, &okeys[0], &ovalues[0]);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_dict_next (&iter, &okeys[1], &ovalues[1]);
+ CuAssertIntEquals (tc, true, ret);
+ if (!p11_dict_remove (map, okeys[1]))
+ CuFail (tc, "should not be reached");
+
+ ret = p11_dict_next (&iter, &okeys[2], &ovalues[2]);
+ CuAssertIntEquals (tc, true, ret);
+
+ ret = p11_dict_next (&iter, NULL, NULL);
+ CuAssertIntEquals (tc, false, ret);
+
+ CuAssertIntEquals (tc, 2, p11_dict_size (map));
+ p11_dict_free (map);
+
+ qsort (okeys, 3, sizeof (void *), compar_pointers);
+ qsort (ovalues, 3, sizeof (void *), compar_pointers);
+
+ for (i = 0; i < 3; i++) {
+ CuAssertStrEquals (tc, keys[i], okeys[i]);
+ CuAssertPtrEquals (tc, keys[i], okeys[i]);
+ CuAssertStrEquals (tc, values[i], ovalues[i]);
+ CuAssertPtrEquals (tc, values[i], ovalues[i]);
+ }
+}
+
static void
test_set_get (CuTest *tc)
{
@@ -455,6 +514,7 @@ main (void)
SUITE_ADD_TEST (suite, test_free_null);
SUITE_ADD_TEST (suite, test_free_destroys);
SUITE_ADD_TEST (suite, test_iterate);
+ SUITE_ADD_TEST (suite, test_iterate_remove);
SUITE_ADD_TEST (suite, test_hash_add_check_lots_and_collisions);
SUITE_ADD_TEST (suite, test_hash_count);
SUITE_ADD_TEST (suite, test_hash_ulongptr);