1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1999 The Free Software Foundation
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GLib Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GLib at ftp://ftp.gtk.org/pub/gtk/.
28 #undef G_DISABLE_ASSERT
39 static int global_array[10000];
42 fill_hash_table_and_array (GHashTable *hash_table)
46 for (i = 0; i < 10000; i++)
49 g_hash_table_insert (hash_table, &global_array[i], &global_array[i]);
54 init_result_array (int result_array[10000])
58 for (i = 0; i < 10000; i++)
63 verify_result_array (int array[10000])
67 for (i = 0; i < 10000; i++)
68 g_assert (array[i] == i);
72 handle_pair (gpointer key, gpointer value, int result_array[10000])
76 g_assert (key == value);
80 g_assert (n >= 0 && n < 10000);
81 g_assert (result_array[n] == -1);
87 my_hash_callback_remove (gpointer key,
100 my_hash_callback_remove_test (gpointer key,
107 g_assert_not_reached ();
111 my_hash_callback (gpointer key,
115 handle_pair (key, value, user_data);
119 my_hash (gconstpointer key)
121 return (guint) *((const gint*) key);
125 my_hash_equal (gconstpointer a,
128 return *((const gint*) a) == *((const gint*) b);
134 * This is a simplified version of the pathalias hashing function.
135 * Thanks to Steve Belovin and Peter Honeyman
137 * hash a string into a long int. 31 bit crc (from andrew appel).
138 * the crc table is computed at run time by crcinit() -- we could
139 * precompute, but it takes 1 clock tick on a 750.
141 * This fast table calculation works only if POLY is a prime polynomial
142 * in the field of integers modulo 2. Since the coefficients of a
143 * 32-bit polynomial won't fit in a 32-bit word, the high-order bit is
144 * implicit. IT MUST ALSO BE THE CASE that the coefficients of orders
145 * 31 down to 25 are zero. Happily, we have candidates, from
146 * E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
147 * x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
150 * We reverse the bits to get:
151 * 111101010000000000000000000000001 but drop the last 1
153 * 010010000000000000000000000000001 ditto, for 31-bit crc
157 #define POLY 0x48000000L /* 31-bit polynomial (avoids sign problems) */
159 static guint CrcTable[128];
162 - crcinit - initialize tables for hash function
164 static void crcinit(void)
169 for (i = 0; i < 128; ++i)
172 for (j = 7 - 1; j >= 0; --j)
180 - hash - Honeyman's nice hashing function
183 honeyman_hash (gconstpointer key)
185 const gchar *name = (const gchar *) key;
189 g_assert (name != NULL);
190 g_assert (*name != 0);
192 size = strlen (name);
195 sum = (sum >> 7) ^ CrcTable[(sum ^ (*name++)) & 0x7f];
202 second_hash_cmp (gconstpointer a, gconstpointer b)
204 return strcmp (a, b) == 0;
210 one_hash (gconstpointer key)
217 not_even_foreach (gpointer key,
221 const char *_key = (const char *) key;
222 const char *_value = (const char *) value;
226 g_assert (_key != NULL);
227 g_assert (*_key != 0);
228 g_assert (_value != NULL);
229 g_assert (*_value != 0);
233 sprintf (val, "%d value", i);
234 g_assert (strcmp (_value, val) == 0);
236 g_assert ((i % 2) != 0);
241 remove_even_foreach (gpointer key,
245 const char *_key = (const char *) key;
246 const char *_value = (const char *) value;
250 g_assert (_key != NULL);
251 g_assert (*_key != 0);
252 g_assert (_value != NULL);
253 g_assert (*_value != 0);
257 sprintf (val, "%d value", i);
258 g_assert (strcmp (_value, val) == 0);
260 return ((i % 2) == 0) ? TRUE : FALSE;
267 second_hash_test (gconstpointer d)
269 gboolean simple_hash = GPOINTER_TO_INT (d);
272 char key[20] = "", val[20]="", *v, *orig_key, *orig_val;
278 h = g_hash_table_new_full (simple_hash ? one_hash : honeyman_hash,
281 g_assert (h != NULL);
282 for (i = 0; i < 20; i++)
284 sprintf (key, "%d", i);
285 g_assert (atoi (key) == i);
287 sprintf (val, "%d value", i);
288 g_assert (atoi (val) == i);
290 g_hash_table_insert (h, g_strdup (key), g_strdup (val));
293 g_assert (g_hash_table_size (h) == 20);
295 for (i = 0; i < 20; i++)
297 sprintf (key, "%d", i);
298 g_assert (atoi(key) == i);
300 v = (char *) g_hash_table_lookup (h, key);
302 g_assert (v != NULL);
304 g_assert (atoi (v) == i);
307 sprintf (key, "%d", 3);
308 g_hash_table_remove (h, key);
309 g_assert (g_hash_table_size (h) == 19);
310 g_hash_table_foreach_remove (h, remove_even_foreach, NULL);
311 g_assert (g_hash_table_size (h) == 9);
312 g_hash_table_foreach (h, not_even_foreach, NULL);
314 for (i = 0; i < 20; i++)
316 sprintf (key, "%d", i);
317 g_assert (atoi(key) == i);
319 sprintf (val, "%d value", i);
320 g_assert (atoi (val) == i);
322 orig_key = orig_val = NULL;
323 found = g_hash_table_lookup_extended (h, key,
325 (gpointer)&orig_val);
326 if ((i % 2) == 0 || i == 3)
334 g_assert (orig_key != NULL);
335 g_assert (strcmp (key, orig_key) == 0);
337 g_assert (orig_val != NULL);
338 g_assert (strcmp (val, orig_val) == 0);
341 g_hash_table_destroy (h);
345 find_first (gpointer key,
350 gint *test = user_data;
351 return (*v == *test);
355 direct_hash_test (void)
360 h = g_hash_table_new (NULL, NULL);
361 g_assert (h != NULL);
362 for (i = 1; i <= 20; i++)
363 g_hash_table_insert (h, GINT_TO_POINTER (i),
364 GINT_TO_POINTER (i + 42));
366 g_assert (g_hash_table_size (h) == 20);
368 for (i = 1; i <= 20; i++)
370 rc = GPOINTER_TO_INT (g_hash_table_lookup (h, GINT_TO_POINTER (i)));
373 g_assert ((rc - 42) == i);
376 g_hash_table_destroy (h);
380 direct_hash_test2 (void)
385 h = g_hash_table_new (g_direct_hash, g_direct_equal);
386 g_assert (h != NULL);
387 for (i = 1; i <= 20; i++)
388 g_hash_table_insert (h, GINT_TO_POINTER (i),
389 GINT_TO_POINTER (i + 42));
391 g_assert (g_hash_table_size (h) == 20);
393 for (i = 1; i <= 20; i++)
395 rc = GPOINTER_TO_INT (g_hash_table_lookup (h, GINT_TO_POINTER (i)));
398 g_assert ((rc - 42) == i);
401 g_hash_table_destroy (h);
412 h = g_hash_table_new (g_int_hash, g_int_equal);
413 g_assert (h != NULL);
414 for (i = 0; i < 20; i++)
417 g_hash_table_insert (h, &values[i], GINT_TO_POINTER (i + 42));
420 g_assert (g_hash_table_size (h) == 20);
422 for (i = 0; i < 20; i++)
425 rc = GPOINTER_TO_INT (g_hash_table_lookup (h, &key));
427 g_assert_cmpint (rc, ==, i + 42);
430 g_hash_table_destroy (h);
434 int64_hash_test (void)
441 h = g_hash_table_new (g_int64_hash, g_int64_equal);
442 g_assert (h != NULL);
443 for (i = 0; i < 20; i++)
446 g_hash_table_insert (h, &values[i], GINT_TO_POINTER (i + 42));
449 g_assert (g_hash_table_size (h) == 20);
451 for (i = 0; i < 20; i++)
454 rc = GPOINTER_TO_INT (g_hash_table_lookup (h, &key));
456 g_assert_cmpint (rc, ==, i + 42);
459 g_hash_table_destroy (h);
463 int64_hash_collision_test (void)
468 g_test_summary ("Check int64 Hash collisions caused by ignoring high word");
471 n = ((gint64) 2003 << 32) + 722;
472 g_assert_cmpuint (g_int64_hash (&m), !=, g_int64_hash (&n));
476 double_hash_test (void)
483 h = g_hash_table_new (g_double_hash, g_double_equal);
484 g_assert (h != NULL);
485 for (i = 0; i < 20; i++)
487 values[i] = i + 42.5;
488 g_hash_table_insert (h, &values[i], GINT_TO_POINTER (i + 42));
491 g_assert (g_hash_table_size (h) == 20);
493 for (i = 0; i < 20; i++)
496 rc = GPOINTER_TO_INT (g_hash_table_lookup (h, &key));
498 g_assert_cmpint (rc, ==, i + 42);
501 g_hash_table_destroy (h);
505 double_hash_collision_test (void)
510 g_test_summary ("Check double Hash collisions caused by int conversion " \
511 "and by numbers larger than 2^64-1 (G_MAXUINT64)");
512 g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2771");
514 /* Equal when directly converted to integers */
517 g_assert_cmpuint (g_double_hash (&m), !=, g_double_hash (&n));
519 /* Numbers larger than 2^64-1 (G_MAXUINT64) */
522 g_assert_cmpuint (g_double_hash (&m), !=, g_double_hash (&n));
526 string_free (gpointer data)
530 g_string_free (s, TRUE);
534 string_hash_test (void)
540 h = g_hash_table_new_full ((GHashFunc)g_string_hash, (GEqualFunc)g_string_equal, string_free, NULL);
541 g_assert (h != NULL);
542 for (i = 0; i < 20; i++)
544 s = g_string_new ("");
545 g_string_append_printf (s, "%d", i + 42);
546 g_string_append_c (s, '.');
547 g_string_prepend_unichar (s, 0x2301);
548 g_hash_table_insert (h, s, GINT_TO_POINTER (i + 42));
551 g_assert (g_hash_table_size (h) == 20);
553 s = g_string_new ("");
554 for (i = 0; i < 20; i++)
556 g_string_assign (s, "");
557 g_string_append_printf (s, "%d", i + 42);
558 g_string_append_c (s, '.');
559 g_string_prepend_unichar (s, 0x2301);
560 rc = GPOINTER_TO_INT (g_hash_table_lookup (h, s));
562 g_assert_cmpint (rc, ==, i + 42);
565 g_string_free (s, TRUE);
566 g_hash_table_destroy (h);
570 set_check (gpointer key,
576 g_assert_not_reached ();
578 g_assert_cmpint (atoi (key) % 7, ==, 2);
586 GHashTable *hash_table =
587 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
590 for (i = 2; i < 5000; i += 7)
592 char *s = g_strdup_printf ("%d", i);
593 g_assert (g_hash_table_add (hash_table, s));
596 g_assert (!g_hash_table_add (hash_table, g_strdup_printf ("%d", 2)));
599 g_hash_table_foreach (hash_table, set_check, &i);
600 g_assert_cmpint (i, ==, g_hash_table_size (hash_table));
602 g_assert (g_hash_table_contains (hash_table, "2"));
603 g_assert (g_hash_table_contains (hash_table, "9"));
604 g_assert (!g_hash_table_contains (hash_table, "a"));
606 /* this will cause the hash table to loose set nature */
607 g_assert (g_hash_table_insert (hash_table, g_strdup ("a"), "b"));
608 g_assert (!g_hash_table_insert (hash_table, g_strdup ("a"), "b"));
610 g_assert (g_hash_table_replace (hash_table, g_strdup ("c"), "d"));
611 g_assert (!g_hash_table_replace (hash_table, g_strdup ("c"), "d"));
613 g_assert_cmpstr (g_hash_table_lookup (hash_table, "2"), ==, "2");
614 g_assert_cmpstr (g_hash_table_lookup (hash_table, "a"), ==, "b");
616 g_hash_table_destroy (hash_table);
621 test_hash_misc (void)
623 GHashTable *hash_table;
627 GList *keys, *values;
628 gsize keys_len, values_len;
630 gpointer ikey, ivalue;
631 int result_array[10000];
634 hash_table = g_hash_table_new (my_hash, my_hash_equal);
635 fill_hash_table_and_array (hash_table);
636 pvalue = g_hash_table_find (hash_table, find_first, &value);
637 if (!pvalue || *pvalue != value)
638 g_assert_not_reached();
640 keys = g_hash_table_get_keys (hash_table);
642 g_assert_not_reached ();
644 values = g_hash_table_get_values (hash_table);
646 g_assert_not_reached ();
648 keys_len = g_list_length (keys);
649 values_len = g_list_length (values);
650 if (values_len != keys_len && keys_len != g_hash_table_size (hash_table))
651 g_assert_not_reached ();
654 g_list_free (values);
656 init_result_array (result_array);
657 g_hash_table_iter_init (&iter, hash_table);
658 for (i = 0; i < 10000; i++)
660 g_assert (g_hash_table_iter_next (&iter, &ikey, &ivalue));
662 handle_pair (ikey, ivalue, result_array);
665 g_hash_table_iter_remove (&iter);
667 g_assert (! g_hash_table_iter_next (&iter, &ikey, &ivalue));
668 g_assert (g_hash_table_size (hash_table) == 5000);
669 verify_result_array (result_array);
671 fill_hash_table_and_array (hash_table);
673 init_result_array (result_array);
674 g_hash_table_foreach (hash_table, my_hash_callback, result_array);
675 verify_result_array (result_array);
677 for (i = 0; i < 10000; i++)
678 g_hash_table_remove (hash_table, &global_array[i]);
680 fill_hash_table_and_array (hash_table);
682 if (g_hash_table_foreach_remove (hash_table, my_hash_callback_remove, NULL) != 5000 ||
683 g_hash_table_size (hash_table) != 5000)
684 g_assert_not_reached();
686 g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL);
687 g_hash_table_destroy (hash_table);
689 hash_table = g_hash_table_new (my_hash, my_hash_equal);
690 fill_hash_table_and_array (hash_table);
694 g_hash_table_iter_init (&iter, hash_table);
695 for (i = 0; i < 10000; i++)
697 g_assert (g_hash_table_iter_next (&iter, &ikey, &ivalue));
698 g_hash_table_iter_replace (&iter, &n_array[0]);
701 g_hash_table_iter_init (&iter, hash_table);
702 for (i = 0; i < 10000; i++)
704 g_assert (g_hash_table_iter_next (&iter, &ikey, &ivalue));
706 g_assert (ivalue == &n_array[0]);
709 g_hash_table_destroy (hash_table);
712 static gint destroy_counter;
715 value_destroy (gpointer value)
726 gboolean abc_seen = FALSE;
727 gboolean cde_seen = FALSE;
728 gboolean xyz_seen = FALSE;
730 h = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, value_destroy);
731 g_hash_table_insert (h, "abc", "ABC");
732 g_hash_table_insert (h, "cde", "CDE");
733 g_hash_table_insert (h, "xyz", "XYZ");
735 g_assert_cmpint (g_hash_table_size (h), == , 3);
737 g_hash_table_iter_init (&iter, h);
739 while (g_hash_table_iter_next (&iter, (gpointer*)&key, (gpointer*)&value))
741 if (strcmp (key, "abc") == 0)
743 g_assert_cmpstr (value, ==, "ABC");
745 g_hash_table_iter_steal (&iter);
747 else if (strcmp (key, "cde") == 0)
749 g_assert_cmpstr (value, ==, "CDE");
752 else if (strcmp (key, "xyz") == 0)
754 g_assert_cmpstr (value, ==, "XYZ");
758 g_assert_cmpint (destroy_counter, ==, 0);
760 g_assert (g_hash_table_iter_get_hash_table (&iter) == h);
761 g_assert (abc_seen && cde_seen && xyz_seen);
762 g_assert_cmpint (g_hash_table_size (h), == , 2);
764 g_hash_table_ref (h);
765 g_hash_table_destroy (h);
766 g_assert_cmpint (g_hash_table_size (h), == , 0);
767 g_assert_cmpint (destroy_counter, ==, 2);
768 g_hash_table_insert (h, "uvw", "UVW");
769 g_hash_table_unref (h);
770 g_assert_cmpint (destroy_counter, ==, 3);
774 null_safe_str_hash (gconstpointer key)
779 return g_str_hash (key);
783 null_safe_str_equal (gconstpointer a, gconstpointer b)
785 return g_strcmp0 (a, b) == 0;
789 test_lookup_null_key (void)
796 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=642944");
798 h = g_hash_table_new (null_safe_str_hash, null_safe_str_equal);
799 g_hash_table_insert (h, "abc", "ABC");
801 res = g_hash_table_lookup_extended (h, NULL, &key, &value);
804 g_hash_table_insert (h, NULL, "NULL");
806 res = g_hash_table_lookup_extended (h, NULL, &key, &value);
808 g_assert_cmpstr (value, ==, "NULL");
810 g_hash_table_unref (h);
813 static gint destroy_key_counter;
816 key_destroy (gpointer key)
818 destroy_key_counter++;
822 test_remove_all (void)
827 h = g_hash_table_new_full (g_str_hash, g_str_equal, key_destroy, value_destroy);
829 g_hash_table_insert (h, "abc", "cde");
830 g_hash_table_insert (h, "cde", "xyz");
831 g_hash_table_insert (h, "xyz", "abc");
834 destroy_key_counter = 0;
836 g_hash_table_steal_all (h);
837 g_assert_cmpint (destroy_counter, ==, 0);
838 g_assert_cmpint (destroy_key_counter, ==, 0);
840 /* Test stealing on an empty hash table. */
841 g_hash_table_steal_all (h);
842 g_assert_cmpint (destroy_counter, ==, 0);
843 g_assert_cmpint (destroy_key_counter, ==, 0);
845 g_hash_table_insert (h, "abc", "ABC");
846 g_hash_table_insert (h, "cde", "CDE");
847 g_hash_table_insert (h, "xyz", "XYZ");
849 res = g_hash_table_steal (h, "nosuchkey");
851 g_assert_cmpint (destroy_counter, ==, 0);
852 g_assert_cmpint (destroy_key_counter, ==, 0);
854 res = g_hash_table_steal (h, "xyz");
856 g_assert_cmpint (destroy_counter, ==, 0);
857 g_assert_cmpint (destroy_key_counter, ==, 0);
859 g_hash_table_remove_all (h);
860 g_assert_cmpint (destroy_counter, ==, 2);
861 g_assert_cmpint (destroy_key_counter, ==, 2);
863 g_hash_table_remove_all (h);
864 g_assert_cmpint (destroy_counter, ==, 2);
865 g_assert_cmpint (destroy_key_counter, ==, 2);
867 g_hash_table_unref (h);
870 GHashTable *recursive_destruction_table = NULL;
872 recursive_value_destroy (gpointer value)
876 if (recursive_destruction_table)
877 g_hash_table_remove (recursive_destruction_table, value);
881 test_recursive_remove_all_subprocess (void)
885 h = g_hash_table_new_full (g_str_hash, g_str_equal, key_destroy, recursive_value_destroy);
886 recursive_destruction_table = h;
888 /* Add more items compared to test_remove_all, as it would not fail otherwise. */
889 g_hash_table_insert (h, "abc", "cde");
890 g_hash_table_insert (h, "cde", "fgh");
891 g_hash_table_insert (h, "fgh", "ijk");
892 g_hash_table_insert (h, "ijk", "lmn");
893 g_hash_table_insert (h, "lmn", "opq");
894 g_hash_table_insert (h, "opq", "rst");
895 g_hash_table_insert (h, "rst", "uvw");
896 g_hash_table_insert (h, "uvw", "xyz");
897 g_hash_table_insert (h, "xyz", "abc");
900 destroy_key_counter = 0;
902 g_hash_table_remove_all (h);
903 g_assert_cmpint (destroy_counter, ==, 9);
904 g_assert_cmpint (destroy_key_counter, ==, 9);
906 g_hash_table_unref (h);
910 test_recursive_remove_all (void)
912 g_test_trap_subprocess ("/hash/recursive-remove-all/subprocess", 1000000,
913 G_TEST_SUBPROCESS_DEFAULT);
914 g_test_trap_assert_passed ();
923 hash_func (gconstpointer key)
925 const RefCountedKey *rkey = key;
927 return g_str_hash (rkey->key);
931 eq_func (gconstpointer a, gconstpointer b)
933 const RefCountedKey *aa = a;
934 const RefCountedKey *bb = b;
936 return g_strcmp0 (aa->key, bb->key) == 0;
940 key_unref (gpointer data)
942 RefCountedKey *key = data;
944 g_assert (key->ref_count > 0);
948 if (key->ref_count == 0)
952 static RefCountedKey *
953 key_ref (RefCountedKey *key)
960 static RefCountedKey *
961 key_new (const gchar *key)
965 rkey = g_new (RefCountedKey, 1);
974 set_ref_hash_test (void)
980 h = g_hash_table_new_full (hash_func, eq_func, key_unref, key_unref);
982 key1 = key_new ("a");
983 key2 = key_new ("a");
985 g_assert_cmpint (key1->ref_count, ==, 1);
986 g_assert_cmpint (key2->ref_count, ==, 1);
988 g_hash_table_insert (h, key_ref (key1), key_ref (key1));
990 g_assert_cmpint (key1->ref_count, ==, 3);
991 g_assert_cmpint (key2->ref_count, ==, 1);
993 g_hash_table_replace (h, key_ref (key2), key_ref (key2));
995 g_assert_cmpint (key1->ref_count, ==, 1);
996 g_assert_cmpint (key2->ref_count, ==, 3);
998 g_hash_table_remove (h, key1);
1000 g_assert_cmpint (key1->ref_count, ==, 1);
1001 g_assert_cmpint (key2->ref_count, ==, 1);
1003 g_hash_table_unref (h);
1009 static GHashTable *global_hashtable;
1016 static GPtrArray *fake_free_data;
1019 fake_free (gpointer dead)
1023 for (i = 0; i < fake_free_data->len; i++)
1025 FakeFreeData *ffd = g_ptr_array_index (fake_free_data, i);
1027 if (ffd->string == (gchar *) dead)
1029 g_assert (!ffd->freed);
1035 g_assert_not_reached ();
1039 value_destroy_insert (gpointer value)
1041 g_hash_table_remove_all (global_hashtable);
1045 test_destroy_modify (void)
1050 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=650459");
1052 fake_free_data = g_ptr_array_new ();
1054 global_hashtable = g_hash_table_new_full (g_str_hash, g_str_equal, fake_free, value_destroy_insert);
1056 ffd = g_new0 (FakeFreeData, 1);
1057 ffd->string = g_strdup ("a");
1058 g_ptr_array_add (fake_free_data, ffd);
1059 g_hash_table_insert (global_hashtable, ffd->string, "b");
1061 ffd = g_new0 (FakeFreeData, 1);
1062 ffd->string = g_strdup ("c");
1063 g_ptr_array_add (fake_free_data, ffd);
1064 g_hash_table_insert (global_hashtable, ffd->string, "d");
1066 ffd = g_new0 (FakeFreeData, 1);
1067 ffd->string = g_strdup ("e");
1068 g_ptr_array_add (fake_free_data, ffd);
1069 g_hash_table_insert (global_hashtable, ffd->string, "f");
1071 ffd = g_new0 (FakeFreeData, 1);
1072 ffd->string = g_strdup ("g");
1073 g_ptr_array_add (fake_free_data, ffd);
1074 g_hash_table_insert (global_hashtable, ffd->string, "h");
1076 ffd = g_new0 (FakeFreeData, 1);
1077 ffd->string = g_strdup ("h");
1078 g_ptr_array_add (fake_free_data, ffd);
1079 g_hash_table_insert (global_hashtable, ffd->string, "k");
1081 ffd = g_new0 (FakeFreeData, 1);
1082 ffd->string = g_strdup ("a");
1083 g_ptr_array_add (fake_free_data, ffd);
1084 g_hash_table_insert (global_hashtable, ffd->string, "c");
1086 g_hash_table_remove (global_hashtable, "c");
1088 /* that removed everything... */
1089 for (i = 0; i < fake_free_data->len; i++)
1091 ffd = g_ptr_array_index (fake_free_data, i);
1093 g_assert (ffd->freed);
1094 g_free (ffd->string);
1098 g_ptr_array_unref (fake_free_data);
1100 /* ... so this is a no-op */
1101 g_hash_table_remove (global_hashtable, "e");
1103 g_hash_table_unref (global_hashtable);
1107 find_str (gpointer key, gpointer value, gpointer data)
1109 return g_str_equal (key, data);
1118 hash = g_hash_table_new (g_str_hash, g_str_equal);
1120 g_hash_table_insert (hash, "a", "A");
1121 g_hash_table_insert (hash, "b", "B");
1122 g_hash_table_insert (hash, "c", "C");
1123 g_hash_table_insert (hash, "d", "D");
1124 g_hash_table_insert (hash, "e", "E");
1125 g_hash_table_insert (hash, "f", "F");
1127 value = g_hash_table_find (hash, find_str, "a");
1128 g_assert_cmpstr (value, ==, "A");
1130 value = g_hash_table_find (hash, find_str, "b");
1131 g_assert_cmpstr (value, ==, "B");
1133 value = g_hash_table_find (hash, find_str, "c");
1134 g_assert_cmpstr (value, ==, "C");
1136 value = g_hash_table_find (hash, find_str, "d");
1137 g_assert_cmpstr (value, ==, "D");
1139 value = g_hash_table_find (hash, find_str, "e");
1140 g_assert_cmpstr (value, ==, "E");
1142 value = g_hash_table_find (hash, find_str, "f");
1143 g_assert_cmpstr (value, ==, "F");
1145 value = g_hash_table_find (hash, find_str, "0");
1146 g_assert (value == NULL);
1148 g_hash_table_unref (hash);
1151 gboolean seen_key[6];
1154 foreach_func (gpointer key, gpointer value, gpointer data)
1156 seen_key[((char*)key)[0] - 'a'] = TRUE;
1165 hash = g_hash_table_new (g_str_hash, g_str_equal);
1167 g_hash_table_insert (hash, "a", "A");
1168 g_hash_table_insert (hash, "b", "B");
1169 g_hash_table_insert (hash, "c", "C");
1170 g_hash_table_insert (hash, "d", "D");
1171 g_hash_table_insert (hash, "e", "E");
1172 g_hash_table_insert (hash, "f", "F");
1174 for (i = 0; i < 6; i++)
1175 seen_key[i] = FALSE;
1177 g_hash_table_foreach (hash, foreach_func, NULL);
1179 for (i = 0; i < 6; i++)
1180 g_assert (seen_key[i]);
1182 g_hash_table_unref (hash);
1186 foreach_steal_func (gpointer key, gpointer value, gpointer data)
1188 GHashTable *hash2 = data;
1190 if (strstr ("ace", (gchar*)key))
1192 g_hash_table_insert (hash2, key, value);
1201 test_foreach_steal (void)
1206 hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1207 hash2 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1209 g_hash_table_insert (hash, g_strdup ("a"), g_strdup ("A"));
1210 g_hash_table_insert (hash, g_strdup ("b"), g_strdup ("B"));
1211 g_hash_table_insert (hash, g_strdup ("c"), g_strdup ("C"));
1212 g_hash_table_insert (hash, g_strdup ("d"), g_strdup ("D"));
1213 g_hash_table_insert (hash, g_strdup ("e"), g_strdup ("E"));
1214 g_hash_table_insert (hash, g_strdup ("f"), g_strdup ("F"));
1216 g_hash_table_foreach_steal (hash, foreach_steal_func, hash2);
1218 g_assert_cmpint (g_hash_table_size (hash), ==, 3);
1219 g_assert_cmpint (g_hash_table_size (hash2), ==, 3);
1221 g_assert_cmpstr (g_hash_table_lookup (hash2, "a"), ==, "A");
1222 g_assert_cmpstr (g_hash_table_lookup (hash, "b"), ==, "B");
1223 g_assert_cmpstr (g_hash_table_lookup (hash2, "c"), ==, "C");
1224 g_assert_cmpstr (g_hash_table_lookup (hash, "d"), ==, "D");
1225 g_assert_cmpstr (g_hash_table_lookup (hash2, "e"), ==, "E");
1226 g_assert_cmpstr (g_hash_table_lookup (hash, "f"), ==, "F");
1228 g_hash_table_unref (hash);
1229 g_hash_table_unref (hash2);
1232 /* Test g_hash_table_steal_extended() works properly with existing and
1233 * non-existing keys. */
1235 test_steal_extended (void)
1238 gchar *stolen_key = NULL, *stolen_value = NULL;
1240 hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1242 g_hash_table_insert (hash, g_strdup ("a"), g_strdup ("A"));
1243 g_hash_table_insert (hash, g_strdup ("b"), g_strdup ("B"));
1244 g_hash_table_insert (hash, g_strdup ("c"), g_strdup ("C"));
1245 g_hash_table_insert (hash, g_strdup ("d"), g_strdup ("D"));
1246 g_hash_table_insert (hash, g_strdup ("e"), g_strdup ("E"));
1247 g_hash_table_insert (hash, g_strdup ("f"), g_strdup ("F"));
1249 g_assert_true (g_hash_table_steal_extended (hash, "a",
1250 (gpointer *) &stolen_key,
1251 (gpointer *) &stolen_value));
1252 g_assert_cmpstr (stolen_key, ==, "a");
1253 g_assert_cmpstr (stolen_value, ==, "A");
1254 g_clear_pointer (&stolen_key, g_free);
1255 g_clear_pointer (&stolen_value, g_free);
1257 g_assert_cmpuint (g_hash_table_size (hash), ==, 5);
1259 g_assert_false (g_hash_table_steal_extended (hash, "a",
1260 (gpointer *) &stolen_key,
1261 (gpointer *) &stolen_value));
1262 g_assert_null (stolen_key);
1263 g_assert_null (stolen_value);
1265 g_assert_false (g_hash_table_steal_extended (hash, "never a key",
1266 (gpointer *) &stolen_key,
1267 (gpointer *) &stolen_value));
1268 g_assert_null (stolen_key);
1269 g_assert_null (stolen_value);
1271 g_assert_cmpuint (g_hash_table_size (hash), ==, 5);
1273 g_hash_table_unref (hash);
1276 /* Test that passing %NULL to the optional g_hash_table_steal_extended()
1277 * arguments works. */
1279 test_steal_extended_optional (void)
1282 const gchar *stolen_key = NULL, *stolen_value = NULL;
1284 hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
1286 g_hash_table_insert (hash, "b", "B");
1287 g_hash_table_insert (hash, "c", "C");
1288 g_hash_table_insert (hash, "d", "D");
1289 g_hash_table_insert (hash, "e", "E");
1290 g_hash_table_insert (hash, "f", "F");
1292 g_assert_true (g_hash_table_steal_extended (hash, "b",
1293 (gpointer *) &stolen_key,
1295 g_assert_cmpstr (stolen_key, ==, "b");
1297 g_assert_cmpuint (g_hash_table_size (hash), ==, 4);
1299 g_assert_false (g_hash_table_steal_extended (hash, "b",
1300 (gpointer *) &stolen_key,
1302 g_assert_null (stolen_key);
1304 g_assert_true (g_hash_table_steal_extended (hash, "c",
1306 (gpointer *) &stolen_value));
1307 g_assert_cmpstr (stolen_value, ==, "C");
1309 g_assert_cmpuint (g_hash_table_size (hash), ==, 3);
1311 g_assert_false (g_hash_table_steal_extended (hash, "c",
1313 (gpointer *) &stolen_value));
1314 g_assert_null (stolen_value);
1316 g_assert_true (g_hash_table_steal_extended (hash, "d", NULL, NULL));
1318 g_assert_cmpuint (g_hash_table_size (hash), ==, 2);
1320 g_assert_false (g_hash_table_steal_extended (hash, "d", NULL, NULL));
1322 g_assert_cmpuint (g_hash_table_size (hash), ==, 2);
1324 g_hash_table_unref (hash);
1327 /* Test g_hash_table_lookup_extended() works with its optional parameters
1328 * sometimes set to %NULL. */
1330 test_lookup_extended (void)
1333 const gchar *original_key = NULL, *value = NULL;
1335 hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1337 g_hash_table_insert (hash, g_strdup ("a"), g_strdup ("A"));
1338 g_hash_table_insert (hash, g_strdup ("b"), g_strdup ("B"));
1339 g_hash_table_insert (hash, g_strdup ("c"), g_strdup ("C"));
1340 g_hash_table_insert (hash, g_strdup ("d"), g_strdup ("D"));
1341 g_hash_table_insert (hash, g_strdup ("e"), g_strdup ("E"));
1342 g_hash_table_insert (hash, g_strdup ("f"), g_strdup ("F"));
1344 g_assert_true (g_hash_table_lookup_extended (hash, "a",
1345 (gpointer *) &original_key,
1346 (gpointer *) &value));
1347 g_assert_cmpstr (original_key, ==, "a");
1348 g_assert_cmpstr (value, ==, "A");
1350 g_assert_true (g_hash_table_lookup_extended (hash, "b",
1352 (gpointer *) &value));
1353 g_assert_cmpstr (value, ==, "B");
1355 g_assert_true (g_hash_table_lookup_extended (hash, "c",
1356 (gpointer *) &original_key,
1358 g_assert_cmpstr (original_key, ==, "c");
1360 g_assert_true (g_hash_table_lookup_extended (hash, "d", NULL, NULL));
1362 g_assert_false (g_hash_table_lookup_extended (hash, "not a key",
1363 (gpointer *) &original_key,
1364 (gpointer *) &value));
1365 g_assert_null (original_key);
1366 g_assert_null (value);
1368 g_assert_false (g_hash_table_lookup_extended (hash, "not a key",
1370 (gpointer *) &value));
1371 g_assert_null (value);
1373 g_assert_false (g_hash_table_lookup_extended (hash, "not a key",
1374 (gpointer *) &original_key,
1376 g_assert_null (original_key);
1378 g_assert_false (g_hash_table_lookup_extended (hash, "not a key", NULL, NULL));
1380 g_hash_table_unref (hash);
1384 inc_state (gpointer user_data)
1386 int *state = user_data;
1387 g_assert_cmpint (*state, ==, 0);
1392 test_new_similar (void)
1399 hash1 = g_hash_table_new_full (g_str_hash, g_str_equal,
1402 g_hash_table_insert (hash1,
1405 g_assert_true (g_hash_table_lookup (hash1, "test") == &state1);
1407 hash2 = g_hash_table_new_similar (hash1);
1409 g_assert_true (g_hash_table_lookup (hash1, "test") == &state1);
1410 g_assert_null (g_hash_table_lookup (hash2, "test"));
1413 g_hash_table_insert (hash2, g_strdup ("test"), &state2);
1414 g_assert_true (g_hash_table_lookup (hash2, "test") == &state2);
1415 g_hash_table_remove (hash2, "test");
1416 g_assert_cmpint (state2, ==, 1);
1418 g_assert_cmpint (state1, ==, 0);
1419 g_hash_table_remove (hash1, "test");
1420 g_assert_cmpint (state1, ==, 1);
1422 g_hash_table_unref (hash1);
1423 g_hash_table_unref (hash2);
1432 gint noccupied; /* nnodes + tombstones */
1434 guint have_big_keys : 1;
1435 guint have_big_values : 1;
1441 GHashFunc hash_func;
1442 GEqualFunc key_equal_func;
1443 gint ref_count; /* (atomic) */
1445 #ifndef G_DISABLE_ASSERT
1448 GDestroyNotify key_destroy_func;
1449 GDestroyNotify value_destroy_func;
1453 count_keys (GHashTable *h, gint *unused, gint *occupied, gint *tombstones)
1460 for (i = 0; i < h->size; i++)
1462 if (h->hashes[i] == 0)
1464 else if (h->hashes[i] == 1)
1471 #define BIG_ENTRY_SIZE (SIZEOF_VOID_P)
1472 #define SMALL_ENTRY_SIZE (SIZEOF_INT)
1474 #if SMALL_ENTRY_SIZE < BIG_ENTRY_SIZE
1475 # define USE_SMALL_ARRAYS
1479 fetch_key_or_value (gpointer a, guint index, gboolean is_big)
1481 #ifdef USE_SMALL_ARRAYS
1482 return is_big ? *(((gpointer *) a) + index) : GUINT_TO_POINTER (*(((guint *) a) + index));
1484 return *(((gpointer *) a) + index);
1489 check_data (GHashTable *h)
1493 for (i = 0; i < h->size; i++)
1495 if (h->hashes[i] >= 2)
1497 g_assert_cmpint (h->hashes[i], ==, h->hash_func (fetch_key_or_value (h->keys, i, h->have_big_keys)));
1503 check_consistency (GHashTable *h)
1509 count_keys (h, &unused, &occupied, &tombstones);
1511 g_assert_cmpint (occupied, ==, h->nnodes);
1512 g_assert_cmpint (occupied + tombstones, ==, h->noccupied);
1513 g_assert_cmpint (occupied + tombstones + unused, ==, h->size);
1519 check_counts (GHashTable *h, gint occupied, gint tombstones)
1521 g_assert_cmpint (occupied, ==, h->nnodes);
1522 g_assert_cmpint (occupied + tombstones, ==, h->noccupied);
1526 trivial_key_destroy (gpointer key)
1531 test_internal_consistency (void)
1535 h = g_hash_table_new_full (g_str_hash, g_str_equal, trivial_key_destroy, NULL);
1537 check_counts (h, 0, 0);
1538 check_consistency (h);
1540 g_hash_table_insert (h, "a", "A");
1541 g_hash_table_insert (h, "b", "B");
1542 g_hash_table_insert (h, "c", "C");
1543 g_hash_table_insert (h, "d", "D");
1544 g_hash_table_insert (h, "e", "E");
1545 g_hash_table_insert (h, "f", "F");
1547 check_counts (h, 6, 0);
1548 check_consistency (h);
1550 g_hash_table_remove (h, "a");
1551 check_counts (h, 5, 1);
1552 check_consistency (h);
1554 g_hash_table_remove (h, "b");
1555 check_counts (h, 4, 2);
1556 check_consistency (h);
1558 g_hash_table_insert (h, "c", "c");
1559 check_counts (h, 4, 2);
1560 check_consistency (h);
1562 g_hash_table_insert (h, "a", "A");
1563 check_counts (h, 5, 1);
1564 check_consistency (h);
1566 g_hash_table_remove_all (h);
1567 check_counts (h, 0, 0);
1568 check_consistency (h);
1570 g_hash_table_unref (h);
1574 my_key_free (gpointer v)
1577 g_assert (s[0] != 'x');
1583 my_value_free (gpointer v)
1586 g_assert (s[0] != 'y');
1592 test_iter_replace (void)
1595 GHashTableIter iter;
1599 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=662544");
1601 h = g_hash_table_new_full (g_str_hash, g_str_equal, my_key_free, my_value_free);
1603 g_hash_table_insert (h, g_strdup ("A"), g_strdup ("a"));
1604 g_hash_table_insert (h, g_strdup ("B"), g_strdup ("b"));
1605 g_hash_table_insert (h, g_strdup ("C"), g_strdup ("c"));
1607 g_hash_table_iter_init (&iter, h);
1609 while (g_hash_table_iter_next (&iter, &k, &v))
1612 g_assert (g_ascii_islower (s[0]));
1613 g_hash_table_iter_replace (&iter, g_strdup (k));
1616 g_hash_table_unref (h);
1620 replace_first_character (gchar *string)
1626 test_set_insert_corruption (void)
1628 GHashTable *hash_table =
1629 g_hash_table_new_full (g_str_hash, g_str_equal,
1630 (GDestroyNotify) replace_first_character, NULL);
1631 GHashTableIter iter;
1634 gpointer key, value;
1636 g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=692815");
1638 g_hash_table_insert (hash_table, a, a);
1639 g_assert (g_hash_table_contains (hash_table, "foo"));
1641 g_hash_table_insert (hash_table, b, b);
1643 g_assert_cmpuint (g_hash_table_size (hash_table), ==, 1);
1644 g_hash_table_iter_init (&iter, hash_table);
1645 if (!g_hash_table_iter_next (&iter, &key, &value))
1646 g_assert_not_reached();
1648 /* per the documentation to g_hash_table_insert(), 'b' has now been freed,
1649 * and the sole key in 'hash_table' should be 'a'.
1651 g_assert (key != b);
1652 g_assert (key == a);
1654 g_assert_cmpstr (b, ==, "boo");
1656 /* g_hash_table_insert() also says that the value should now be 'b',
1657 * which is probably not what the caller intended but is precisely what they
1660 g_assert (value == b);
1662 /* even though the hash has now been de-set-ified: */
1663 g_assert (g_hash_table_contains (hash_table, "foo"));
1665 g_hash_table_unref (hash_table);
1669 test_set_to_strv (void)
1675 set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1676 g_hash_table_add (set, g_strdup ("xyz"));
1677 g_hash_table_add (set, g_strdup ("xyz"));
1678 g_hash_table_add (set, g_strdup ("abc"));
1679 strv = (gchar **) g_hash_table_get_keys_as_array (set, &n);
1680 g_hash_table_steal_all (set);
1681 g_hash_table_unref (set);
1682 g_assert_cmpint (n, ==, 2);
1683 n = g_strv_length (strv);
1684 g_assert_cmpint (n, ==, 2);
1685 if (g_str_equal (strv[0], "abc"))
1686 g_assert_cmpstr (strv[1], ==, "xyz");
1689 g_assert_cmpstr (strv[0], ==, "xyz");
1690 g_assert_cmpstr (strv[1], ==, "abc");
1696 test_set_get_keys_as_ptr_array (void)
1701 set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1702 g_hash_table_add (set, g_strdup ("xyz"));
1703 g_hash_table_add (set, g_strdup ("xyz"));
1704 g_hash_table_add (set, g_strdup ("abc"));
1706 array = g_hash_table_get_keys_as_ptr_array (set);
1707 g_hash_table_steal_all (set);
1708 g_hash_table_unref (set);
1709 g_ptr_array_set_free_func (array, g_free);
1711 g_assert_cmpint (array->len, ==, 2);
1712 g_ptr_array_add (array, NULL);
1715 g_strv_equal ((const gchar * const[]) { "xyz", "abc", NULL },
1716 (const gchar * const*) array->pdata) ||
1717 g_strv_equal ((const gchar * const[]) { "abc", "xyz", NULL },
1718 (const gchar * const*) array->pdata)
1721 g_clear_pointer (&array, g_ptr_array_unref);
1725 test_set_get_values_as_ptr_array (void)
1730 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1731 g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (0));
1732 g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (1));
1733 g_hash_table_insert (table, g_strdup ("abc"), GUINT_TO_POINTER (2));
1735 array = g_hash_table_get_values_as_ptr_array (table);
1736 g_clear_pointer (&table, g_hash_table_unref);
1738 g_assert_cmpint (array->len, ==, 2);
1739 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (1), NULL));
1740 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (2), NULL));
1743 memcmp ((gpointer []) { GUINT_TO_POINTER (1), GUINT_TO_POINTER (2) },
1744 array->pdata, array->len * sizeof (gpointer)) == 0 ||
1745 memcmp ((gpointer []) { GUINT_TO_POINTER (2), GUINT_TO_POINTER (1) },
1746 array->pdata, array->len * sizeof (gpointer)) == 0
1749 g_clear_pointer (&array, g_ptr_array_unref);
1753 test_steal_all_keys (void)
1758 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1759 g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (0));
1760 g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (1));
1761 g_hash_table_insert (table, g_strdup ("abc"), GUINT_TO_POINTER (2));
1763 array = g_hash_table_steal_all_keys (table);
1764 g_assert_cmpuint (g_hash_table_size (table), ==, 0);
1766 g_hash_table_insert (table, g_strdup ("do-not-leak-me"), GUINT_TO_POINTER (5));
1767 g_clear_pointer (&table, g_hash_table_unref);
1769 g_assert_cmpint (array->len, ==, 2);
1770 g_ptr_array_add (array, NULL);
1773 g_strv_equal ((const gchar * const[]) { "xyz", "abc", NULL },
1774 (const gchar * const*) array->pdata) ||
1775 g_strv_equal ((const gchar * const[]) { "abc", "xyz", NULL },
1776 (const gchar * const*) array->pdata)
1779 g_clear_pointer (&array, g_ptr_array_unref);
1781 table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
1782 g_hash_table_insert (table, GUINT_TO_POINTER (0), g_strdup ("xyz"));
1783 g_hash_table_insert (table, GUINT_TO_POINTER (1), g_strdup ("xyz"));
1784 g_hash_table_insert (table, GUINT_TO_POINTER (2), g_strdup ("abc"));
1786 array = g_hash_table_steal_all_keys (table);
1787 g_assert_cmpuint (g_hash_table_size (table), ==, 0);
1789 g_hash_table_insert (table, GUINT_TO_POINTER (5), g_strdup ("do-not-leak-me"));
1790 g_clear_pointer (&table, g_hash_table_unref);
1792 g_assert_cmpint (array->len, ==, 3);
1793 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (0), NULL));
1794 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (1), NULL));
1795 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (2), NULL));
1797 g_clear_pointer (&array, g_ptr_array_unref);
1801 test_steal_all_values (void)
1806 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1807 g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (0));
1808 g_hash_table_insert (table, g_strdup ("xyz"), GUINT_TO_POINTER (1));
1809 g_hash_table_insert (table, g_strdup ("abc"), GUINT_TO_POINTER (2));
1811 array = g_hash_table_steal_all_values (table);
1812 g_assert_cmpuint (g_hash_table_size (table), ==, 0);
1814 g_hash_table_insert (table, g_strdup ("do-not-leak-me"), GUINT_TO_POINTER (5));
1815 g_clear_pointer (&table, g_hash_table_unref);
1817 g_assert_cmpint (array->len, ==, 2);
1818 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (1), NULL));
1819 g_assert_true (g_ptr_array_find (array, GUINT_TO_POINTER (2), NULL));
1822 memcmp ((gpointer []) { GUINT_TO_POINTER (1), GUINT_TO_POINTER (2) },
1823 array->pdata, array->len * sizeof (gpointer)) == 0 ||
1824 memcmp ((gpointer []) { GUINT_TO_POINTER (2), GUINT_TO_POINTER (1) },
1825 array->pdata, array->len * sizeof (gpointer)) == 0
1828 g_clear_pointer (&array, g_ptr_array_unref);
1830 table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
1831 g_hash_table_insert (table, GUINT_TO_POINTER (0), g_strdup ("xyz"));
1832 g_hash_table_insert (table, GUINT_TO_POINTER (1), g_strdup ("foo"));
1833 g_hash_table_insert (table, GUINT_TO_POINTER (2), g_strdup ("abc"));
1835 array = g_hash_table_steal_all_values (table);
1836 g_assert_cmpuint (g_hash_table_size (table), ==, 0);
1838 g_hash_table_insert (table, GUINT_TO_POINTER (5), g_strdup ("do-not-leak-me"));
1839 g_clear_pointer (&table, g_hash_table_unref);
1841 g_assert_cmpint (array->len, ==, 3);
1843 g_ptr_array_find_with_equal_func (array, "xyz", g_str_equal, NULL));
1845 g_ptr_array_find_with_equal_func (array, "foo", g_str_equal, NULL));
1847 g_ptr_array_find_with_equal_func (array, "abc", g_str_equal, NULL));
1849 g_clear_pointer (&array, g_ptr_array_unref);
1877 gdouble r, min, max;
1884 q = g_spaced_primes_closest (p);
1885 g_assert (is_prime (q));
1886 if (p == 1) continue;
1888 r = q / (gdouble) p;
1893 g_assert_cmpfloat (1.3, <, min);
1894 g_assert_cmpfloat (max, <, 2.0);
1898 main (int argc, char *argv[])
1900 g_test_init (&argc, &argv, NULL);
1902 g_test_add_func ("/hash/misc", test_hash_misc);
1903 g_test_add_data_func ("/hash/one", GINT_TO_POINTER (TRUE), second_hash_test);
1904 g_test_add_data_func ("/hash/honeyman", GINT_TO_POINTER (FALSE), second_hash_test);
1905 g_test_add_func ("/hash/direct", direct_hash_test);
1906 g_test_add_func ("/hash/direct2", direct_hash_test2);
1907 g_test_add_func ("/hash/int", int_hash_test);
1908 g_test_add_func ("/hash/int64", int64_hash_test);
1909 g_test_add_func ("/hash/int64/collisions", int64_hash_collision_test);
1910 g_test_add_func ("/hash/double", double_hash_test);
1911 g_test_add_func ("/hash/double/collisions", double_hash_collision_test);
1912 g_test_add_func ("/hash/string", string_hash_test);
1913 g_test_add_func ("/hash/set", set_hash_test);
1914 g_test_add_func ("/hash/set-ref", set_ref_hash_test);
1915 g_test_add_func ("/hash/ref", test_hash_ref);
1916 g_test_add_func ("/hash/remove-all", test_remove_all);
1917 g_test_add_func ("/hash/recursive-remove-all", test_recursive_remove_all);
1918 g_test_add_func ("/hash/recursive-remove-all/subprocess", test_recursive_remove_all_subprocess);
1919 g_test_add_func ("/hash/find", test_find);
1920 g_test_add_func ("/hash/foreach", test_foreach);
1921 g_test_add_func ("/hash/foreach-steal", test_foreach_steal);
1922 g_test_add_func ("/hash/steal-extended", test_steal_extended);
1923 g_test_add_func ("/hash/steal-extended/optional", test_steal_extended_optional);
1924 g_test_add_func ("/hash/steal-all-keys", test_steal_all_keys);
1925 g_test_add_func ("/hash/steal-all-values", test_steal_all_values);
1926 g_test_add_func ("/hash/lookup-extended", test_lookup_extended);
1927 g_test_add_func ("/hash/new-similar", test_new_similar);
1929 /* tests for individual bugs */
1930 g_test_add_func ("/hash/lookup-null-key", test_lookup_null_key);
1931 g_test_add_func ("/hash/destroy-modify", test_destroy_modify);
1932 g_test_add_func ("/hash/consistency", test_internal_consistency);
1933 g_test_add_func ("/hash/iter-replace", test_iter_replace);
1934 g_test_add_func ("/hash/set-insert-corruption", test_set_insert_corruption);
1935 g_test_add_func ("/hash/set-to-strv", test_set_to_strv);
1936 g_test_add_func ("/hash/get-keys-as-ptr-array", test_set_get_keys_as_ptr_array);
1937 g_test_add_func ("/hash/get-values-as-ptr-array", test_set_get_values_as_ptr_array);
1938 g_test_add_func ("/hash/primes", test_primes);
1940 return g_test_run ();