2 * Wireshark Memory Manager Tests
3 * Copyright 2012, Evan Huus <eapache@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include "wmem_tree-int.h"
19 #include "wmem_allocator.h"
20 #include "wmem_allocator_block.h"
21 #include "wmem_allocator_block_fast.h"
22 #include "wmem_allocator_simple.h"
23 #include "wmem_allocator_strict.h"
25 #include <wsutil/time_util.h>
27 #define STRING_80 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
28 #define MAX_ALLOC_SIZE (1024*64)
29 #define MAX_SIMULTANEOUS_ALLOCS 1024
30 #define CONTAINER_ITERS 10000
32 typedef void (*wmem_verify_func
)(wmem_allocator_t
*allocator
);
34 /* A local copy of wmem_allocator_new that ignores the
35 * WIRESHARK_DEBUG_WMEM_OVERRIDE variable so that test functions are
36 * guaranteed to actually get the allocator type they asked for */
37 static wmem_allocator_t
*
38 wmem_allocator_force_new(const wmem_allocator_type_t type
)
40 wmem_allocator_t
*allocator
;
42 allocator
= wmem_new(NULL
, wmem_allocator_t
);
43 allocator
->type
= type
;
44 allocator
->callbacks
= NULL
;
45 allocator
->in_scope
= true;
48 case WMEM_ALLOCATOR_SIMPLE
:
49 wmem_simple_allocator_init(allocator
);
51 case WMEM_ALLOCATOR_BLOCK
:
52 wmem_block_allocator_init(allocator
);
54 case WMEM_ALLOCATOR_BLOCK_FAST
:
55 wmem_block_fast_allocator_init(allocator
);
57 case WMEM_ALLOCATOR_STRICT
:
58 wmem_strict_allocator_init(allocator
);
61 g_assert_not_reached();
62 /* This is necessary to squelch MSVC errors; is there
63 any way to tell it that g_assert_not_reached()
71 /* A helper for generating pseudo-random strings. Just uses glib's random number
72 * functions to generate 'numbers' in the printable character range. */
74 wmem_test_rand_string(wmem_allocator_t
*allocator
, int minlen
, int maxlen
)
79 len
= g_random_int_range(minlen
, maxlen
);
81 /* +1 for null-terminator */
82 str
= (char*)wmem_alloc(allocator
, len
+ 1);
85 for (i
=0; i
<len
; i
++) {
86 /* ASCII normal printable range is 32 (space) to 126 (tilde) */
87 str
[i
] = (char) g_random_int_range(32, 126);
94 wmem_test_compare_uint32(const void *a
, const void *b
)
98 l
= *(const uint32_t*)a
;
99 r
= *(const uint32_t*)b
;
104 /* Some helpers for properly testing callback functionality */
105 wmem_allocator_t
*expected_allocator
;
106 void *expected_user_data
;
107 wmem_cb_event_t expected_event
;
109 int cb_continue_count
;
110 bool value_seen
[CONTAINER_ITERS
];
113 wmem_test_cb(wmem_allocator_t
*allocator
, wmem_cb_event_t event
,
116 g_assert_true(allocator
== expected_allocator
);
117 g_assert_true(event
== expected_event
);
121 return *(bool*)user_data
;
125 wmem_test_foreach_cb(const void *key _U_
, void *value
, void *user_data
)
127 g_assert_true(user_data
== expected_user_data
);
129 g_assert_true(! value_seen
[GPOINTER_TO_INT(value
)]);
130 value_seen
[GPOINTER_TO_INT(value
)] = true;
135 return (cb_continue_count
== 0);
138 /* ALLOCATOR TESTING FUNCTIONS (/wmem/allocator/) */
141 wmem_test_allocator_callbacks(void)
143 wmem_allocator_t
*allocator
;
148 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
150 expected_allocator
= allocator
;
152 wmem_register_callback(expected_allocator
, &wmem_test_cb
, &f
);
153 wmem_register_callback(expected_allocator
, &wmem_test_cb
, &f
);
154 cb_id
= wmem_register_callback(expected_allocator
, &wmem_test_cb
, &t
);
155 wmem_register_callback(expected_allocator
, &wmem_test_cb
, &t
);
156 wmem_register_callback(expected_allocator
, &wmem_test_cb
, &f
);
158 expected_event
= WMEM_CB_FREE_EVENT
;
161 wmem_free_all(allocator
);
162 g_assert_true(cb_called_count
== 5);
165 wmem_free_all(allocator
);
166 g_assert_true(cb_called_count
== 2);
169 wmem_free_all(allocator
);
170 g_assert_true(cb_called_count
== 2);
172 wmem_unregister_callback(allocator
, cb_id
);
174 wmem_free_all(allocator
);
175 g_assert_true(cb_called_count
== 1);
177 cb_id
= wmem_register_callback(expected_allocator
, &wmem_test_cb
, &f
);
178 wmem_register_callback(expected_allocator
, &wmem_test_cb
, &t
);
181 wmem_free_all(allocator
);
182 g_assert_true(cb_called_count
== 3);
184 wmem_unregister_callback(allocator
, cb_id
);
186 wmem_free_all(allocator
);
187 g_assert_true(cb_called_count
== 2);
189 wmem_register_callback(expected_allocator
, &wmem_test_cb
, &t
);
191 expected_event
= WMEM_CB_DESTROY_EVENT
;
193 wmem_destroy_allocator(allocator
);
194 g_assert_true(cb_called_count
== 3);
198 wmem_test_allocator_det(wmem_allocator_t
*allocator
, wmem_verify_func verify
,
202 char *ptrs
[MAX_SIMULTANEOUS_ALLOCS
];
204 /* we use wmem_alloc0 in part because it tests slightly more code, but
205 * primarily so that if the allocator doesn't give us enough memory or
206 * gives us memory that includes its own metadata, we write to it and
207 * things go wrong, causing the tests to fail */
208 for (i
=0; i
<MAX_SIMULTANEOUS_ALLOCS
; i
++) {
209 ptrs
[i
] = (char *)wmem_alloc0(allocator
, len
);
211 for (i
=MAX_SIMULTANEOUS_ALLOCS
-1; i
>=0; i
--) {
212 /* no wmem_realloc0 so just use memset manually */
213 ptrs
[i
] = (char *)wmem_realloc(allocator
, ptrs
[i
], 4*len
);
214 memset(ptrs
[i
], 0, 4*len
);
216 for (i
=0; i
<MAX_SIMULTANEOUS_ALLOCS
; i
++) {
217 wmem_free(allocator
, ptrs
[i
]);
220 if (verify
) (*verify
)(allocator
);
221 wmem_free_all(allocator
);
223 if (verify
) (*verify
)(allocator
);
227 wmem_test_allocator_jumbo(wmem_allocator_type_t type
, wmem_verify_func verify
)
229 wmem_allocator_t
*allocator
;
232 allocator
= wmem_allocator_force_new(type
);
234 ptr
= (char*)wmem_alloc0(allocator
, 4*1024*1024);
235 wmem_free(allocator
, ptr
);
237 ptr
= (char*)wmem_alloc0(allocator
, 4*1024*1024);
239 if (verify
) (*verify
)(allocator
);
240 wmem_free(allocator
, ptr
);
242 if (verify
) (*verify
)(allocator
);
244 ptr
= (char *)wmem_alloc0(allocator
, 10*1024*1024);
245 ptr1
= (char *)wmem_alloc0(allocator
, 13*1024*1024);
246 ptr1
= (char *)wmem_realloc(allocator
, ptr1
, 10*1024*1024);
247 memset(ptr1
, 0, 10*1024*1024);
248 ptr
= (char *)wmem_realloc(allocator
, ptr
, 13*1024*1024);
249 memset(ptr
, 0, 13*1024*1024);
250 if (verify
) (*verify
)(allocator
);
252 if (verify
) (*verify
)(allocator
);
253 wmem_free(allocator
, ptr1
);
254 if (verify
) (*verify
)(allocator
);
255 wmem_free_all(allocator
);
257 if (verify
) (*verify
)(allocator
);
259 wmem_destroy_allocator(allocator
);
263 wmem_test_allocator(wmem_allocator_type_t type
, wmem_verify_func verify
,
267 char *ptrs
[MAX_SIMULTANEOUS_ALLOCS
];
268 wmem_allocator_t
*allocator
;
270 allocator
= wmem_allocator_force_new(type
);
272 if (verify
) (*verify
)(allocator
);
274 /* start with some fairly simple deterministic tests */
276 wmem_test_allocator_det(allocator
, verify
, 8);
278 wmem_test_allocator_det(allocator
, verify
, 64);
280 wmem_test_allocator_det(allocator
, verify
, 512);
282 for (i
=0; i
<MAX_SIMULTANEOUS_ALLOCS
; i
++) {
283 ptrs
[i
] = wmem_alloc0_array(allocator
, char, 32);
286 if (verify
) (*verify
)(allocator
);
287 wmem_free_all(allocator
);
289 if (verify
) (*verify
)(allocator
);
291 /* now do some random fuzz-like tests */
293 /* reset our ptr array */
294 for (i
=0; i
<MAX_SIMULTANEOUS_ALLOCS
; i
++) {
298 /* Run enough iterations to fill the array 32 times */
299 for (i
=0; i
<iterations
; i
++) {
303 /* returns value 0 <= x < MAX_SIMULTANEOUS_ALLOCS which is a valid
305 ptrs_index
= g_test_rand_int_range(0, MAX_SIMULTANEOUS_ALLOCS
);
307 if (ptrs
[ptrs_index
] == NULL
) {
308 /* if that index is unused, allocate some random amount of memory
309 * between 0 and MAX_ALLOC_SIZE */
310 new_size
= g_test_rand_int_range(0, MAX_ALLOC_SIZE
);
312 ptrs
[ptrs_index
] = (char *) wmem_alloc0(allocator
, new_size
);
314 else if (g_test_rand_bit()) {
315 /* the index is used, and our random bit has determined we will be
316 * reallocating instead of freeing. Do so to some random size
317 * between 0 and MAX_ALLOC_SIZE, then manually zero the
319 new_size
= g_test_rand_int_range(0, MAX_ALLOC_SIZE
);
321 ptrs
[ptrs_index
] = (char *) wmem_realloc(allocator
,
322 ptrs
[ptrs_index
], new_size
);
325 memset(ptrs
[ptrs_index
], 0, new_size
);
328 /* the index is used, and our random bit has determined we will be
329 * freeing instead of reallocating. Do so and NULL the pointer for
330 * the next iteration. */
331 wmem_free(allocator
, ptrs
[ptrs_index
]);
332 ptrs
[ptrs_index
] = NULL
;
334 if (verify
) (*verify
)(allocator
);
337 wmem_destroy_allocator(allocator
);
341 wmem_test_allocator_block(void)
343 wmem_test_allocator(WMEM_ALLOCATOR_BLOCK
, &wmem_block_verify
,
344 MAX_SIMULTANEOUS_ALLOCS
*64);
345 wmem_test_allocator_jumbo(WMEM_ALLOCATOR_BLOCK
, &wmem_block_verify
);
349 wmem_test_allocator_block_fast(void)
351 wmem_test_allocator(WMEM_ALLOCATOR_BLOCK_FAST
, NULL
,
352 MAX_SIMULTANEOUS_ALLOCS
*4);
353 wmem_test_allocator_jumbo(WMEM_ALLOCATOR_BLOCK
, NULL
);
357 wmem_test_allocator_simple(void)
359 wmem_test_allocator(WMEM_ALLOCATOR_SIMPLE
, NULL
,
360 MAX_SIMULTANEOUS_ALLOCS
*64);
361 wmem_test_allocator_jumbo(WMEM_ALLOCATOR_SIMPLE
, NULL
);
365 wmem_test_allocator_strict(void)
367 wmem_test_allocator(WMEM_ALLOCATOR_STRICT
, &wmem_strict_check_canaries
,
368 MAX_SIMULTANEOUS_ALLOCS
*64);
369 wmem_test_allocator_jumbo(WMEM_ALLOCATOR_STRICT
, &wmem_strict_check_canaries
);
372 /* UTILITY TESTING FUNCTIONS (/wmem/utils/) */
375 wmem_test_miscutls(void)
377 wmem_allocator_t
*allocator
;
378 const char *source
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
381 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
383 ret
= (char*) wmem_memdup(allocator
, NULL
, 0);
384 g_assert_true(ret
== NULL
);
386 ret
= (char*) wmem_memdup(allocator
, source
, 5);
388 g_assert_cmpstr(ret
, ==, "ABCD");
390 ret
= (char*) wmem_memdup(allocator
, source
, 1);
391 g_assert_true(ret
[0] == 'A');
392 wmem_strict_check_canaries(allocator
);
394 ret
= (char*) wmem_memdup(allocator
, source
, 10);
396 g_assert_cmpstr(ret
, ==, "ABCDEFGHI");
398 wmem_destroy_allocator(allocator
);
402 wmem_test_strutls(void)
404 wmem_allocator_t
*allocator
;
405 const char *orig_str
;
408 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
411 new_str
= wmem_strdup(allocator
, orig_str
);
412 g_assert_cmpstr(new_str
, ==, orig_str
);
414 g_assert_cmpstr(new_str
, >, orig_str
);
415 wmem_strict_check_canaries(allocator
);
417 orig_str
= "TEST123456789";
418 new_str
= wmem_strndup(allocator
, orig_str
, 6);
419 g_assert_cmpstr(new_str
, ==, "TEST12");
420 g_assert_cmpstr(new_str
, <, orig_str
);
422 g_assert_cmpstr(new_str
, >, orig_str
);
423 wmem_strict_check_canaries(allocator
);
425 new_str
= wmem_strdup_printf(allocator
, "abc %s %% %d", "boo", 23);
426 g_assert_cmpstr(new_str
, ==, "abc boo % 23");
427 new_str
= wmem_strdup_printf(allocator
, "%s", STRING_80
);
428 g_assert_cmpstr(new_str
, ==, STRING_80
);
429 wmem_strict_check_canaries(allocator
);
431 orig_str
= "Short String";
432 new_str
= wmem_strdup_printf(allocator
, "TEST %s", orig_str
);
433 g_assert_cmpstr(new_str
, ==, "TEST Short String");
435 orig_str
= "Very Long..............................."
436 "........................................"
437 "........................................"
438 "........................................"
439 "........................................"
440 "........................................"
441 "..................................String";
442 new_str
= wmem_strdup_printf(allocator
, "TEST %s", orig_str
);
443 g_assert_cmpstr(new_str
, ==,
444 "TEST Very Long..............................."
445 "........................................"
446 "........................................"
447 "........................................"
448 "........................................"
449 "........................................"
450 "..................................String");
452 wmem_destroy_allocator(allocator
);
455 #define RESOURCE_USAGE_START get_resource_usage(&start_utime, &start_stime)
457 #define RESOURCE_USAGE_END \
458 get_resource_usage(&end_utime, &end_stime); \
459 utime_ms = (end_utime - start_utime) * 1000.0; \
460 stime_ms = (end_stime - start_stime) * 1000.0
462 /* NOTE: You have to run "wmem_test -m perf" to run the performance tests. */
464 wmem_test_stringperf(void)
466 #define LOOP_COUNT (1 * 1000 * 1000)
467 wmem_allocator_t
*allocator
;
471 char **str_ptr
= g_new(char *, LOOP_COUNT
);
472 char *s_val
= "test string";
473 double d_val
= 1000.2;
474 unsigned u_val
= 54321;
477 double start_utime
, start_stime
, end_utime
, end_stime
, utime_ms
, stime_ms
;
479 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_BLOCK
);
483 RESOURCE_USAGE_START
;
484 for (i
= 0; i
< LOOP_COUNT
; i
++) {
485 snprintf(NULL
, 0, "%s", s_val
);
488 g_test_minimized_result(utime_ms
+ stime_ms
,
489 "snprintf 1 string: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
491 RESOURCE_USAGE_START
;
492 for (i
= 0; i
< LOOP_COUNT
; i
++) {
493 snprintf(NULL
, 0, "%s%s%s%s%s", s_val
, s_val
, s_val
, s_val
, s_val
);
496 g_test_minimized_result(utime_ms
+ stime_ms
,
497 "snprintf 5 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
499 RESOURCE_USAGE_START
;
500 for (i
= 0; i
< LOOP_COUNT
; i
++) {
501 snprintf(NULL
, 0, "%s%u%3.5f%02d", s_val
, u_val
, d_val
, i_val
);
504 g_test_minimized_result(utime_ms
+ stime_ms
,
505 "snprintf mixed args: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
507 /* GLib g_snprintf (can use C99 or Gnulib) */
509 RESOURCE_USAGE_START
;
510 for (i
= 0; i
< LOOP_COUNT
; i
++) {
511 g_snprintf(NULL
, 0, "%s", s_val
);
514 g_test_minimized_result(utime_ms
+ stime_ms
,
515 "g_printf_string_upper_bound (via g_snprintf) 1 string: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
517 RESOURCE_USAGE_START
;
518 for (i
= 0; i
< LOOP_COUNT
; i
++) {
519 g_snprintf(NULL
, 0, "%s%s%s%s%s", s_val
, s_val
, s_val
, s_val
, s_val
);
522 g_test_minimized_result(utime_ms
+ stime_ms
,
523 "g_printf_string_upper_bound (via g_snprintf) 5 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
525 RESOURCE_USAGE_START
;
526 for (i
= 0; i
< LOOP_COUNT
; i
++) {
527 g_snprintf(NULL
, 0, "%s%u%3.5f%02d", s_val
, u_val
, d_val
, i_val
);
530 g_test_minimized_result(utime_ms
+ stime_ms
,
531 "g_printf_string_upper_bound (via g_snprintf) mixed args: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
533 /* Windows _snprintf_s */
536 RESOURCE_USAGE_START
;
537 for (i
= 0; i
< LOOP_COUNT
; i
++) {
538 _snprintf_s(buffer
, 1, _TRUNCATE
, "%s", s_val
);
541 g_test_minimized_result(utime_ms
+ stime_ms
,
542 "_snprintf_s upper bound 1 string: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
544 RESOURCE_USAGE_START
;
545 for (i
= 0; i
< LOOP_COUNT
; i
++) {
546 _snprintf_s(buffer
, 1, _TRUNCATE
, "%s%s%s%s%s", s_val
, s_val
, s_val
, s_val
, s_val
);
549 g_test_minimized_result(utime_ms
+ stime_ms
,
550 "_snprintf_s upper bound 5 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
552 RESOURCE_USAGE_START
;
553 for (i
= 0; i
< LOOP_COUNT
; i
++) {
554 _snprintf_s(buffer
, 1, _TRUNCATE
, "%s%u%3.5f%02d", s_val
, u_val
, d_val
, i_val
);
557 g_test_minimized_result(utime_ms
+ stime_ms
,
558 "_snprintf_s upper bound mixed args: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
563 RESOURCE_USAGE_START
;
564 for (i
= 0; i
< LOOP_COUNT
; i
++) {
565 str_ptr
[i
] = g_strdup_printf("%s%s", s_val
, s_val
);
568 g_test_minimized_result(utime_ms
+ stime_ms
,
569 "g_strdup_printf 2 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
570 for (i
= 0; i
< LOOP_COUNT
; i
++) {
574 RESOURCE_USAGE_START
;
575 for (i
= 0; i
< LOOP_COUNT
; i
++) {
576 str_ptr
[i
] = g_strdup_printf("%s%s%s%s%s", s_val
, s_val
, s_val
, s_val
, s_val
);
579 g_test_minimized_result(utime_ms
+ stime_ms
,
580 "g_strdup_printf 5 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
581 for (i
= 0; i
< LOOP_COUNT
; i
++) {
585 /* wmem strdup null allocator */
587 RESOURCE_USAGE_START
;
588 for (i
= 0; i
< LOOP_COUNT
; i
++) {
589 str_ptr
[i
] = wmem_strdup_printf(NULL
, "%s%s", s_val
, s_val
);
592 g_test_minimized_result(utime_ms
+ stime_ms
,
593 "wmem_strdup_printf() 2 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
594 for (i
= 0; i
< LOOP_COUNT
; i
++) {
598 RESOURCE_USAGE_START
;
599 for (i
= 0; i
< LOOP_COUNT
; i
++) {
600 str_ptr
[i
] = wmem_strdup_printf(NULL
, "%s%s%s%s%s", s_val
, s_val
, s_val
, s_val
, s_val
);
603 g_test_minimized_result(utime_ms
+ stime_ms
,
604 "wmem_strdup_printf(NULL) 5 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
605 for (i
= 0; i
< LOOP_COUNT
; i
++) {
609 /* wmem strdup strict allocator */
611 RESOURCE_USAGE_START
;
612 for (i
= 0; i
< LOOP_COUNT
; i
++) {
613 wmem_strdup_printf(allocator
, "%s%s", s_val
, s_val
);
616 g_test_minimized_result(utime_ms
+ stime_ms
,
617 "wmem_strdup_printf(allocator) 2 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
619 RESOURCE_USAGE_START
;
620 for (i
= 0; i
< LOOP_COUNT
; i
++) {
621 wmem_strdup_printf(allocator
, "%s%s%s%s%s", s_val
, s_val
, s_val
, s_val
, s_val
);
624 g_test_minimized_result(utime_ms
+ stime_ms
,
625 "wmem_strdup_printf(allocator) 5 strings: u %.3f ms s %.3f ms", utime_ms
, stime_ms
);
627 wmem_destroy_allocator(allocator
);
631 /* DATA STRUCTURE TESTING FUNCTIONS (/wmem/datastruct/) */
634 wmem_test_array(void)
636 wmem_allocator_t
*allocator
;
638 unsigned int i
, j
, k
;
644 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
646 array
= wmem_array_new(allocator
, sizeof(uint32_t));
647 g_assert_true(array
);
648 g_assert_true(wmem_array_get_count(array
) == 0);
650 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
652 wmem_array_append_one(array
, val
);
653 g_assert_true(wmem_array_get_count(array
) == i
+1);
655 val
= *(uint32_t*)wmem_array_index(array
, i
);
656 g_assert_true(val
== i
);
657 g_assert_true(wmem_array_try_index(array
, i
, &val
) == 0);
658 g_assert_true(val
== i
);
659 g_assert_true(wmem_array_try_index(array
, i
+1, &val
) < 0);
662 wmem_strict_check_canaries(allocator
);
664 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
665 val
= *(uint32_t*)wmem_array_index(array
, i
);
666 g_assert_true(val
== i
);
667 g_assert_true(wmem_array_try_index(array
, i
, &val
) == 0);
668 g_assert_true(val
== i
);
671 wmem_destroy_array(array
);
673 array
= wmem_array_sized_new(allocator
, sizeof(uint32_t), 73);
674 wmem_array_set_null_terminator(array
);
676 g_assert_true(wmem_array_try_index(array
, i
, &val
) < 0);
678 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
679 for (j
=0; j
<8; j
++) {
683 wmem_array_append(array
, vals
, 8);
684 g_assert_true(wmem_array_get_count(array
) == 8*(i
+1));
686 wmem_strict_check_canaries(allocator
);
688 buf
= (uint32_t*)wmem_array_get_raw(array
);
689 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
690 for (j
=0; j
<8; j
++) {
691 g_assert_true(buf
[i
*8 + j
] == i
+j
);
695 wmem_array_sort(array
, wmem_test_compare_uint32
);
696 for (i
=0, k
=0; i
<8; i
++) {
697 for (j
=0; j
<=i
; j
++, k
++) {
698 val
= *(uint32_t*)wmem_array_index(array
, k
);
699 g_assert_true(val
== i
);
700 g_assert_true(wmem_array_try_index(array
, k
, &val
) == 0);
701 g_assert_true(val
== i
);
704 for (j
=k
; k
<8*(CONTAINER_ITERS
+1)-j
; k
++) {
705 val
= *(uint32_t*)wmem_array_index(array
, k
);
706 g_assert_true(val
== ((k
-j
)/8)+8);
707 g_assert_true(wmem_array_try_index(array
, k
, &val
) == 0);
708 g_assert_true(val
== ((k
-j
)/8)+8);
710 for (i
=0; i
<7; i
++) {
711 for (j
=0; j
<7-i
; j
++, k
++) {
712 val
= *(uint32_t*)wmem_array_index(array
, k
);
713 g_assert_true(val
== CONTAINER_ITERS
+i
);
714 g_assert_true(wmem_array_try_index(array
, k
, &val
) == 0);
715 g_assert_true(val
== CONTAINER_ITERS
+i
);
718 g_assert_true(k
== wmem_array_get_count(array
));
721 wmem_array_append_one(array
, lastint
);
723 raw
= (uint32_t*)wmem_array_get_raw(array
);
724 g_assert_true(raw
[wmem_array_get_count(array
)] == 0);
725 g_assert_true(raw
[wmem_array_get_count(array
) - 1] == lastint
);
727 wmem_destroy_array(array
);
729 wmem_destroy_allocator(allocator
);
733 check_val_list(void * val
, void * val_to_check
)
735 g_assert_true(val
== val_to_check
);
739 str_compare(const void *a
, const void *b
)
741 return strcmp((const char*)a
, (const char*)b
);
747 wmem_allocator_t
*allocator
;
749 wmem_list_frame_t
*frame
;
756 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
758 list
= wmem_list_new(allocator
);
760 g_assert_true(wmem_list_count(list
) == 0);
762 frame
= wmem_list_head(list
);
763 g_assert_true(frame
== NULL
);
765 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
766 wmem_list_prepend(list
, GINT_TO_POINTER(i
));
767 g_assert_true(wmem_list_count(list
) == i
+1);
768 g_assert_true(wmem_list_find(list
, GINT_TO_POINTER(i
)));
770 frame
= wmem_list_head(list
);
771 g_assert_true(frame
);
772 g_assert_true(wmem_list_frame_data(frame
) == GINT_TO_POINTER(i
));
774 wmem_strict_check_canaries(allocator
);
776 i
= CONTAINER_ITERS
- 1;
777 frame
= wmem_list_head(list
);
779 g_assert_true(wmem_list_frame_data(frame
) == GINT_TO_POINTER(i
));
781 frame
= wmem_list_frame_next(frame
);
785 frame
= wmem_list_tail(list
);
787 g_assert_true(wmem_list_frame_data(frame
) == GINT_TO_POINTER(i
));
789 frame
= wmem_list_frame_prev(frame
);
792 i
= CONTAINER_ITERS
- 2;
793 while (wmem_list_count(list
) > 1) {
794 wmem_list_remove(list
, GINT_TO_POINTER(i
));
797 wmem_list_remove(list
, GINT_TO_POINTER(CONTAINER_ITERS
- 1));
798 g_assert_true(wmem_list_count(list
) == 0);
799 g_assert_true(wmem_list_head(list
) == NULL
);
800 g_assert_true(wmem_list_tail(list
) == NULL
);
802 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
803 wmem_list_append(list
, GINT_TO_POINTER(i
));
804 g_assert_true(wmem_list_count(list
) == i
+1);
806 frame
= wmem_list_head(list
);
807 g_assert_true(frame
);
809 wmem_strict_check_canaries(allocator
);
812 frame
= wmem_list_head(list
);
814 g_assert_true(wmem_list_frame_data(frame
) == GINT_TO_POINTER(i
));
816 frame
= wmem_list_frame_next(frame
);
819 i
= CONTAINER_ITERS
- 1;
820 frame
= wmem_list_tail(list
);
822 g_assert_true(wmem_list_frame_data(frame
) == GINT_TO_POINTER(i
));
824 frame
= wmem_list_frame_prev(frame
);
827 wmem_destroy_allocator(allocator
);
829 list
= wmem_list_new(NULL
);
830 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
831 wmem_list_prepend(list
, GINT_TO_POINTER(i
));
833 g_assert_true(wmem_list_count(list
) == CONTAINER_ITERS
);
834 wmem_destroy_list(list
);
836 list
= wmem_list_new(NULL
);
837 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
838 wmem_list_append(list
, GINT_TO_POINTER(1));
840 wmem_list_foreach(list
, check_val_list
, GINT_TO_POINTER(1));
841 wmem_destroy_list(list
);
843 list
= wmem_list_new(NULL
);
844 wmem_list_insert_sorted(list
, GINT_TO_POINTER(5), wmem_compare_int
);
845 wmem_list_insert_sorted(list
, GINT_TO_POINTER(8), wmem_compare_int
);
846 wmem_list_insert_sorted(list
, GINT_TO_POINTER(1), wmem_compare_int
);
847 wmem_list_insert_sorted(list
, GINT_TO_POINTER(2), wmem_compare_int
);
848 wmem_list_insert_sorted(list
, GINT_TO_POINTER(9), wmem_compare_int
);
849 g_assert_true(wmem_list_count(list
) == 5);
850 frame
= wmem_list_head(list
);
851 int1
= GPOINTER_TO_INT(wmem_list_frame_data(frame
));
852 while ((frame
= wmem_list_frame_next(frame
))) {
853 int2
= GPOINTER_TO_INT(wmem_list_frame_data(frame
));
854 g_assert_true(int1
<= int2
);
857 wmem_destroy_list(list
);
859 list
= wmem_list_new(NULL
);
860 wmem_list_insert_sorted(list
, GINT_TO_POINTER(5), wmem_compare_int
);
861 wmem_list_insert_sorted(list
, GINT_TO_POINTER(1), wmem_compare_int
);
862 wmem_list_insert_sorted(list
, GINT_TO_POINTER(7), wmem_compare_int
);
863 wmem_list_insert_sorted(list
, GINT_TO_POINTER(3), wmem_compare_int
);
864 wmem_list_insert_sorted(list
, GINT_TO_POINTER(2), wmem_compare_int
);
865 wmem_list_insert_sorted(list
, GINT_TO_POINTER(2), wmem_compare_int
);
866 g_assert_true(wmem_list_count(list
) == 6);
867 frame
= wmem_list_head(list
);
868 int1
= GPOINTER_TO_INT(wmem_list_frame_data(frame
));
869 while ((frame
= wmem_list_frame_next(frame
))) {
870 int2
= GPOINTER_TO_INT(wmem_list_frame_data(frame
));
871 g_assert_true(int1
<= int2
);
874 wmem_destroy_list(list
);
876 list
= wmem_list_new(NULL
);
877 wmem_list_insert_sorted(list
, "abc", str_compare
);
878 wmem_list_insert_sorted(list
, "bcd", str_compare
);
879 wmem_list_insert_sorted(list
, "aaa", str_compare
);
880 wmem_list_insert_sorted(list
, "bbb", str_compare
);
881 wmem_list_insert_sorted(list
, "zzz", str_compare
);
882 wmem_list_insert_sorted(list
, "ggg", str_compare
);
883 g_assert_true(wmem_list_count(list
) == 6);
884 frame
= wmem_list_head(list
);
885 str1
= (char*)wmem_list_frame_data(frame
);
886 while ((frame
= wmem_list_frame_next(frame
))) {
887 str2
= (char*)wmem_list_frame_data(frame
);
888 g_assert_true(strcmp(str1
, str2
) <= 0);
891 wmem_destroy_list(list
);
895 check_val_map(void * key _U_
, void * val
, void * user_data
)
897 g_assert_true(val
== user_data
);
901 equal_val_map(void * key _U_
, void * val
, void * user_data
)
903 return val
== user_data
;
909 wmem_allocator_t
*allocator
, *extra_allocator
;
912 const void *str_key_ret
;
914 unsigned int *key_ret
;
915 unsigned int *value_ret
;
918 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
919 extra_allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
921 /* insertion, lookup and removal of simple integer keys */
922 map
= wmem_map_new(allocator
, g_direct_hash
, g_direct_equal
);
925 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
926 ret
= wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(777777));
927 g_assert_true(ret
== NULL
);
928 ret
= wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(i
));
929 g_assert_true(ret
== GINT_TO_POINTER(777777));
930 ret
= wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(i
));
931 g_assert_true(ret
== GINT_TO_POINTER(i
));
933 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
934 ret
= wmem_map_lookup(map
, GINT_TO_POINTER(i
));
935 g_assert_true(ret
== GINT_TO_POINTER(i
));
936 g_assert_true(wmem_map_contains(map
, GINT_TO_POINTER(i
)) == true);
937 g_assert_true(wmem_map_lookup_extended(map
, GINT_TO_POINTER(i
), NULL
, NULL
));
939 g_assert_true(wmem_map_lookup_extended(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(&key_ret
), NULL
));
940 g_assert_true(key_ret
== GINT_TO_POINTER(i
));
942 g_assert_true(wmem_map_lookup_extended(map
, GINT_TO_POINTER(i
), NULL
, GINT_TO_POINTER(&value_ret
)));
943 g_assert_true(value_ret
== GINT_TO_POINTER(i
));
946 g_assert_true(wmem_map_lookup_extended(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(&key_ret
), GINT_TO_POINTER(&value_ret
)));
947 g_assert_true(key_ret
== GINT_TO_POINTER(i
));
948 g_assert_true(value_ret
== GINT_TO_POINTER(i
));
949 ret
= wmem_map_remove(map
, GINT_TO_POINTER(i
));
950 g_assert_true(ret
== GINT_TO_POINTER(i
));
951 g_assert_true(wmem_map_contains(map
, GINT_TO_POINTER(i
)) == false);
952 ret
= wmem_map_lookup(map
, GINT_TO_POINTER(i
));
953 g_assert_true(ret
== NULL
);
954 ret
= wmem_map_remove(map
, GINT_TO_POINTER(i
));
955 g_assert_true(ret
== NULL
);
957 wmem_free_all(allocator
);
959 /* test auto-reset functionality */
960 map
= wmem_map_new_autoreset(allocator
, extra_allocator
, g_direct_hash
, g_direct_equal
);
962 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
963 ret
= wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(777777));
964 g_assert_true(ret
== NULL
);
965 ret
= wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(i
));
966 g_assert_true(ret
== GINT_TO_POINTER(777777));
967 ret
= wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(i
));
968 g_assert_true(ret
== GINT_TO_POINTER(i
));
970 wmem_free_all(extra_allocator
);
971 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
972 g_assert_true(wmem_map_lookup(map
, GINT_TO_POINTER(i
)) == NULL
);
974 wmem_free_all(allocator
);
976 map
= wmem_map_new(allocator
, wmem_str_hash
, g_str_equal
);
979 /* string keys and for-each */
980 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
981 str_key
= wmem_test_rand_string(allocator
, 1, 64);
982 wmem_map_insert(map
, str_key
, GINT_TO_POINTER(i
));
983 ret
= wmem_map_lookup(map
, str_key
);
984 g_assert_true(ret
== GINT_TO_POINTER(i
));
985 g_assert_true(wmem_map_contains(map
, str_key
) == true);
988 g_assert_true(wmem_map_lookup_extended(map
, str_key
, &str_key_ret
, GINT_TO_POINTER(&value_ret
)) == true);
989 g_assert_true(g_str_equal(str_key_ret
, str_key
));
990 g_assert_true(value_ret
== GINT_TO_POINTER(i
));
994 map
= wmem_map_new(allocator
, wmem_str_hash
, g_str_equal
);
996 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
997 str_key
= wmem_test_rand_string(allocator
, 1, 64);
998 wmem_map_insert(map
, str_key
, GINT_TO_POINTER(2));
1000 wmem_map_foreach(map
, check_val_map
, GINT_TO_POINTER(2));
1001 g_assert_true(wmem_map_find(map
, equal_val_map
, GINT_TO_POINTER(2)) == GINT_TO_POINTER(2));
1002 wmem_map_foreach_remove(map
, equal_val_map
, GINT_TO_POINTER(2));
1003 g_assert_true(wmem_map_size(map
) == 0);
1006 map
= wmem_map_new(allocator
, g_direct_hash
, g_direct_equal
);
1008 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1009 wmem_map_insert(map
, GINT_TO_POINTER(i
), GINT_TO_POINTER(i
));
1011 g_assert_true(wmem_map_size(map
) == CONTAINER_ITERS
);
1013 for (i
=0; i
<CONTAINER_ITERS
; i
+=2) {
1014 wmem_map_foreach_remove(map
, equal_val_map
, GINT_TO_POINTER(i
));
1016 g_assert_true(wmem_map_size(map
) == CONTAINER_ITERS
/2);
1018 wmem_destroy_allocator(extra_allocator
);
1019 wmem_destroy_allocator(allocator
);
1023 wmem_test_queue(void)
1025 wmem_allocator_t
*allocator
;
1026 wmem_queue_t
*queue
;
1029 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1031 queue
= wmem_queue_new(allocator
);
1032 g_assert_true(queue
);
1033 g_assert_true(wmem_queue_count(queue
) == 0);
1035 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1036 wmem_queue_push(queue
, GINT_TO_POINTER(i
));
1038 g_assert_true(wmem_queue_count(queue
) == i
+1);
1039 g_assert_true(wmem_queue_peek(queue
) == GINT_TO_POINTER(0));
1041 wmem_strict_check_canaries(allocator
);
1043 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1044 g_assert_true(wmem_queue_peek(queue
) == GINT_TO_POINTER(i
));
1045 g_assert_true(wmem_queue_pop(queue
) == GINT_TO_POINTER(i
));
1046 g_assert_true(wmem_queue_count(queue
) == CONTAINER_ITERS
-i
-1);
1048 g_assert_true(wmem_queue_count(queue
) == 0);
1050 wmem_destroy_queue(queue
);
1052 wmem_destroy_allocator(allocator
);
1056 wmem_test_stack(void)
1058 wmem_allocator_t
*allocator
;
1059 wmem_stack_t
*stack
;
1062 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1064 stack
= wmem_stack_new(allocator
);
1065 g_assert_true(stack
);
1066 g_assert_true(wmem_stack_count(stack
) == 0);
1068 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1069 wmem_stack_push(stack
, GINT_TO_POINTER(i
));
1071 g_assert_true(wmem_stack_count(stack
) == i
+1);
1072 g_assert_true(wmem_stack_peek(stack
) == GINT_TO_POINTER(i
));
1074 wmem_strict_check_canaries(allocator
);
1076 for (i
=CONTAINER_ITERS
; i
>0; i
--) {
1077 g_assert_true(wmem_stack_peek(stack
) == GINT_TO_POINTER(i
-1));
1078 g_assert_true(wmem_stack_pop(stack
) == GINT_TO_POINTER(i
-1));
1079 g_assert_true(wmem_stack_count(stack
) == i
-1);
1081 g_assert_true(wmem_stack_count(stack
) == 0);
1083 wmem_destroy_stack(stack
);
1085 wmem_destroy_allocator(allocator
);
1089 wmem_test_strbuf(void)
1091 wmem_allocator_t
*allocator
;
1092 wmem_strbuf_t
*strbuf
;
1095 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1097 strbuf
= wmem_strbuf_new(allocator
, "TEST");
1098 g_assert_true(strbuf
);
1099 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TEST");
1100 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 4);
1102 wmem_strbuf_append(strbuf
, "FUZZ");
1103 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ");
1104 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 8);
1106 wmem_strbuf_append_printf(strbuf
, "%d%s", 3, "a");
1107 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ3a");
1108 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 10);
1110 wmem_strbuf_append_c(strbuf
, 'q');
1111 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ3aq");
1112 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 11);
1114 wmem_strbuf_append_unichar(strbuf
, g_utf8_get_char("\xC2\xA9"));
1115 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ3aq\xC2\xA9");
1116 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 13);
1118 wmem_strbuf_append_c_count(strbuf
, '+', 8);
1119 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ3aq\xC2\xA9++++++++");
1120 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 21);
1122 wmem_strbuf_truncate(strbuf
, 32);
1123 wmem_strbuf_truncate(strbuf
, 24);
1124 wmem_strbuf_truncate(strbuf
, 16);
1125 wmem_strbuf_truncate(strbuf
, 13);
1126 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ3aq\xC2\xA9");
1127 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 13);
1129 wmem_strbuf_truncate(strbuf
, 3);
1130 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TES");
1131 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 3);
1133 wmem_strbuf_append_len(strbuf
, "TFUZZ1234", 5);
1134 g_assert_cmpstr(wmem_strbuf_get_str(strbuf
), ==, "TESTFUZZ");
1135 g_assert_cmpuint(wmem_strbuf_get_len(strbuf
), ==, 8);
1137 wmem_free_all(allocator
);
1139 strbuf
= wmem_strbuf_new(allocator
, "TEST");
1140 for (i
=0; i
<1024; i
++) {
1141 if (g_test_rand_bit()) {
1142 wmem_strbuf_append(strbuf
, "ABC");
1145 wmem_strbuf_append_printf(strbuf
, "%d%d", 3, 777);
1147 wmem_strict_check_canaries(allocator
);
1149 g_assert_true(strlen(wmem_strbuf_get_str(strbuf
)) ==
1150 wmem_strbuf_get_len(strbuf
));
1152 wmem_destroy_allocator(allocator
);
1156 wmem_test_strbuf_validate(void)
1158 wmem_strbuf_t
*strbuf
;
1161 strbuf
= wmem_strbuf_new(NULL
, "TEST\xEF ABC");
1162 g_assert_false(wmem_strbuf_utf8_validate(strbuf
, &endptr
));
1163 g_assert_true(endptr
== &strbuf
->str
[4]);
1164 wmem_strbuf_destroy(strbuf
);
1166 strbuf
= wmem_strbuf_new(NULL
, NULL
);
1167 wmem_strbuf_append_len(strbuf
, "TEST\x00\x00 ABC", 10);
1168 g_assert_true(wmem_strbuf_utf8_validate(strbuf
, &endptr
));
1169 wmem_strbuf_destroy(strbuf
);
1171 strbuf
= wmem_strbuf_new(NULL
, NULL
);
1172 wmem_strbuf_append_len(strbuf
, "TEST\x00\xEF ABC", 10);
1173 g_assert_false(wmem_strbuf_utf8_validate(strbuf
, &endptr
));
1174 g_assert_true(endptr
== &strbuf
->str
[5]);
1175 wmem_strbuf_destroy(strbuf
);
1177 strbuf
= wmem_strbuf_new(NULL
, NULL
);
1178 wmem_strbuf_append_len(strbuf
, "TEST\x00 ABC \x00 DEF \x00", 17);
1179 g_assert_true(wmem_strbuf_utf8_validate(strbuf
, &endptr
));
1180 wmem_strbuf_destroy(strbuf
);
1184 wmem_test_tree(void)
1186 wmem_allocator_t
*allocator
, *extra_allocator
;
1190 int seen_values
= 0;
1194 #define WMEM_TREE_MAX_KEY_COUNT 8
1195 #define WMEM_TREE_MAX_KEY_LEN 4
1197 wmem_tree_key_t keys
[WMEM_TREE_MAX_KEY_COUNT
];
1199 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1200 extra_allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1202 tree
= wmem_tree_new(allocator
);
1203 g_assert_true(tree
);
1204 g_assert_true(wmem_tree_is_empty(tree
));
1206 /* test basic 32-bit key operations */
1207 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1208 g_assert_true(wmem_tree_lookup32(tree
, i
) == NULL
);
1210 g_assert_true(wmem_tree_lookup32_le_full(tree
, i
, &int_key
) == GINT_TO_POINTER(i
-1));
1211 g_assert_true(int_key
== i
- 1);
1213 wmem_tree_insert32(tree
, i
, GINT_TO_POINTER(i
));
1214 g_assert_true(wmem_tree_lookup32(tree
, i
) == GINT_TO_POINTER(i
));
1215 g_assert_true(!wmem_tree_is_empty(tree
));
1217 g_assert_true(wmem_tree_count(tree
) == CONTAINER_ITERS
);
1219 rand_int
= ((uint32_t)g_test_rand_int()) % CONTAINER_ITERS
;
1220 wmem_tree_remove32(tree
, rand_int
);
1221 g_assert_true(wmem_tree_lookup32(tree
, rand_int
) == NULL
);
1223 g_assert_true(wmem_tree_lookup32_le(tree
, rand_int
) == GINT_TO_POINTER(rand_int
- 1));
1225 if (rand_int
+ 1 < CONTAINER_ITERS
) {
1226 g_assert_true(wmem_tree_lookup32_ge(tree
, rand_int
) == GINT_TO_POINTER(rand_int
+ 1));
1228 g_assert_true(wmem_tree_count(tree
) == CONTAINER_ITERS
- 1);
1229 wmem_free_all(allocator
);
1231 tree
= wmem_tree_new(allocator
);
1232 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1234 rand_int
= g_test_rand_int();
1235 } while (wmem_tree_lookup32(tree
, rand_int
));
1236 wmem_tree_insert32(tree
, rand_int
, GINT_TO_POINTER(i
));
1237 g_assert_true(wmem_tree_lookup32(tree
, rand_int
) == GINT_TO_POINTER(i
));
1239 g_assert_true(wmem_tree_count(tree
) == CONTAINER_ITERS
);
1240 wmem_free_all(allocator
);
1242 /* test auto-reset functionality */
1243 tree
= wmem_tree_new_autoreset(allocator
, extra_allocator
);
1244 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1245 g_assert_true(wmem_tree_lookup32(tree
, i
) == NULL
);
1246 wmem_tree_insert32(tree
, i
, GINT_TO_POINTER(i
));
1247 g_assert_true(wmem_tree_lookup32(tree
, i
) == GINT_TO_POINTER(i
));
1249 g_assert_true(wmem_tree_count(tree
) == CONTAINER_ITERS
);
1250 wmem_free_all(extra_allocator
);
1251 g_assert_true(wmem_tree_count(tree
) == 0);
1252 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1253 g_assert_true(wmem_tree_lookup32(tree
, i
) == NULL
);
1254 g_assert_true(wmem_tree_lookup32_le(tree
, i
) == NULL
);
1256 wmem_free_all(allocator
);
1258 /* test array key functionality */
1259 tree
= wmem_tree_new(allocator
);
1260 key_count
= g_random_int_range(1, WMEM_TREE_MAX_KEY_COUNT
);
1261 for (j
=0; j
<key_count
; j
++) {
1262 keys
[j
].length
= g_random_int_range(1, WMEM_TREE_MAX_KEY_LEN
);
1264 keys
[key_count
].length
= 0;
1265 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1266 for (j
=0; j
<key_count
; j
++) {
1267 keys
[j
].key
= (uint32_t*)wmem_test_rand_string(allocator
,
1268 (keys
[j
].length
*4), (keys
[j
].length
*4)+1);
1270 wmem_tree_insert32_array(tree
, keys
, GINT_TO_POINTER(i
));
1271 g_assert_true(wmem_tree_lookup32_array(tree
, keys
) == GINT_TO_POINTER(i
));
1273 wmem_free_all(allocator
);
1275 tree
= wmem_tree_new(allocator
);
1277 keys
[0].key
= wmem_new(allocator
, uint32_t);
1280 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1281 wmem_tree_insert32_array(tree
, keys
, GINT_TO_POINTER(i
));
1282 *(keys
[0].key
) += 4;
1285 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1286 g_assert_true(wmem_tree_lookup32_array(tree
, keys
) == GINT_TO_POINTER(i
));
1287 for (j
=0; j
<3; j
++) {
1288 (*(keys
[0].key
)) += 1;
1289 g_assert_true(wmem_tree_lookup32_array_le(tree
, keys
) ==
1290 GINT_TO_POINTER(i
));
1292 *(keys
[0].key
) += 1;
1294 wmem_free_all(allocator
);
1296 /* test string key functionality */
1297 tree
= wmem_tree_new(allocator
);
1298 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1299 str_key
= wmem_test_rand_string(allocator
, 1, 64);
1300 wmem_tree_insert_string(tree
, str_key
, GINT_TO_POINTER(i
), 0);
1301 g_assert_true(wmem_tree_lookup_string(tree
, str_key
, 0) ==
1302 GINT_TO_POINTER(i
));
1304 wmem_free_all(allocator
);
1306 tree
= wmem_tree_new(allocator
);
1307 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1308 str_key
= wmem_test_rand_string(allocator
, 1, 64);
1309 wmem_tree_insert_string(tree
, str_key
, GINT_TO_POINTER(i
),
1310 WMEM_TREE_STRING_NOCASE
);
1311 g_assert_true(wmem_tree_lookup_string(tree
, str_key
,
1312 WMEM_TREE_STRING_NOCASE
) == GINT_TO_POINTER(i
));
1314 wmem_free_all(allocator
);
1316 /* test for-each functionality */
1317 tree
= wmem_tree_new(allocator
);
1318 expected_user_data
= GINT_TO_POINTER(g_test_rand_int());
1319 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1322 tmp
= g_test_rand_int();
1323 } while (wmem_tree_lookup32(tree
, tmp
));
1324 value_seen
[i
] = false;
1325 wmem_tree_insert32(tree
, tmp
, GINT_TO_POINTER(i
));
1328 cb_called_count
= 0;
1329 cb_continue_count
= CONTAINER_ITERS
;
1330 wmem_tree_foreach(tree
, wmem_test_foreach_cb
, expected_user_data
);
1331 g_assert_true(cb_called_count
== CONTAINER_ITERS
);
1332 g_assert_true(cb_continue_count
== 0);
1334 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1335 g_assert_true(value_seen
[i
]);
1336 value_seen
[i
] = false;
1339 cb_called_count
= 0;
1340 cb_continue_count
= 10;
1341 wmem_tree_foreach(tree
, wmem_test_foreach_cb
, expected_user_data
);
1342 g_assert_true(cb_called_count
== 10);
1343 g_assert_true(cb_continue_count
== 0);
1345 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1346 if (value_seen
[i
]) {
1350 g_assert_true(seen_values
== 10);
1352 wmem_destroy_allocator(extra_allocator
);
1353 wmem_destroy_allocator(allocator
);
1357 /* to be used as userdata in the callback wmem_test_itree_check_overlap_cb*/
1358 typedef struct wmem_test_itree_user_data
{
1361 } wmem_test_itree_user_data_t
;
1364 /* increase userData counter in case the range match the userdata range */
1366 wmem_test_itree_check_overlap_cb (const void *key
, void *value _U_
, void *userData
)
1368 const wmem_range_t
*ckey
= (const wmem_range_t
*)key
;
1369 struct wmem_test_itree_user_data
* d
= (struct wmem_test_itree_user_data
*)userData
;
1373 if(wmem_itree_range_overlap(ckey
, &d
->range
)) {
1382 wmem_test_overlap(uint64_t low
, uint64_t high
, uint64_t lowbis
, uint64_t highbis
)
1384 wmem_range_t r1
= {low
, high
, 0};
1385 wmem_range_t r2
= {lowbis
, highbis
, 0};
1386 return wmem_itree_range_overlap(&r1
, &r2
);
1390 wmem_test_itree(void)
1392 wmem_allocator_t
*allocator
, *extra_allocator
;
1395 int32_t max_rand
= 0;
1396 wmem_test_itree_user_data_t userData
;
1397 wmem_range_t range
, r2
;
1399 allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1400 extra_allocator
= wmem_allocator_new(WMEM_ALLOCATOR_STRICT
);
1402 tree
= wmem_itree_new(allocator
);
1403 g_assert_true(tree
);
1404 g_assert_true(wmem_itree_is_empty(tree
));
1406 wmem_free_all(allocator
);
1408 /* make sure that wmem_test_overlap is correct (well it's no proof but...)*/
1409 g_assert_true(wmem_test_overlap(0, 10, 0, 4));
1410 g_assert_true(wmem_test_overlap(0, 10, 9, 14));
1411 g_assert_true(wmem_test_overlap(5, 10, 3, 8));
1412 g_assert_true(wmem_test_overlap(5, 10, 1, 12));
1413 g_assert_true(!wmem_test_overlap(0, 10, 11, 12));
1415 /* Generate a reference range, then fill an itree with random ranges,
1416 then we count greedily the number of overlapping ranges and compare
1417 the result with the optimized result
1420 userData
.counter
= 0;
1422 tree
= wmem_itree_new(allocator
);
1424 /* even though keys are uint64_t, we use INT32_MAX as a max because of the type returned by
1425 g_test_rand_int_range.
1427 max_rand
= INT32_MAX
;
1428 r2
.max_edge
= range
.max_edge
= 0;
1429 range
.low
= g_test_rand_int_range(0, max_rand
);
1430 range
.high
= g_test_rand_int_range( (int32_t)range
.low
, (int32_t)max_rand
);
1431 userData
.range
= range
;
1433 for (i
=0; i
<CONTAINER_ITERS
; i
++) {
1435 wmem_list_t
*results
= NULL
;
1437 /* reset the search */
1438 userData
.counter
= 0;
1439 r2
.low
= (uint64_t)g_test_rand_int_range(0, 100);
1440 r2
.high
= (uint64_t)g_test_rand_int_range( (int32_t)r2
.low
, 100);
1442 wmem_itree_insert(tree
, r2
.low
, r2
.high
, GINT_TO_POINTER(i
));
1445 wmem_tree_foreach(tree
, wmem_test_itree_check_overlap_cb
, &userData
);
1447 /* Optimized search */
1448 results
= wmem_itree_find_intervals(tree
, allocator
, range
.low
, range
.high
);
1450 /* keep it as a loop instead of wmem_list_count in case one */
1451 g_assert_true(wmem_list_count(results
) == userData
.counter
);
1454 wmem_destroy_allocator(extra_allocator
);
1455 wmem_destroy_allocator(allocator
);
1460 main(int argc
, char **argv
)
1466 g_test_init(&argc
, &argv
, NULL
);
1468 g_test_add_func("/wmem/allocator/block", wmem_test_allocator_block
);
1469 g_test_add_func("/wmem/allocator/blk_fast", wmem_test_allocator_block_fast
);
1470 g_test_add_func("/wmem/allocator/simple", wmem_test_allocator_simple
);
1471 g_test_add_func("/wmem/allocator/strict", wmem_test_allocator_strict
);
1472 g_test_add_func("/wmem/allocator/callbacks", wmem_test_allocator_callbacks
);
1474 g_test_add_func("/wmem/utils/misc", wmem_test_miscutls
);
1475 g_test_add_func("/wmem/utils/strings", wmem_test_strutls
);
1477 if (g_test_perf()) {
1478 g_test_add_func("/wmem/utils/stringperf", wmem_test_stringperf
);
1481 g_test_add_func("/wmem/datastruct/array", wmem_test_array
);
1482 g_test_add_func("/wmem/datastruct/list", wmem_test_list
);
1483 g_test_add_func("/wmem/datastruct/map", wmem_test_map
);
1484 g_test_add_func("/wmem/datastruct/queue", wmem_test_queue
);
1485 g_test_add_func("/wmem/datastruct/stack", wmem_test_stack
);
1486 g_test_add_func("/wmem/datastruct/strbuf", wmem_test_strbuf
);
1487 g_test_add_func("/wmem/datastruct/strbuf/validate", wmem_test_strbuf_validate
);
1488 g_test_add_func("/wmem/datastruct/tree", wmem_test_tree
);
1489 g_test_add_func("/wmem/datastruct/itree", wmem_test_itree
);
1499 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1504 * indent-tabs-mode: nil
1507 * vi: set shiftwidth=4 tabstop=8 expandtab:
1508 * :indentSize=4:tabSize=8:noTabs=true: