Coverage Report

Created: 2024-05-03 06:05

/builds/xfbs/passgen/src/tests/hashmap.c
Line
Count
Source
1
#include "passgen/container/hashmap.h"
2
#include "tests.h"
3
#include <stdlib.h>
4
#include <string.h>
5
6
1
test_result test_hashmap_init(void) {
7
1
    passgen_hashmap map;
8
1
    passgen_hashmap_init(&map, NULL);
9
1
    passgen_hashmap_free(&map);
10
1
    return test_ok;
11
1
}
12
13
1
test_result test_hashmap_context_utf8(void) {
14
1
    passgen_hashmap map;
15
1
    passgen_hashmap_init(&map, &passgen_hashmap_context_utf8);
16
1
17
1
    const char *key1 = "hello";
18
1
    const char *key2 = "hola";
19
1
20
1
    assert(passgen_hashmap_context_utf8.equal(&map, key1, key1));
21
1
    assert(passgen_hashmap_context_utf8.equal(&map, key2, key2));
22
1
    assert(!passgen_hashmap_context_utf8.equal(&map, key1, key2));
23
1
24
1
    assert_eq(
25
1
        passgen_hashmap_context_utf8.hash(&map, key1, true),
26
1
        0xf6f0cd43722c7cfe);
27
1
    assert_eq(
28
1
        passgen_hashmap_context_utf8.hash(&map, key1, false),
29
1
        0x438bcb516e4d4abf);
30
1
31
1
    assert_eq(
32
1
        passgen_hashmap_context_utf8.hash(&map, key2, true),
33
1
        0xcb99aa476d12f348);
34
1
    assert_eq(
35
1
        passgen_hashmap_context_utf8.hash(&map, key2, false),
36
1
        0xef7ec81d7aa533ea);
37
1
38
1
    passgen_hashmap_free(&map);
39
1
40
1
    return test_ok;
41
1
}
42
43
1
test_result test_hashmap_context_utf32(void) {
44
1
    passgen_hashmap map;
45
1
    passgen_hashmap_init(&map, &passgen_hashmap_context_utf32);
46
1
47
1
    uint32_t key1[] = {'h', 'e', 'l', 'l', 'o', 0};
48
1
    uint32_t key2[] = {'h', 'o', 'l', 'a', 0};
49
1
50
1
    assert(passgen_hashmap_context_utf32.equal(&map, &key1[0], &key1[0]));
51
1
    assert(passgen_hashmap_context_utf32.equal(&map, &key2[0], &key2[0]));
52
1
    assert(!passgen_hashmap_context_utf32.equal(&map, &key1[0], &key2[0]));
53
1
54
1
    assert_eq(
55
1
        passgen_hashmap_context_utf32.hash(&map, &key1[0], true),
56
1
        0x4b9a41e6925a46ad);
57
1
    assert_eq(
58
1
        passgen_hashmap_context_utf32.hash(&map, &key1[0], false),
59
1
        0x6ce43ac01a6144b8);
60
1
61
1
    assert_eq(
62
1
        passgen_hashmap_context_utf32.hash(&map, &key2[0], true),
63
1
        0xdefab330a5dcde19);
64
1
    assert_eq(
65
1
        passgen_hashmap_context_utf32.hash(&map, &key2[0], false),
66
1
        0x45168f9b31b7e7bd);
67
1
68
1
    passgen_hashmap_free(&map);
69
1
70
1
    return test_ok;
71
1
}
72
73
1
test_result test_hashmap_insert_utf32(void) {
74
1
    passgen_hashmap map;
75
1
    passgen_hashmap_entry entry;
76
1
77
1
    passgen_hashmap_init(&map, &passgen_hashmap_context_utf32);
78
1
79
1
    uint32_t key1[] = {'h', 'e', 'l', 'l', 'o', 0};
80
1
    int value1;
81
1
    entry = passgen_hashmap_insert(&map, &key1, &value1);
82
1
    assert_eq(entry.key, NULL);
83
1
    assert_eq(entry.value, NULL);
84
1
    assert_eq(map.len, 1);
85
1
    assert_eq(passgen_hashmap_lookup(&map, &key1)->value, &value1);
86
1
87
1
    uint32_t key2[] = {'h', 'o', 'l', 'a', 0};
88
1
    int value2;
89
1
    entry = passgen_hashmap_insert(&map, &key2, &value2);
90
1
    assert_eq(map.len, 2);
91
1
    assert_eq(entry.key, NULL);
92
1
    assert_eq(entry.value, NULL);
93
1
    assert_eq(passgen_hashmap_lookup(&map, &key1)->value, &value1);
94
1
    assert_eq(passgen_hashmap_lookup(&map, &key2)->value, &value2);
95
1
96
1
    passgen_hashmap_free(&map);
97
1
98
1
    return test_ok;
99
1
}
100
101
1
test_result test_hashmap_insert_utf8(void) {
102
1
    passgen_hashmap map;
103
1
    passgen_hashmap_init(&map, NULL);
104
1
105
1
    int value_a = 4, value_b = 7;
106
1
107
1
    passgen_hashmap_insert(&map, "hello", &value_a);
108
1
    assert_eq(map.len, 1);
109
1
    passgen_hashmap_insert(&map, "world", &value_b);
110
1
    assert_eq(map.len, 2);
111
1
112
1
    passgen_hashmap_entry *entry;
113
1
    entry = passgen_hashmap_lookup(&map, "hello");
114
1
    assert(entry);
115
1
    assert_eq(entry->value, &value_a);
116
1
117
1
    entry = passgen_hashmap_lookup(&map, "world");
118
1
    assert(entry);
119
1
    assert_eq(entry->value, &value_b);
120
1
121
1
    entry = passgen_hashmap_lookup(&map, "other");
122
1
    assert(!entry);
123
1
124
1
    passgen_hashmap_free(&map);
125
1
    return test_ok;
126
1
}
127
128
1
test_result test_hashmap_insert_many(void) {
129
1
    passgen_hashmap map;
130
1
    passgen_hashmap_init(&map, NULL);
131
1
    size_t insert_max = 10000;
132
1
133
1
    // insert large amount of items
134
10.0k
    for(size_t i = 0; i < insert_max; 
i++10.0k
) {
135
10.0k
        assert_eq(map.len, i);
136
10.0k
        char *key = malloc(32);
137
10.0k
        size_t *value = malloc(sizeof(size_t));
138
10.0k
        *value = i;
139
10.0k
        snprintf(key, 32, "%zu", i);
140
10.0k
        passgen_hashmap_insert(&map, key, value);
141
10.0k
142
10.0k
        // fill factor is how many percent of slots are used. we want this
143
10.0k
        // to be high.
144
10.0k
        float fill = map.len * 100.0 / (double) map.capacity;
145
10.0k
        assert(fill > 3.0);
146
10.0k
    }
147
1
148
1
    // retrieve all items
149
10.0k
    
for(size_t i = 0; 1
i < insert_max;
i++10.0k
) {
150
10.0k
        char key[32];
151
10.0k
        snprintf(key, 32, "%zu", i);
152
10.0k
        passgen_hashmap_entry *entry = passgen_hashmap_lookup(&map, key);
153
10.0k
        assert(entry);
154
10.0k
        size_t *value = entry->value;
155
10.0k
        assert_eq(*value, i);
156
10.0k
    }
157
1
158
1
    // release memory
159
1
    passgen_hashmap_foreach(&map, NULL, passgen_hashmap_entry_free);
160
1
161
1
    passgen_hashmap_free(&map);
162
1
    return test_ok;
163
1
}
164
165
1
test_result test_hashmap_remove(void) {
166
1
    passgen_hashmap map;
167
1
    passgen_hashmap_init(&map, NULL);
168
1
169
1
    int value_a = 4, value_b = 7;
170
1
171
1
    passgen_hashmap_insert(&map, "hello", &value_a);
172
1
    passgen_hashmap_insert(&map, "world", &value_b);
173
1
    assert_eq(map.len, 2);
174
1
175
1
    assert(passgen_hashmap_lookup(&map, "hello"));
176
1
    assert(passgen_hashmap_lookup(&map, "world"));
177
1
    assert(!passgen_hashmap_lookup(&map, "other"));
178
1
179
1
    passgen_hashmap_entry entry;
180
1
    entry = passgen_hashmap_remove(&map, "hello");
181
1
    assert_eq(map.len, 1);
182
1
    assert(entry.key);
183
1
    assert_eq(entry.value, &value_a);
184
1
    assert_streq(entry.key, "hello");
185
1
186
1
    assert(!passgen_hashmap_lookup(&map, "hello"));
187
1
    assert(passgen_hashmap_lookup(&map, "world"));
188
1
    assert(!passgen_hashmap_lookup(&map, "other"));
189
1
190
1
    entry = passgen_hashmap_remove(&map, "world");
191
1
    assert_eq(map.len, 0);
192
1
    assert(entry.key);
193
1
    assert_eq(entry.value, &value_b);
194
1
    assert_streq(entry.key, "world");
195
1
196
1
    assert(!passgen_hashmap_lookup(&map, "hello"));
197
1
    assert(!passgen_hashmap_lookup(&map, "world"));
198
1
    assert(!passgen_hashmap_lookup(&map, "other"));
199
1
200
1
    passgen_hashmap_free(&map);
201
1
    return test_ok;
202
1
}
203
204
1
test_result test_hashmap_lookup_empty(void) {
205
1
    passgen_hashmap map;
206
1
    passgen_hashmap_init(&map, NULL);
207
1
208
1
    passgen_hashmap_entry *entry = passgen_hashmap_lookup(&map, "test");
209
1
    assert(!entry);
210
1
211
1
    passgen_hashmap_free(&map);
212
1
    return test_ok;
213
1
}
214
215
1
int function_fails(void *data, passgen_hashmap_entry *entry) {
216
1
    (void) data;
217
1
    (void) entry;
218
1
    return 7;
219
1
}
220
221
5
int free_value(void *data, passgen_hashmap_entry *entry) {
222
5
    (void) data;
223
5
    free(entry->value);
224
5
    return 0;
225
5
}
226
227
1
test_result test_hashmap_foreach(void) {
228
1
    passgen_hashmap map;
229
1
    passgen_hashmap_init(&map, NULL);
230
1
231
1
    passgen_hashmap_insert(&map, "alpha", malloc(255));
232
1
    passgen_hashmap_insert(&map, "beta", malloc(255));
233
1
    passgen_hashmap_insert(&map, "gamma", malloc(255));
234
1
    passgen_hashmap_insert(&map, "delta", malloc(255));
235
1
    passgen_hashmap_insert(&map, "epsilon", malloc(255));
236
1
237
1
    assert_eq(passgen_hashmap_foreach(&map, NULL, function_fails), 7);
238
1
    assert_eq(passgen_hashmap_foreach(&map, NULL, free_value), 0);
239
1
240
1
    passgen_hashmap_free(&map);
241
1
    return test_ok;
242
1
}