From: Simon McVittie Date: Mon, 17 Dec 2018 11:18:35 +0000 (+0000) Subject: test: Unembed hash test from libdbus and move it into test/ X-Git-Tag: dbus-1.13.10~25^2~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=053a62122bedd1f4511d46c29272f887c0743091;p=thirdparty%2Fdbus.git test: Unembed hash test from libdbus and move it into test/ This required exposing one additional internal symbol: _dbus_hash_table_ref(). I think that's a reasonable trade-off for not compiling this test into the library. Signed-off-by: Simon McVittie --- diff --git a/dbus/dbus-hash.c b/dbus/dbus-hash.c index cf20fd58f..f04b0d113 100644 --- a/dbus/dbus-hash.c +++ b/dbus/dbus-hash.c @@ -1592,443 +1592,3 @@ _dbus_hash_table_to_array (DBusHashTable *table, char delimiter) } /** @} */ - -#ifdef DBUS_ENABLE_EMBEDDED_TESTS -#include "dbus-test.h" -#include - -/* If you're wondering why the hash table test takes - * forever to run, it's because we call this function - * in inner loops thus making things quadratic. - */ -static int -count_entries (DBusHashTable *table) -{ - DBusHashIter iter; - int count; - - count = 0; - _dbus_hash_iter_init (table, &iter); - while (_dbus_hash_iter_next (&iter)) - ++count; - - _dbus_assert (count == _dbus_hash_table_get_n_entries (table)); - - return count; -} - -static inline void * -steal (void *ptr) -{ - /* @ptr is passed in as void* to avoid casting in the call */ - void **_ptr = (void **) ptr; - void *val; - - val = *_ptr; - *_ptr = NULL; - - return val; -} - -/** - * @ingroup DBusHashTableInternals - * Unit test for DBusHashTable - * @returns #TRUE on success. - */ -dbus_bool_t -_dbus_hash_test (const char *test_data_dir _DBUS_GNUC_UNUSED) -{ - int i; - DBusHashTable *table1; - DBusHashTable *table2; - DBusHashTable *table3; - DBusHashIter iter; -#define N_HASH_KEYS 5000 - char **keys; - dbus_bool_t ret = FALSE; - char *str_key = NULL; - char *str_value = NULL; - - keys = dbus_new (char *, N_HASH_KEYS); - if (keys == NULL) - _dbus_test_fatal ("no memory"); - - for (i = 0; i < N_HASH_KEYS; i++) - { - keys[i] = dbus_malloc (128); - - if (keys[i] == NULL) - _dbus_test_fatal ("no memory"); - } - - _dbus_test_diag ("Computing test hash keys..."); - i = 0; - while (i < N_HASH_KEYS) - { - int len; - - len = sprintf (keys[i], "Hash key %d", i); - _dbus_assert (*(keys[i] + len) == '\0'); - ++i; - } - _dbus_test_diag ("... done."); - - table1 = _dbus_hash_table_new (DBUS_HASH_STRING, - dbus_free, dbus_free); - if (table1 == NULL) - goto out; - - table2 = _dbus_hash_table_new (DBUS_HASH_INT, - NULL, dbus_free); - if (table2 == NULL) - goto out; - - table3 = _dbus_hash_table_new (DBUS_HASH_UINTPTR, - NULL, dbus_free); - if (table3 == NULL) - goto out; - - /* Insert and remove a bunch of stuff, counting the table in between - * to be sure it's not broken and that iteration works - */ - i = 0; - while (i < 3000) - { - const void *out_value; - - str_key = _dbus_strdup (keys[i]); - if (str_key == NULL) - goto out; - str_value = _dbus_strdup ("Value!"); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_insert_string (table1, - steal (&str_key), - steal (&str_value))) - goto out; - - str_value = _dbus_strdup (keys[i]); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_insert_int (table2, - i, steal (&str_value))) - goto out; - - str_value = _dbus_strdup (keys[i]); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_insert_uintptr (table3, - i, steal (&str_value))) - goto out; - - _dbus_assert (count_entries (table1) == i + 1); - _dbus_assert (count_entries (table2) == i + 1); - _dbus_assert (count_entries (table3) == i + 1); - - out_value = _dbus_hash_table_lookup_string (table1, keys[i]); - _dbus_assert (out_value != NULL); - _dbus_assert (strcmp (out_value, "Value!") == 0); - - out_value = _dbus_hash_table_lookup_int (table2, i); - _dbus_assert (out_value != NULL); - _dbus_assert (strcmp (out_value, keys[i]) == 0); - - out_value = _dbus_hash_table_lookup_uintptr (table3, i); - _dbus_assert (out_value != NULL); - _dbus_assert (strcmp (out_value, keys[i]) == 0); - - ++i; - } - - --i; - while (i >= 0) - { - _dbus_hash_table_remove_string (table1, - keys[i]); - - _dbus_hash_table_remove_int (table2, i); - - _dbus_hash_table_remove_uintptr (table3, i); - - _dbus_assert (count_entries (table1) == i); - _dbus_assert (count_entries (table2) == i); - _dbus_assert (count_entries (table3) == i); - - --i; - } - - _dbus_hash_table_ref (table1); - _dbus_hash_table_ref (table2); - _dbus_hash_table_ref (table3); - _dbus_hash_table_unref (table1); - _dbus_hash_table_unref (table2); - _dbus_hash_table_unref (table3); - _dbus_hash_table_unref (table1); - _dbus_hash_table_unref (table2); - _dbus_hash_table_unref (table3); - table3 = NULL; - - /* Insert a bunch of stuff then check - * that iteration works correctly (finds the right - * values, iter_set_value works, etc.) - */ - table1 = _dbus_hash_table_new (DBUS_HASH_STRING, - dbus_free, dbus_free); - if (table1 == NULL) - goto out; - - table2 = _dbus_hash_table_new (DBUS_HASH_INT, - NULL, dbus_free); - if (table2 == NULL) - goto out; - - i = 0; - while (i < 5000) - { - str_key = _dbus_strdup (keys[i]); - if (str_key == NULL) - goto out; - str_value = _dbus_strdup ("Value!"); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_insert_string (table1, - steal (&str_key), - steal (&str_value))) - goto out; - - str_value = _dbus_strdup (keys[i]); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_insert_int (table2, - i, steal (&str_value))) - goto out; - - _dbus_assert (count_entries (table1) == i + 1); - _dbus_assert (count_entries (table2) == i + 1); - - ++i; - } - - _dbus_hash_iter_init (table1, &iter); - while (_dbus_hash_iter_next (&iter)) - { - const char *key; - const void *value; - - key = _dbus_hash_iter_get_string_key (&iter); - value = _dbus_hash_iter_get_value (&iter); - - _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); - - str_value = _dbus_strdup ("Different value!"); - if (str_value == NULL) - goto out; - - value = str_value; - _dbus_hash_iter_set_value (&iter, steal (&str_value)); - _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); - } - - _dbus_hash_iter_init (table1, &iter); - while (_dbus_hash_iter_next (&iter)) - { - _dbus_hash_iter_remove_entry (&iter); - _dbus_assert (count_entries (table1) == i - 1); - --i; - } - - _dbus_hash_iter_init (table2, &iter); - while (_dbus_hash_iter_next (&iter)) - { - int key; - const void *value; - - key = _dbus_hash_iter_get_int_key (&iter); - value = _dbus_hash_iter_get_value (&iter); - - _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); - - str_value = _dbus_strdup ("Different value!"); - if (str_value == NULL) - goto out; - - value = str_value; - _dbus_hash_iter_set_value (&iter, steal (&str_value)); - _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); - } - - i = count_entries (table2); - _dbus_hash_iter_init (table2, &iter); - while (_dbus_hash_iter_next (&iter)) - { - _dbus_hash_iter_remove_entry (&iter); - _dbus_assert (count_entries (table2) + 1 == i); - --i; - } - - /* add/remove interleaved, to check that we grow/shrink the table - * appropriately - */ - i = 0; - while (i < 1000) - { - str_key = _dbus_strdup (keys[i]); - if (str_key == NULL) - goto out; - - str_value = _dbus_strdup ("Value!"); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_insert_string (table1, - steal (&str_key), - steal (&str_value))) - goto out; - - ++i; - } - - --i; - while (i >= 0) - { - str_key = _dbus_strdup (keys[i]); - if (str_key == NULL) - goto out; - str_value = _dbus_strdup ("Value!"); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_table_remove_string (table1, keys[i])) - goto out; - - if (!_dbus_hash_table_insert_string (table1, - steal (&str_key), - steal (&str_value))) - goto out; - - if (!_dbus_hash_table_remove_string (table1, keys[i])) - goto out; - - _dbus_assert (_dbus_hash_table_get_n_entries (table1) == i); - - --i; - } - - /* nuke these tables */ - _dbus_hash_table_unref (table1); - _dbus_hash_table_unref (table2); - - - /* Now do a bunch of things again using _dbus_hash_iter_lookup() to - * be sure that interface works. - */ - table1 = _dbus_hash_table_new (DBUS_HASH_STRING, - dbus_free, dbus_free); - if (table1 == NULL) - goto out; - - table2 = _dbus_hash_table_new (DBUS_HASH_INT, - NULL, dbus_free); - if (table2 == NULL) - goto out; - - i = 0; - while (i < 3000) - { - const void *out_value; - - str_key = _dbus_strdup (keys[i]); - if (str_key == NULL) - goto out; - str_value = _dbus_strdup ("Value!"); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_iter_lookup (table1, - steal (&str_key), TRUE, &iter)) - goto out; - _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); - _dbus_hash_iter_set_value (&iter, steal (&str_value)); - - str_value = _dbus_strdup (keys[i]); - if (str_value == NULL) - goto out; - - if (!_dbus_hash_iter_lookup (table2, - _DBUS_INT_TO_POINTER (i), TRUE, &iter)) - goto out; - _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); - _dbus_hash_iter_set_value (&iter, steal (&str_value)); - - _dbus_assert (count_entries (table1) == i + 1); - _dbus_assert (count_entries (table2) == i + 1); - - if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) - goto out; - - out_value = _dbus_hash_iter_get_value (&iter); - _dbus_assert (out_value != NULL); - _dbus_assert (strcmp (out_value, "Value!") == 0); - - /* Iterate just to be sure it works, though - * it's a stupid thing to do - */ - while (_dbus_hash_iter_next (&iter)) - ; - - if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) - goto out; - - out_value = _dbus_hash_iter_get_value (&iter); - _dbus_assert (out_value != NULL); - _dbus_assert (strcmp (out_value, keys[i]) == 0); - - /* Iterate just to be sure it works, though - * it's a stupid thing to do - */ - while (_dbus_hash_iter_next (&iter)) - ; - - ++i; - } - - --i; - while (i >= 0) - { - if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) - _dbus_test_fatal ("hash entry should have existed"); - _dbus_hash_iter_remove_entry (&iter); - - if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) - _dbus_test_fatal ("hash entry should have existed"); - _dbus_hash_iter_remove_entry (&iter); - - _dbus_assert (count_entries (table1) == i); - _dbus_assert (count_entries (table2) == i); - - --i; - } - - _dbus_hash_table_unref (table1); - _dbus_hash_table_unref (table2); - - ret = TRUE; - - out: - for (i = 0; i < N_HASH_KEYS; i++) - dbus_free (keys[i]); - - dbus_free (keys); - - dbus_free (str_key); - dbus_free (str_value); - - return ret; -} - -#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/dbus/dbus-hash.h b/dbus/dbus-hash.h index 9387f9ebb..ea6fef0d4 100644 --- a/dbus/dbus-hash.h +++ b/dbus/dbus-hash.h @@ -75,6 +75,7 @@ DBUS_PRIVATE_EXPORT DBusHashTable* _dbus_hash_table_new (DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function); +DBUS_PRIVATE_EXPORT DBusHashTable* _dbus_hash_table_ref (DBusHashTable *table); DBUS_PRIVATE_EXPORT void _dbus_hash_table_unref (DBusHashTable *table); diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h index 29f78915a..6be55f396 100644 --- a/dbus/dbus-test.h +++ b/dbus/dbus-test.h @@ -37,9 +37,6 @@ * then you have added too many. */ -DBUS_PRIVATE_EXPORT -dbus_bool_t _dbus_hash_test (const char *test_data_dir); - DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_list_test (const char *test_data_dir); diff --git a/test/internals/hash.c b/test/internals/hash.c index f6faa7356..314c65f09 100644 --- a/test/internals/hash.c +++ b/test/internals/hash.c @@ -1,6 +1,9 @@ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* + * Copyright 1991-1993 The Regents of the University of California + * Copyright 1994 Sun Microsystems, Inc. * Copyright 2002-2009 Red Hat, Inc. + * Copyright 2003 Joe Shaw * Copyright 2011-2018 Collabora Ltd. * * Licensed under the Academic Free License version 2.1 @@ -19,14 +22,497 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * The following license applies to code from the Tcl distribution, + * if there is any in this file: + * + * Copyright (c) 1991-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * This software is copyrighted by the Regents of the University of + * California, Sun Microsystems, Inc., Scriptics Corporation, and + * other parties. The following terms apply to all files associated + * with the software unless explicitly disclaimed in individual files. + * + * The authors hereby grant permission to use, copy, modify, + * distribute, and license this software and its documentation for any + * purpose, provided that existing copyright notices are retained in + * all copies and that this notice is included verbatim in any + * distributions. No written agreement, license, or royalty fee is + * required for any of the authorized uses. Modifications to this + * software may be copyrighted by their authors and need not follow + * the licensing terms described here, provided that the new terms are + * clearly indicated on the first page of each file where they apply. + * + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL + * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, + * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + * NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, + * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf of the + * U.S. government, the Government shall have only "Restricted Rights" + * in the software and related documentation as defined in the Federal + * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you + * are acquiring the software on behalf of the Department of Defense, + * the software shall be classified as "Commercial Computer Software" + * and the Government shall have only "Restricted Rights" as defined + * in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others acting + * in its behalf permission to use and distribute the software in + * accordance with the terms specified in this license. */ #include +#include + +#include "dbus/dbus-hash.h" #include "dbus/dbus-internals.h" #include "dbus/dbus-test.h" +#include "dbus/dbus-test-tap.h" #include "test/test-utils.h" +/* If you're wondering why the hash table test takes + * forever to run, it's because we call this function + * in inner loops thus making things quadratic. + */ +static int +count_entries (DBusHashTable *table) +{ + DBusHashIter iter; + int count; + + count = 0; + _dbus_hash_iter_init (table, &iter); + while (_dbus_hash_iter_next (&iter)) + ++count; + + _dbus_assert (count == _dbus_hash_table_get_n_entries (table)); + + return count; +} + +static inline void * +steal (void *ptr) +{ + /* @ptr is passed in as void* to avoid casting in the call */ + void **_ptr = (void **) ptr; + void *val; + + val = *_ptr; + *_ptr = NULL; + + return val; +} + +/** + * @ingroup DBusHashTableInternals + * Unit test for DBusHashTable + * @returns #TRUE on success. + */ +static dbus_bool_t +_dbus_hash_test (const char *test_data_dir _DBUS_GNUC_UNUSED) +{ + int i; + DBusHashTable *table1; + DBusHashTable *table2; + DBusHashTable *table3; + DBusHashIter iter; +#define N_HASH_KEYS 5000 + char **keys; + dbus_bool_t ret = FALSE; + char *str_key = NULL; + char *str_value = NULL; + + keys = dbus_new (char *, N_HASH_KEYS); + if (keys == NULL) + _dbus_test_fatal ("no memory"); + + for (i = 0; i < N_HASH_KEYS; i++) + { + keys[i] = dbus_malloc (128); + + if (keys[i] == NULL) + _dbus_test_fatal ("no memory"); + } + + _dbus_test_diag ("Computing test hash keys..."); + i = 0; + while (i < N_HASH_KEYS) + { + int len; + + len = sprintf (keys[i], "Hash key %d", i); + _dbus_assert (*(keys[i] + len) == '\0'); + ++i; + } + _dbus_test_diag ("... done."); + + table1 = _dbus_hash_table_new (DBUS_HASH_STRING, + dbus_free, dbus_free); + if (table1 == NULL) + goto out; + + table2 = _dbus_hash_table_new (DBUS_HASH_INT, + NULL, dbus_free); + if (table2 == NULL) + goto out; + + table3 = _dbus_hash_table_new (DBUS_HASH_UINTPTR, + NULL, dbus_free); + if (table3 == NULL) + goto out; + + /* Insert and remove a bunch of stuff, counting the table in between + * to be sure it's not broken and that iteration works + */ + i = 0; + while (i < 3000) + { + const void *out_value; + + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) + goto out; + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_insert_string (table1, + steal (&str_key), + steal (&str_value))) + goto out; + + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_insert_int (table2, + i, steal (&str_value))) + goto out; + + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_insert_uintptr (table3, + i, steal (&str_value))) + goto out; + + _dbus_assert (count_entries (table1) == i + 1); + _dbus_assert (count_entries (table2) == i + 1); + _dbus_assert (count_entries (table3) == i + 1); + + out_value = _dbus_hash_table_lookup_string (table1, keys[i]); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, "Value!") == 0); + + out_value = _dbus_hash_table_lookup_int (table2, i); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, keys[i]) == 0); + + out_value = _dbus_hash_table_lookup_uintptr (table3, i); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, keys[i]) == 0); + + ++i; + } + + --i; + while (i >= 0) + { + _dbus_hash_table_remove_string (table1, + keys[i]); + + _dbus_hash_table_remove_int (table2, i); + + _dbus_hash_table_remove_uintptr (table3, i); + + _dbus_assert (count_entries (table1) == i); + _dbus_assert (count_entries (table2) == i); + _dbus_assert (count_entries (table3) == i); + + --i; + } + + _dbus_hash_table_ref (table1); + _dbus_hash_table_ref (table2); + _dbus_hash_table_ref (table3); + _dbus_hash_table_unref (table1); + _dbus_hash_table_unref (table2); + _dbus_hash_table_unref (table3); + _dbus_hash_table_unref (table1); + _dbus_hash_table_unref (table2); + _dbus_hash_table_unref (table3); + table3 = NULL; + + /* Insert a bunch of stuff then check + * that iteration works correctly (finds the right + * values, iter_set_value works, etc.) + */ + table1 = _dbus_hash_table_new (DBUS_HASH_STRING, + dbus_free, dbus_free); + if (table1 == NULL) + goto out; + + table2 = _dbus_hash_table_new (DBUS_HASH_INT, + NULL, dbus_free); + if (table2 == NULL) + goto out; + + i = 0; + while (i < 5000) + { + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) + goto out; + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_insert_string (table1, + steal (&str_key), + steal (&str_value))) + goto out; + + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_insert_int (table2, + i, steal (&str_value))) + goto out; + + _dbus_assert (count_entries (table1) == i + 1); + _dbus_assert (count_entries (table2) == i + 1); + + ++i; + } + + _dbus_hash_iter_init (table1, &iter); + while (_dbus_hash_iter_next (&iter)) + { + const char *key; + const void *value; + + key = _dbus_hash_iter_get_string_key (&iter); + value = _dbus_hash_iter_get_value (&iter); + + _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); + + str_value = _dbus_strdup ("Different value!"); + if (str_value == NULL) + goto out; + + value = str_value; + _dbus_hash_iter_set_value (&iter, steal (&str_value)); + _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value); + } + + _dbus_hash_iter_init (table1, &iter); + while (_dbus_hash_iter_next (&iter)) + { + _dbus_hash_iter_remove_entry (&iter); + _dbus_assert (count_entries (table1) == i - 1); + --i; + } + + _dbus_hash_iter_init (table2, &iter); + while (_dbus_hash_iter_next (&iter)) + { + int key; + const void *value; + + key = _dbus_hash_iter_get_int_key (&iter); + value = _dbus_hash_iter_get_value (&iter); + + _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); + + str_value = _dbus_strdup ("Different value!"); + if (str_value == NULL) + goto out; + + value = str_value; + _dbus_hash_iter_set_value (&iter, steal (&str_value)); + _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value); + } + + i = count_entries (table2); + _dbus_hash_iter_init (table2, &iter); + while (_dbus_hash_iter_next (&iter)) + { + _dbus_hash_iter_remove_entry (&iter); + _dbus_assert (count_entries (table2) + 1 == i); + --i; + } + + /* add/remove interleaved, to check that we grow/shrink the table + * appropriately + */ + i = 0; + while (i < 1000) + { + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) + goto out; + + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_insert_string (table1, + steal (&str_key), + steal (&str_value))) + goto out; + + ++i; + } + + --i; + while (i >= 0) + { + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) + goto out; + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_table_remove_string (table1, keys[i])) + goto out; + + if (!_dbus_hash_table_insert_string (table1, + steal (&str_key), + steal (&str_value))) + goto out; + + if (!_dbus_hash_table_remove_string (table1, keys[i])) + goto out; + + _dbus_assert (_dbus_hash_table_get_n_entries (table1) == i); + + --i; + } + + /* nuke these tables */ + _dbus_hash_table_unref (table1); + _dbus_hash_table_unref (table2); + + + /* Now do a bunch of things again using _dbus_hash_iter_lookup() to + * be sure that interface works. + */ + table1 = _dbus_hash_table_new (DBUS_HASH_STRING, + dbus_free, dbus_free); + if (table1 == NULL) + goto out; + + table2 = _dbus_hash_table_new (DBUS_HASH_INT, + NULL, dbus_free); + if (table2 == NULL) + goto out; + + i = 0; + while (i < 3000) + { + const void *out_value; + + str_key = _dbus_strdup (keys[i]); + if (str_key == NULL) + goto out; + str_value = _dbus_strdup ("Value!"); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_iter_lookup (table1, + steal (&str_key), TRUE, &iter)) + goto out; + _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); + _dbus_hash_iter_set_value (&iter, steal (&str_value)); + + str_value = _dbus_strdup (keys[i]); + if (str_value == NULL) + goto out; + + if (!_dbus_hash_iter_lookup (table2, + _DBUS_INT_TO_POINTER (i), TRUE, &iter)) + goto out; + _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL); + _dbus_hash_iter_set_value (&iter, steal (&str_value)); + + _dbus_assert (count_entries (table1) == i + 1); + _dbus_assert (count_entries (table2) == i + 1); + + if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) + goto out; + + out_value = _dbus_hash_iter_get_value (&iter); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, "Value!") == 0); + + /* Iterate just to be sure it works, though + * it's a stupid thing to do + */ + while (_dbus_hash_iter_next (&iter)) + ; + + if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) + goto out; + + out_value = _dbus_hash_iter_get_value (&iter); + _dbus_assert (out_value != NULL); + _dbus_assert (strcmp (out_value, keys[i]) == 0); + + /* Iterate just to be sure it works, though + * it's a stupid thing to do + */ + while (_dbus_hash_iter_next (&iter)) + ; + + ++i; + } + + --i; + while (i >= 0) + { + if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter)) + _dbus_test_fatal ("hash entry should have existed"); + _dbus_hash_iter_remove_entry (&iter); + + if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter)) + _dbus_test_fatal ("hash entry should have existed"); + _dbus_hash_iter_remove_entry (&iter); + + _dbus_assert (count_entries (table1) == i); + _dbus_assert (count_entries (table2) == i); + + --i; + } + + _dbus_hash_table_unref (table1); + _dbus_hash_table_unref (table2); + + ret = TRUE; + + out: + for (i = 0; i < N_HASH_KEYS; i++) + dbus_free (keys[i]); + + dbus_free (keys); + + dbus_free (str_key); + dbus_free (str_value); + + return ret; +} + static DBusTestCase test = { "hash", _dbus_hash_test }; int