jcs's openbsd hax
openbsd

Add more regress coverage for lhash.

jsing 080cd0fa 22f856c7

+263 -3
+263 -3
regress/lib/libcrypto/lhash/lhash_test.c
··· 1 - /* $OpenBSD: lhash_test.c,v 1.1 2024/05/06 14:31:25 jsing Exp $ */ 1 + /* $OpenBSD: lhash_test.c,v 1.2 2024/05/08 15:13:23 jsing Exp $ */ 2 2 /* 3 3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> 4 4 * ··· 21 21 22 22 #include <openssl/lhash.h> 23 23 24 + /* 25 + * Need to add test coverage for: 26 + * - custom hash function 27 + * - custom comparison function 28 + */ 29 + 24 30 static void 25 - test_doall_fn(void *arg1, void *arg2) 31 + test_doall_count(void *arg1, void *arg2) 32 + { 33 + int *count = arg2; 34 + 35 + (*count)++; 36 + } 37 + 38 + static int 39 + test_lhash(void) 40 + { 41 + const char *a = "a", *b = "b", *c = "c", *d = "d"; 42 + const char *a2 = "a", *b2 = "b"; 43 + _LHASH *lh; 44 + int count; 45 + int failed = 1; 46 + 47 + if ((lh = lh_new(NULL, NULL)) == NULL) 48 + goto failure; 49 + 50 + /* 51 + * Another amazing API... both a successful insert and a failure will 52 + * return NULL. The only way you can tell the difference is to follow 53 + * with a call to lh_error(). 54 + */ 55 + if (lh_retrieve(lh, "a") != NULL || lh_error(lh) != 0) { 56 + fprintf(stderr, "FAIL: retrieved a before insert\n"); 57 + goto failure; 58 + } 59 + if (lh_insert(lh, (void *)a) != NULL || lh_error(lh) != 0) { 60 + fprintf(stderr, "FAIL: insert a\n"); 61 + goto failure; 62 + } 63 + if (lh_retrieve(lh, "a") != a) { 64 + fprintf(stderr, "FAIL: failed to retrieve a\n"); 65 + goto failure; 66 + } 67 + 68 + if (lh_retrieve(lh, "b") != NULL || lh_error(lh) != 0) { 69 + fprintf(stderr, "FAIL: retrieved b before insert\n"); 70 + goto failure; 71 + } 72 + if (lh_insert(lh, (void *)b) != NULL || lh_error(lh) != 0) { 73 + fprintf(stderr, "FAIL: insert b\n"); 74 + goto failure; 75 + } 76 + if (lh_retrieve(lh, "b") != b) { 77 + fprintf(stderr, "FAIL: failed to retrieve b\n"); 78 + goto failure; 79 + } 80 + 81 + if (lh_retrieve(lh, "c") != NULL || lh_error(lh) != 0) { 82 + fprintf(stderr, "FAIL: retrieved c before insert\n"); 83 + goto failure; 84 + } 85 + if (lh_insert(lh, (void *)c) != NULL || lh_error(lh) != 0) { 86 + fprintf(stderr, "FAIL: insert c\n"); 87 + goto failure; 88 + } 89 + if (lh_retrieve(lh, "c") != c) { 90 + fprintf(stderr, "FAIL: failed to retrieve c\n"); 91 + goto failure; 92 + } 93 + 94 + if (lh_retrieve(lh, "d") != NULL || lh_error(lh) != 0) { 95 + fprintf(stderr, "FAIL: retrieved d before insert\n"); 96 + goto failure; 97 + } 98 + if (lh_insert(lh, (void *)d) != NULL || lh_error(lh) != 0) { 99 + fprintf(stderr, "FAIL: insert d\n"); 100 + goto failure; 101 + } 102 + if (lh_retrieve(lh, "d") != d) { 103 + fprintf(stderr, "FAIL: failed to retrieve d\n"); 104 + goto failure; 105 + } 106 + 107 + if (lh_num_items(lh) != 4) { 108 + fprintf(stderr, "FAIL: lh_num_items() = %ld, want 4\n", 109 + lh_num_items(lh)); 110 + goto failure; 111 + } 112 + 113 + /* Insert should replace. */ 114 + if (lh_insert(lh, (void *)a2) != a || lh_error(lh) != 0) { 115 + fprintf(stderr, "FAIL: replace a\n"); 116 + goto failure; 117 + } 118 + if (lh_retrieve(lh, "a") != a2) { 119 + fprintf(stderr, "FAIL: failed to retrieve a2\n"); 120 + goto failure; 121 + } 122 + if (lh_insert(lh, (void *)b2) != b || lh_error(lh) != 0) { 123 + fprintf(stderr, "FAIL: replace b\n"); 124 + goto failure; 125 + } 126 + if (lh_retrieve(lh, "b") != b2) { 127 + fprintf(stderr, "FAIL: failed to retrieve b2\n"); 128 + goto failure; 129 + } 130 + 131 + if (lh_num_items(lh) != 4) { 132 + fprintf(stderr, "FAIL: lh_num_items() = %ld, want 4\n", 133 + lh_num_items(lh)); 134 + goto failure; 135 + } 136 + 137 + /* Do all. */ 138 + count = 0; 139 + lh_doall_arg(lh, test_doall_count, &count); 140 + if (count != 4) { 141 + fprintf(stderr, "FAIL: lh_doall_arg failed (count = %d)\n", 142 + count); 143 + goto failure; 144 + } 145 + 146 + /* Delete. */ 147 + if (lh_delete(lh, "z") != NULL || lh_error(lh) != 0) { 148 + fprintf(stderr, "FAIL: delete succeeded for z\n"); 149 + goto failure; 150 + } 151 + if (lh_delete(lh, "a") != a2 || lh_error(lh) != 0) { 152 + fprintf(stderr, "FAIL: delete failed for a\n"); 153 + goto failure; 154 + } 155 + if (lh_retrieve(lh, "a") != NULL || lh_error(lh) != 0) { 156 + fprintf(stderr, "FAIL: retrieved a after deletion\n"); 157 + goto failure; 158 + } 159 + if (lh_delete(lh, "b") != b2 || lh_error(lh) != 0) { 160 + fprintf(stderr, "FAIL: delete failed for b\n"); 161 + goto failure; 162 + } 163 + if (lh_retrieve(lh, "b") != NULL || lh_error(lh) != 0) { 164 + fprintf(stderr, "FAIL: retrieved b after deletion\n"); 165 + goto failure; 166 + } 167 + if (lh_delete(lh, "c") != c || lh_error(lh) != 0) { 168 + fprintf(stderr, "FAIL: delete failed for c\n"); 169 + goto failure; 170 + } 171 + if (lh_retrieve(lh, "c") != NULL || lh_error(lh) != 0) { 172 + fprintf(stderr, "FAIL: retrieved c after deletion\n"); 173 + goto failure; 174 + } 175 + if (lh_delete(lh, "d") != d || lh_error(lh) != 0) { 176 + fprintf(stderr, "FAIL: delete failed for d\n"); 177 + goto failure; 178 + } 179 + if (lh_retrieve(lh, "d") != NULL || lh_error(lh) != 0) { 180 + fprintf(stderr, "FAIL: retrieved d after deletion\n"); 181 + goto failure; 182 + } 183 + 184 + if (lh_num_items(lh) != 0) { 185 + fprintf(stderr, "FAIL: lh_num_items() = %ld, want 0\n", 186 + lh_num_items(lh)); 187 + goto failure; 188 + } 189 + 190 + failed = 0; 191 + 192 + failure: 193 + lh_free(lh); 194 + 195 + return failed; 196 + } 197 + 198 + static void 199 + test_doall_fn(void *arg1) 26 200 { 27 201 } 28 202 ··· 38 212 39 213 /* Call doall multiple times while linked hash is empty. */ 40 214 for (i = 0; i < 100; i++) 41 - lh_doall_arg(lh, test_doall_fn, NULL); 215 + lh_doall(lh, test_doall_fn); 42 216 217 + failed = 0; 218 + 219 + failure: 43 220 lh_free(lh); 44 221 222 + return failed; 223 + } 224 + 225 + static void 226 + test_doall_delete_some(void *arg1, void *arg2) 227 + { 228 + void *data; 229 + 230 + if (arc4random_uniform(32) != 0) 231 + return; 232 + 233 + data = lh_delete(arg2, arg1); 234 + free(data); 235 + } 236 + 237 + static void 238 + test_doall_delete_all(void *arg1, void *arg2) 239 + { 240 + void *data; 241 + 242 + data = lh_delete(arg2, arg1); 243 + free(data); 244 + } 245 + 246 + static int 247 + test_lhash_load(void) 248 + { 249 + uint8_t c3 = 1, c2 = 1, c1 = 1, c0 = 1; 250 + _LHASH *lh; 251 + char *data = NULL; 252 + int i, j; 253 + int failed = 1; 254 + 255 + if ((lh = lh_new(NULL, NULL)) == NULL) 256 + goto failure; 257 + 258 + for (i = 0; i < 1024; i++) { 259 + for (j = 0; j < 1024; j++) { 260 + if ((data = calloc(1, 128)) == NULL) 261 + goto failure; 262 + 263 + data[0] = c0; 264 + data[1] = c1; 265 + data[2] = c2; 266 + data[3] = c3; 267 + 268 + if (++c0 == 0) { 269 + c0++; 270 + c1++; 271 + } 272 + if (c1 == 0) { 273 + c1++; 274 + c2++; 275 + } 276 + if (c2 == 0) { 277 + c2++; 278 + c3++; 279 + } 280 + 281 + if (lh_insert(lh, data) != NULL || lh_error(lh) != 0) { 282 + fprintf(stderr, "FAIL: lh_insert() failed\n"); 283 + goto failure; 284 + } 285 + data = NULL; 286 + } 287 + lh_doall_arg(lh, test_doall_delete_some, lh); 288 + } 289 + 290 + /* We should have ~31,713 entries. */ 291 + if (lh_num_items(lh) < 31000 || lh_num_items(lh) > 33000) { 292 + fprintf(stderr, "FAIL: unexpected number of entries (%ld)\n", 293 + lh_num_items(lh)); 294 + goto failure; 295 + } 296 + 45 297 failed = 0; 46 298 47 299 failure: 300 + if (lh != NULL) 301 + lh_doall_arg(lh, test_doall_delete_all, lh); 302 + 303 + lh_free(lh); 304 + free(data); 305 + 48 306 return failed; 49 307 } 50 308 ··· 53 311 { 54 312 int failed = 0; 55 313 314 + failed |= test_lhash(); 56 315 failed |= test_lhash_doall(); 316 + failed |= test_lhash_load(); 57 317 58 318 return failed; 59 319 }