tests.c 12 KB

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