1 /* Test of persistent hash array mapped trie implementation.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Marc Nieper-Wißkirchen <marc@nieper-wisskirchen.de>, 2021. */
32 entry_value (const void *elt
)
34 return ((Element
*) elt
)->val
;
38 hash_element (const void *elt
)
40 return entry_value (elt
) & ~3; /* We drop the last bits so that we
41 can test hash collisions. */
45 compare_element (const void *elt1
, const void *elt2
)
47 return entry_value (elt1
) == entry_value (elt2
);
51 free_element (Hamt_entry
*elt
)
59 Element
*elt
= XMALLOC (Element
);
61 return hamt_element (&elt
->entry
);
65 test_hamt_create (void)
67 return hamt_create (hash_element
, compare_element
, free_element
);
75 proc (Hamt_entry
*elt
, void *data
)
79 sum
+= entry_value (elt
);
93 Hamt
*hamt
= test_hamt_create ();
95 Hamt_entry
*x5
= make_element (5);
97 Hamt
*hamt1
= hamt_insert (hamt
, &p
);
98 ASSERT (hamt1
!= hamt
);
99 ASSERT (hamt_lookup (hamt
, x5
) == NULL
);
100 ASSERT (hamt_lookup (hamt1
, x5
) == x5
);
103 Hamt_entry
*y5
= make_element (5);
105 Hamt
*hamt2
= hamt_insert (hamt1
, &p
);
106 ASSERT (hamt2
== hamt1
);
108 ASSERT (hamt_lookup (hamt1
, y5
) == x5
);
111 hamt
= hamt_replace (hamt1
, &p
);
113 ASSERT (hamt_lookup (hamt
, y5
) == y5
);
115 y5
= make_element (5);
117 Hamt_entry
*z37
= make_element (37);
119 hamt2
= hamt_insert (hamt1
, &p
);
120 ASSERT (hamt2
!= hamt1
);
122 ASSERT (hamt_lookup (hamt1
, z37
) == NULL
);
123 ASSERT (hamt_lookup (hamt2
, z37
) == z37
);
126 ASSERT (hamt_lookup (hamt2
, x5
) == x5
);
127 ASSERT (hamt_lookup (hamt2
, z37
) == z37
);
129 ASSERT (hamt_do_while (hamt2
, proc
, &flag
) == 2);
131 ASSERT (hamt_do_while (hamt2
, proc
, NULL
) == 1);
135 hamt1
= hamt_remove (hamt2
, &p
);
136 ASSERT (hamt1
!= hamt2
);
139 ASSERT (hamt_lookup (hamt1
, x5
) == NULL
);
140 ASSERT (hamt_lookup (hamt2
, x5
) == x5
);
143 Hamt_entry
*x4
= make_element (4);
144 hamt1
= hamt_insert (hamt2
, &x4
);
146 Hamt_entry
*x6
= make_element (6);
147 hamt2
= hamt_insert (hamt1
, &x6
);
149 ASSERT (hamt_do_while (hamt2
, proc
, &flag
) == 4);
152 hamt1
= hamt_remove (hamt2
, &x4
);
154 ASSERT (hamt_do_while (hamt2
, proc
, &flag
) == 4);
157 ASSERT (hamt_do_while (hamt1
, proc
, &flag
) == 3);
166 true_processor (_GL_ATTRIBUTE_MAYBE_UNUSED Hamt_entry
*elt
,
167 _GL_ATTRIBUTE_MAYBE_UNUSED
void *data
)
173 element_count (Hamt
*hamt
)
175 return hamt_do_while (hamt
, true_processor
, NULL
);
178 struct find_values_context
186 find_values_processor (Hamt_entry
*entry
, void *data
)
188 struct find_values_context
*ctx
= data
;
189 int val
= entry_value (entry
);
190 for (size_t i
= 0; i
< ctx
->n
; ++i
)
191 if (ctx
->elts
[i
] == val
&& !ctx
->found
[i
])
193 ctx
->found
[i
] = true;
200 find_values (Hamt
*hamt
, size_t n
, int *elts
)
202 bool *found
= XCALLOC (n
, bool);
203 struct find_values_context ctx
= {n
, elts
, found
};
204 bool res
= hamt_do_while (hamt
, find_values_processor
, &ctx
) == n
;
210 insert_values (Hamt
**hamt
, size_t n
, int *elts
, bool destructive
)
213 for (size_t i
= 0; i
< n
; ++i
)
215 Hamt_entry
*p
= make_element (elts
[i
]);
219 if (hamt_insert_x (*hamt
, &p
))
226 Hamt
*new_hamt
= hamt_insert (*hamt
, &p
);
227 if (new_hamt
!= *hamt
)
243 replace_values (Hamt
**hamt
, size_t n
, int *elts
, bool destructive
)
246 for (size_t i
= 0; i
< n
; ++i
)
248 Hamt_entry
*p
= make_element (elts
[i
]);
251 if (hamt_replace_x (*hamt
, p
))
256 Hamt
*new_hamt
= hamt_replace (*hamt
, &p
);
267 remove_values (Hamt
**hamt
, size_t n
, int *elts
, bool destructive
)
270 for (size_t i
= 0; i
< n
; ++i
)
272 Hamt_entry
*p
= make_element (elts
[i
]);
276 if (hamt_remove_x (*hamt
, p
))
281 Hamt
*new_hamt
= hamt_remove (*hamt
, &p
);
282 if (new_hamt
!= *hamt
)
294 static int val_array1
[10] = {1, 2, 3, 4, 33, 34, 35, 36, 1024, 1025};
295 static int val_array2
[10] = {1, 2, 34, 36, 1025, 32768, 32769, 32770, 32771,
299 test_functional_update (void)
301 Hamt
*hamt
= test_hamt_create ();
303 ASSERT (insert_values (&hamt
, 10, val_array1
, false) == 10);
304 ASSERT (element_count (hamt
) == 10);
305 ASSERT (find_values (hamt
, 10, val_array1
));
306 ASSERT (insert_values (&hamt
, 10, val_array2
, false) == 5);
307 ASSERT (element_count (hamt
) == 15);
308 ASSERT (remove_values (&hamt
, 10, val_array1
, false) == 10);
309 ASSERT (element_count (hamt
) == 5);
310 ASSERT (remove_values (&hamt
, 10, val_array2
, false) == 5);
311 ASSERT (element_count (hamt
) == 0);
313 ASSERT (replace_values (&hamt
, 10, val_array1
, false) == 0);
314 ASSERT (element_count (hamt
) == 10);
315 ASSERT (find_values (hamt
, 10, val_array1
));
316 ASSERT (replace_values (&hamt
, 10, val_array2
, false) == 5);
317 ASSERT (element_count (hamt
) == 15);
323 test_destructive_update (void)
325 Hamt
*hamt
= test_hamt_create ();
327 ASSERT (insert_values (&hamt
, 10, val_array1
, true) == 10);
328 ASSERT (element_count (hamt
) == 10);
329 ASSERT (find_values (hamt
, 10, val_array1
));
330 ASSERT (insert_values (&hamt
, 10, val_array2
, true) == 5);
331 ASSERT (element_count (hamt
) == 15);
332 ASSERT (remove_values (&hamt
, 10, val_array1
, true) == 10);
333 ASSERT (element_count (hamt
) == 5);
334 ASSERT (remove_values (&hamt
, 10, val_array2
, true) == 5);
335 ASSERT (element_count (hamt
) == 0);
337 ASSERT (replace_values (&hamt
, 10, val_array1
, true) == 0);
338 ASSERT (element_count (hamt
) == 10);
339 ASSERT (find_values (hamt
, 10, val_array1
));
340 ASSERT (replace_values (&hamt
, 10, val_array2
, true) == 5);
341 ASSERT (element_count (hamt
) == 15);
349 Hamt
*hamt
= test_hamt_create ();
350 ASSERT (insert_values (&hamt
, 10, val_array1
, true) == 10);
351 Hamt_iterator iter
[1];
352 iter
[0] = hamt_iterator (hamt
);
354 bool found
[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
356 while (hamt_iterator_next (iter
, &p
))
358 for (size_t i
= 0; i
< 10; ++i
)
359 if (val_array1
[i
] == entry_value (p
))
368 hamt_iterator_free (iter
);
376 test_functional_update ();
377 test_destructive_update ();
380 return test_exit_status
;