Blender V4.3
BLI_ghash_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
7#define GHASH_INTERNAL_API
8
9#include "BLI_ghash.h"
10#include "BLI_rand.h"
11#include "BLI_utildefines.h"
12
13#define TESTCASE_SIZE 10000
14
15/* Only keeping this in case here, for now. */
16#define PRINTF_GHASH_STATS(_gh) \
17 { \
18 double q, lf, var, pempty, poverloaded; \
19 int bigb; \
20 q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \
21 printf( \
22 "GHash stats (%d entries):\n\t" \
23 "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: " \
24 "%f\n\t" \
25 "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \
26 BLI_ghash_len(_gh), \
27 q, \
28 var, \
29 lf, \
30 pempty * 100.0, \
31 poverloaded * 100.0, \
32 bigb); \
33 } \
34 void(0)
35
36/* NOTE: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here
37 * we just use mere random integers stored in pointers. */
38
39static void init_keys(uint keys[TESTCASE_SIZE], const int seed)
40{
41 RNG *rng = BLI_rng_new(seed);
42 uint *k;
43 int i;
44
45 for (i = 0, k = keys; i < TESTCASE_SIZE;) {
46 /* Risks of collision are low, but they do exist.
47 * And we cannot use a GSet, since we test that here! */
48 int j, t = BLI_rng_get_uint(rng);
49 for (j = i; j--;) {
50 if (keys[j] == t) {
51 continue;
52 }
53 }
54 *k = t;
55 i++;
56 k++;
57 }
58 BLI_rng_free(rng);
59}
60
61/* Here we simply insert and then lookup all keys, ensuring we do get back the expected stored
62 * 'data'. */
63TEST(ghash, InsertLookup)
64{
66 uint keys[TESTCASE_SIZE], *k;
67 int i;
68
69 init_keys(keys, 0);
70
71 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
73 }
74
76
77 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
78 void *v = BLI_ghash_lookup(ghash, POINTER_FROM_UINT(*k));
80 }
81
82 BLI_ghash_free(ghash, nullptr, nullptr);
83}
84
85/* Here we simply insert and then remove all keys, ensuring we do get an empty,
86 * ghash that has not been shrunk. */
87TEST(ghash, InsertRemove)
88{
90 uint keys[TESTCASE_SIZE], *k;
91 int i, bkt_size;
92
93 init_keys(keys, 10);
94
95 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
97 }
98
100 bkt_size = BLI_ghash_buckets_len(ghash);
101
102 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
103 void *v = BLI_ghash_popkey(ghash, POINTER_FROM_UINT(*k), nullptr);
105 }
106
107 EXPECT_EQ(BLI_ghash_len(ghash), 0);
108 EXPECT_EQ(BLI_ghash_buckets_len(ghash), bkt_size);
109
110 BLI_ghash_free(ghash, nullptr, nullptr);
111}
112
113/* Same as `InsertRemove`, but this time we allow ghash to shrink. */
114TEST(ghash, InsertRemoveShrink)
115{
117 uint keys[TESTCASE_SIZE], *k;
118 int i, bkt_size;
119
121 init_keys(keys, 20);
122
123 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
125 }
126
128 bkt_size = BLI_ghash_buckets_len(ghash);
129
130 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
131 void *v = BLI_ghash_popkey(ghash, POINTER_FROM_UINT(*k), nullptr);
133 }
134
135 EXPECT_EQ(BLI_ghash_len(ghash), 0);
136 EXPECT_LT(BLI_ghash_buckets_len(ghash), bkt_size);
137
138 BLI_ghash_free(ghash, nullptr, nullptr);
139}
140
141/* Check copy. */
142TEST(ghash, Copy)
143{
146 uint keys[TESTCASE_SIZE], *k;
147 int i;
148
149 init_keys(keys, 30);
150
151 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
153 }
154
156
157 ghash_copy = BLI_ghash_copy(ghash, nullptr, nullptr);
158
161
162 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
165 }
166
167 BLI_ghash_free(ghash, nullptr, nullptr);
168 BLI_ghash_free(ghash_copy, nullptr, nullptr);
169}
170
171/* Check pop. */
172TEST(ghash, Pop)
173{
175 uint keys[TESTCASE_SIZE], *k;
176 int i;
177
179 init_keys(keys, 30);
180
181 for (i = TESTCASE_SIZE, k = keys; i--; k++) {
183 }
184
186
187 GHashIterState pop_state = {0};
188
189 for (i = TESTCASE_SIZE / 2; i--;) {
190 void *k, *v;
191 bool success = BLI_ghash_pop(ghash, &pop_state, &k, &v);
192 EXPECT_EQ(k, v);
193 EXPECT_TRUE(success);
194
195 if (i % 2) {
197 }
198 }
199
201
202 {
203 void *k, *v;
204 while (BLI_ghash_pop(ghash, &pop_state, &k, &v)) {
205 EXPECT_EQ(k, v);
206 }
207 }
208 EXPECT_EQ(BLI_ghash_len(ghash), 0);
209
210 BLI_ghash_free(ghash, nullptr, nullptr);
211}
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
int BLI_ghash_buckets_len(const GHash *gh)
Definition BLI_ghash.c:1083
static GHash * ghash_copy(const GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
Definition BLI_ghash.c:636
bool BLI_ghash_pop(GHash *gh, GHashIterState *state, void **r_key, void **r_val) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition BLI_ghash.c:824
GHash * BLI_ghash_copy(const GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:691
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
void * BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:802
bool BLI_ghashutil_intcmp(const void *a, const void *b)
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:702
unsigned int BLI_ghashutil_inthash_p(const void *ptr)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:731
@ GHASH_FLAG_ALLOW_SHRINK
Definition BLI_ghash.h:57
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
void BLI_ghash_flag_set(GHash *gh, unsigned int flag)
Definition BLI_ghash.c:872
#define TESTCASE_SIZE
TEST(ghash, InsertLookup)
static void init_keys(uint keys[TESTCASE_SIZE], const int seed)
Random number functions.
struct RNG * BLI_rng_new(unsigned int seed)
Definition rand.cc:39
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:58
unsigned int BLI_rng_get_uint(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:83
unsigned int uint
#define POINTER_AS_UINT(i)
#define POINTER_FROM_UINT(i)
ATTR_WARN_UNUSED_RESULT const BMVert * v
static unsigned long seed
Definition btSoftBody.h:39
Definition rand.cc:33