master
c 273 lines 11.8 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "c_rhash.h"
7
8 // terminal color codes
9 #define KNRM "\x1B[0m"
10 #define KRED "\x1B[31m"
11 #define KGRN "\x1B[32m"
12 #define KYEL "\x1B[33m"
13 #define KBLU "\x1B[34m"
14 #define KMAG "\x1B[35m"
15 #define KCYN "\x1B[36m"
16 #define KWHT "\x1B[37m"
17
18 #define KEY_1 "key1"
19 #define KEY_2 "keya"
20
21 #define PRINT_ERR(str, ...) fprintf(stderr, "└─╼ ❌ " KRED str KNRM "\n" __VA_OPT__(,) __VA_ARGS__)
22
23 #define ASSERT_RETVAL(fnc, comparator, expected_retval, ...) \
24 { int rval; \
25 if(!((rval = fnc(__VA_ARGS__)) comparator expected_retval)) { \
26 PRINT_ERR("Failed test. Value returned by \"%s\" in fnc:\"%s\",line:%d is not equal to expected value. Expected:%d, Got:%d", #fnc, __FUNCTION__, __LINE__, expected_retval, rval); \
27 rc = 1; \
28 goto test_cleanup; \
29 } passed_subtest_count++;};
30
31 #define ASSERT_VAL_UINT8(returned, expected) \
32 if(returned != expected) { \
33 PRINT_ERR("Failed test. Value returned (%d) doesn't match expected (%d)! fnc:\"%s\",line:%d", returned, expected, __FUNCTION__, __LINE__); \
34 rc = 1; \
35 goto test_cleanup; \
36 } passed_subtest_count++;
37
38 #define ASSERT_VAL_PTR(returned, expected) \
39 if((void*)returned != (void*)expected) { \
40 PRINT_ERR("Failed test. Value returned(%p) doesn't match expected(%p)! fnc:\"%s\",line:%d", (void*)returned, (void*)expected, __FUNCTION__, __LINE__); \
41 rc = 1; \
42 goto test_cleanup; \
43 } passed_subtest_count++;
44
45 #define ALL_SUBTESTS_PASS() printf("└─╼ ✅" KGRN " Test \"%s\" DONE. All of %zu subtests PASS. (line:%d)\n" KNRM, __FUNCTION__, passed_subtest_count, __LINE__);
46
47 #define TEST_START() size_t passed_subtest_count = 0; int rc = 0; printf("╒═ Starting test \"%s\"\n", __FUNCTION__);
48
49 int test_str_uint8() {
50 c_rhash hash = c_rhash_new(100);
51 uint8_t val;
52
53 TEST_START();
54 // function should fail on empty hash
55 ASSERT_RETVAL(c_rhash_get_uint8_by_str, !=, 0, hash, KEY_1, &val);
56
57 ASSERT_RETVAL(c_rhash_insert_str_uint8, ==, 0, hash, KEY_1, 5);
58 ASSERT_RETVAL(c_rhash_get_uint8_by_str, ==, 0, hash, KEY_1, &val);
59 ASSERT_VAL_UINT8(5, val);
60
61 ASSERT_RETVAL(c_rhash_insert_str_uint8, ==, 0, hash, KEY_2, 8);
62 ASSERT_RETVAL(c_rhash_get_uint8_by_str, ==, 0, hash, KEY_1, &val);
63 ASSERT_VAL_UINT8(5, val);
64 ASSERT_RETVAL(c_rhash_get_uint8_by_str, ==, 0, hash, KEY_2, &val);
65 ASSERT_VAL_UINT8(8, val);
66 ASSERT_RETVAL(c_rhash_get_uint8_by_str, !=, 0, hash, "sndnskjdf", &val);
67
68 // test update of key
69 ASSERT_RETVAL(c_rhash_insert_str_uint8, ==, 0, hash, KEY_1, 100);
70 ASSERT_RETVAL(c_rhash_get_uint8_by_str, ==, 0, hash, KEY_1, &val);
71 ASSERT_VAL_UINT8(100, val);
72
73 ALL_SUBTESTS_PASS();
74 test_cleanup:
75 c_rhash_destroy(hash);
76 return rc;
77 }
78
79 int test_uint64_ptr() {
80 c_rhash hash = c_rhash_new(100);
81 void *val;
82
83 TEST_START();
84
85 // function should fail on empty hash
86 ASSERT_RETVAL(c_rhash_get_ptr_by_uint64, !=, 0, hash, 0, &val);
87
88 ASSERT_RETVAL(c_rhash_insert_uint64_ptr, ==, 0, hash, 0, &hash);
89 ASSERT_RETVAL(c_rhash_get_ptr_by_uint64, ==, 0, hash, 0, &val);
90 ASSERT_VAL_PTR(&hash, val);
91
92 ASSERT_RETVAL(c_rhash_insert_uint64_ptr, ==, 0, hash, 1, &val);
93 ASSERT_RETVAL(c_rhash_get_ptr_by_uint64, ==, 0, hash, 0, &val);
94 ASSERT_VAL_PTR(&hash, val);
95 ASSERT_RETVAL(c_rhash_get_ptr_by_uint64, ==, 0, hash, 1, &val);
96 ASSERT_VAL_PTR(&val, val);
97 ASSERT_RETVAL(c_rhash_get_ptr_by_uint64, !=, 0, hash, 2, &val);
98
99 ALL_SUBTESTS_PASS();
100 test_cleanup:
101 c_rhash_destroy(hash);
102 return rc;
103 }
104
105 #define UINT64_PTR_INC_ITERATION_COUNT 5000
106 int test_uint64_ptr_incremental() {
107 c_rhash hash = c_rhash_new(100);
108 void *val;
109
110 TEST_START();
111
112 char a = 0x20;
113 char *ptr = &a;
114 while(ptr < &a + UINT64_PTR_INC_ITERATION_COUNT) {
115 ASSERT_RETVAL(c_rhash_insert_uint64_ptr, ==, 0, hash, (ptr-&a), ptr);
116 ptr++;
117 }
118
119 ptr = &a;
120 char *retptr;
121 for(int i = 0; i < UINT64_PTR_INC_ITERATION_COUNT; i++) {
122 ASSERT_RETVAL(c_rhash_get_ptr_by_uint64, ==, 0, hash, i, (void**)&retptr);
123 ASSERT_VAL_PTR(retptr, (&a+i));
124 }
125
126 ALL_SUBTESTS_PASS();
127 test_cleanup:
128 c_rhash_destroy(hash);
129 return rc;
130 }
131
132 struct test_string {
133 const char *str;
134 int counter;
135 };
136
137 struct test_string test_strings[] = {
138 { .str = "Cillum reprehenderit eiusmod elit nisi aliquip esse exercitation commodo Lorem voluptate esse.", .counter = 0 },
139 { .str = "Ullamco eiusmod tempor occaecat ad.", .counter = 0 },
140 { .str = "Esse aliquip tempor sint tempor ullamco duis aute incididunt ad.", .counter = 0 },
141 { .str = "Cillum Lorem labore cupidatat commodo proident adipisicing.", .counter = 0 },
142 { .str = "Quis ad cillum officia exercitation.", .counter = 0 },
143 { .str = "Ipsum enim dolor ullamco amet sint nisi ut occaecat sint non.", .counter = 0 },
144 { .str = "Id duis officia ipsum cupidatat velit fugiat.", .counter = 0 },
145 { .str = "Aliqua non occaecat voluptate reprehenderit reprehenderit veniam minim exercitation ea aliquip enim aliqua deserunt qui.", .counter = 0 },
146 { .str = "Ullamco elit tempor laboris reprehenderit quis deserunt duis quis tempor reprehenderit magna dolore reprehenderit exercitation.", .counter = 0 },
147 { .str = "Culpa do dolor quis incididunt et labore in ex.", .counter = 0 },
148 { .str = "Aliquip velit cupidatat qui incididunt ipsum nostrud eiusmod ut proident nisi magna fugiat excepteur.", .counter = 0 },
149 { .str = "Aliqua qui dolore tempor id proident ullamco sunt magna.", .counter = 0 },
150 { .str = "Labore eiusmod ut fugiat dolore reprehenderit mollit magna.", .counter = 0 },
151 { .str = "Veniam aliquip dolor excepteur minim nulla esse cupidatat esse.", .counter = 0 },
152 { .str = "Do quis dolor irure nostrud occaecat aute proident anim.", .counter = 0 },
153 { .str = "Enim veniam non nulla ad quis sit amet.", .counter = 0 },
154 { .str = "Cillum reprehenderit do enim esse do ullamco consectetur ea.", .counter = 0 },
155 { .str = "Sit et duis sint anim qui ad anim labore exercitation sunt cupidatat.", .counter = 0 },
156 { .str = "Dolor officia adipisicing sint pariatur in dolor occaecat officia reprehenderit magna.", .counter = 0 },
157 { .str = "Aliquip dolore qui occaecat eiusmod sunt incididunt reprehenderit minim et.", .counter = 0 },
158 { .str = "Aute fugiat laboris cillum tempor consequat tempor do non laboris culpa officia nisi.", .counter = 0 },
159 { .str = "Et excepteur do aliquip fugiat nisi velit tempor officia enim quis elit incididunt.", .counter = 0 },
160 { .str = "Eu officia adipisicing incididunt occaecat officia cupidatat enim sit sit officia.", .counter = 0 },
161 { .str = "Do amet cillum duis pariatur commodo nulla cillum magna nulla Lorem veniam cupidatat.", .counter = 0 },
162 { .str = "Dolor adipisicing voluptate laboris occaecat culpa aliquip ipsum ut consequat aliqua aliquip commodo sunt velit.", .counter = 0 },
163 { .str = "Nulla proident ipsum quis nulla.", .counter = 0 },
164 { .str = "Laborum adipisicing nulla do aute aliqua est quis sint culpa pariatur laborum voluptate qui.", .counter = 0 },
165 { .str = "Proident eiusmod sunt et nulla elit pariatur dolore irure ex voluptate excepteur adipisicing consectetur.", .counter = 0 },
166 { .str = "Consequat ex voluptate officia excepteur aute deserunt proident commodo et.", .counter = 0 },
167 { .str = "Velit sit cupidatat dolor dolore.", .counter = 0 },
168 { .str = "Sunt enim do non anim nostrud exercitation ullamco ex proident commodo.", .counter = 0 },
169 { .str = "Id ex officia cillum ad.", .counter = 0 },
170 { .str = "Laboris in sunt eiusmod veniam laboris nostrud.", .counter = 0 },
171 { .str = "Ex magna occaecat ea ea incididunt aliquip.", .counter = 0 },
172 { .str = "Sunt eiusmod ex nostrud eu pariatur sit cupidatat ea adipisicing cillum culpa esse consequat aliquip.", .counter = 0 },
173 { .str = "Excepteur commodo qui incididunt enim culpa sunt non excepteur Lorem adipisicing.", .counter = 0 },
174 { .str = "Quis officia est ullamco reprehenderit incididunt occaecat pariatur ex reprehenderit nisi.", .counter = 0 },
175 { .str = "Culpa irure proident proident et eiusmod irure aliqua ipsum cupidatat minim sit.", .counter = 0 },
176 { .str = "Qui cupidatat aliquip est velit magna veniam.", .counter = 0 },
177 { .str = "Pariatur ad ad mollit nostrud non irure minim veniam anim aliquip quis eu.", .counter = 0 },
178 { .str = "Nisi ex minim eu adipisicing tempor Lorem nisi do ad exercitation est non eu.", .counter = 0 },
179 { .str = "Cupidatat do mollit ad commodo cupidatat ut.", .counter = 0 },
180 { .str = "Est non excepteur eiusmod nostrud et eu.", .counter = 0 },
181 { .str = "Cupidatat mollit nisi magna officia ut elit eiusmod.", .counter = 0 },
182 { .str = "Est aliqua consectetur laboris ex consequat est ut dolor.", .counter = 0 },
183 { .str = "Duis eu laboris laborum ut id Lorem nostrud qui ad velit proident fugiat minim ullamco.", .counter = 0 },
184 { .str = "Pariatur esse excepteur anim amet excepteur irure sint quis esse ex cupidatat ut.", .counter = 0 },
185 { .str = "Esse reprehenderit amet qui excepteur aliquip amet.", .counter = 0 },
186 { .str = "Ullamco laboris elit labore adipisicing aute nulla qui laborum tempor officia ut dolor aute.", .counter = 0 },
187 { .str = "Commodo sunt cillum velit minim laborum Lorem aliqua tempor ad id eu.", .counter = 0 },
188 { .str = NULL, .counter = 0 }
189 };
190
191 uint32_t test_strings_contain_element(const char *str) {
192 struct test_string *str_desc = test_strings;
193 while(str_desc->str) {
194 if (!strcmp(str, str_desc->str))
195 return str_desc - test_strings;
196 str_desc++;
197 }
198 return -1;
199 }
200
201 #define TEST_INCREMENT_STR_KEYS_HASH_SIZE 20
202 int test_increment_str_keys() {
203 c_rhash hash;
204 const char *key;
205
206 TEST_START();
207
208 hash = c_rhash_new(TEST_INCREMENT_STR_KEYS_HASH_SIZE); // less than element count of test_strings
209
210 c_rhash_iter_t iter = C_RHASH_ITER_T_INITIALIZER;
211
212 // check iter on empty hash
213 ASSERT_RETVAL(c_rhash_iter_str_keys, !=, 0, hash, &iter, &key);
214
215 int32_t element_count = 0;
216 while (test_strings[element_count].str) {
217 ASSERT_RETVAL(c_rhash_insert_str_ptr, ==, 0, hash, test_strings[element_count].str, NULL);
218 test_strings[element_count].counter++; // we want to test we got each key exactly once
219 element_count++;
220 }
221
222 if (element_count <= TEST_INCREMENT_STR_KEYS_HASH_SIZE * 2) {
223 // verify we are actually test also iteration trough single bin (when 2 keys have same hash pointing them to same bin)
224 PRINT_ERR("For this test to properly test all the hash size needs to be much smaller than all test key count.");
225 rc = 1;
226 goto test_cleanup;
227 }
228
229 // we insert another type of key as iterator should skip it
230 // in case is another type
231 ASSERT_RETVAL(c_rhash_insert_uint64_ptr, ==, 0, hash, 5, NULL);
232
233 c_rhash_iter_t_initialize(&iter);
234 while(!c_rhash_iter_str_keys(hash, &iter, &key)) {
235 element_count--;
236 int i;
237 if ( (i = test_strings_contain_element(key)) < 0) {
238 PRINT_ERR("Key \"%s\" is not present in test_strings array! (Fnc: %s, Line: %d)", key, __FUNCTION__, __LINE__);
239 rc = 1;
240 goto test_cleanup;
241 }
242 passed_subtest_count++;
243
244 test_strings[i].counter--;
245 }
246 ASSERT_VAL_UINT8(element_count, 0); // we added also same non string keys
247
248 // check each key was present exactly once
249 struct test_string *str_desc = test_strings;
250 while (str_desc->str) {
251 ASSERT_VAL_UINT8(str_desc->counter, 0);
252 str_desc++;
253 }
254
255 ALL_SUBTESTS_PASS();
256 test_cleanup:
257 c_rhash_destroy(hash);
258 return rc;
259 }
260
261 #define RUN_TEST(fnc) \
262 if(fnc()) \
263 return 1;
264
265 int main(int argc, char *argv[]) {
266 RUN_TEST(test_str_uint8);
267 RUN_TEST(test_uint64_ptr);
268 RUN_TEST(test_uint64_ptr_incremental);
269 RUN_TEST(test_increment_str_keys);
270 // TODO hash with mixed key tests
271 // TODO iterator test
272 return 0;
273 }