test_containers.c (43900B)
1 /* Copyright (c) 2001-2004, Roger Dingledine. 2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 3 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 4 /* See LICENSE for licensing information */ 5 6 #include "orconfig.h" 7 #include "core/or/or.h" 8 #include "lib/crypt_ops/crypto_rand.h" 9 #include "feature/dircommon/fp_pair.h" 10 #include "test/test.h" 11 12 #include "lib/container/bitarray.h" 13 #include "lib/container/order.h" 14 #include "lib/crypt_ops/digestset.h" 15 16 /** Helper: return a tristate based on comparing the strings in *<b>a</b> and 17 * *<b>b</b>. */ 18 static int 19 compare_strs_(const void **a, const void **b) 20 { 21 const char *s1 = *a, *s2 = *b; 22 return strcmp(s1, s2); 23 } 24 25 /** Helper: return a tristate based on comparing the strings in <b>a</b> and 26 * *<b>b</b>. */ 27 static int 28 compare_strs_for_bsearch_(const void *a, const void **b) 29 { 30 const char *s1 = a, *s2 = *b; 31 return strcmp(s1, s2); 32 } 33 34 /** Helper: return a tristate based on comparing the strings in *<b>a</b> and 35 * *<b>b</b>, excluding a's first character, and ignoring case. */ 36 static int 37 cmp_without_first_(const void *a, const void **b) 38 { 39 const char *s1 = a, *s2 = *b; 40 return strcasecmp(s1+1, s2); 41 } 42 43 /** Run unit tests for basic dynamic-sized array functionality. */ 44 static void 45 test_container_smartlist_basic(void *arg) 46 { 47 smartlist_t *sl; 48 char *v0 = tor_strdup("v0"); 49 char *v1 = tor_strdup("v1"); 50 char *v2 = tor_strdup("v2"); 51 char *v3 = tor_strdup("v3"); 52 char *v4 = tor_strdup("v4"); 53 char *v22 = tor_strdup("v22"); 54 char *v99 = tor_strdup("v99"); 55 char *v555 = tor_strdup("v555"); 56 57 /* XXXX test sort_digests, uniq_strings, uniq_digests */ 58 59 /* Test smartlist add, del_keeporder, insert, get. */ 60 (void)arg; 61 sl = smartlist_new(); 62 smartlist_add(sl, v1); 63 smartlist_add(sl, v2); 64 smartlist_add(sl, v3); 65 smartlist_add(sl, v4); 66 smartlist_del_keeporder(sl, 1); 67 smartlist_insert(sl, 1, v22); 68 smartlist_insert(sl, 0, v0); 69 smartlist_insert(sl, 5, v555); 70 tt_ptr_op(v0,OP_EQ, smartlist_get(sl,0)); 71 tt_ptr_op(v1,OP_EQ, smartlist_get(sl,1)); 72 tt_ptr_op(v22,OP_EQ, smartlist_get(sl,2)); 73 tt_ptr_op(v3,OP_EQ, smartlist_get(sl,3)); 74 tt_ptr_op(v4,OP_EQ, smartlist_get(sl,4)); 75 tt_ptr_op(v555,OP_EQ, smartlist_get(sl,5)); 76 /* Try deleting in the middle. */ 77 smartlist_del(sl, 1); 78 tt_ptr_op(v555,OP_EQ, smartlist_get(sl, 1)); 79 /* Try deleting at the end. */ 80 smartlist_del(sl, 4); 81 tt_int_op(4,OP_EQ, smartlist_len(sl)); 82 83 /* test isin. */ 84 tt_assert(smartlist_contains(sl, v3)); 85 tt_assert(!smartlist_contains(sl, v99)); 86 87 done: 88 smartlist_free(sl); 89 tor_free(v0); 90 tor_free(v1); 91 tor_free(v2); 92 tor_free(v3); 93 tor_free(v4); 94 tor_free(v22); 95 tor_free(v99); 96 tor_free(v555); 97 } 98 99 /** Test SMARTLIST_FOREACH_REVERSE_BEGIN loop macro */ 100 static void 101 test_container_smartlist_foreach_reverse(void *arg) 102 { 103 smartlist_t *sl = smartlist_new(); 104 int i; 105 106 (void) arg; 107 108 /* Add integers to smartlist in increasing order */ 109 for (i=0;i<100;i++) { 110 smartlist_add(sl, (void*)(uintptr_t)i); 111 } 112 113 /* Pop them out in reverse and test their value */ 114 SMARTLIST_FOREACH_REVERSE_BEGIN(sl, void*, k) { 115 i--; 116 tt_ptr_op(k, OP_EQ, (void*)(uintptr_t)i); 117 } SMARTLIST_FOREACH_END(k); 118 119 done: 120 smartlist_free(sl); 121 } 122 123 /** Run unit tests for smartlist-of-strings functionality. */ 124 static void 125 test_container_smartlist_strings(void *arg) 126 { 127 smartlist_t *sl = smartlist_new(); 128 char *cp=NULL, *cp_alloc=NULL; 129 size_t sz; 130 131 /* Test split and join */ 132 (void)arg; 133 tt_int_op(0,OP_EQ, smartlist_len(sl)); 134 smartlist_split_string(sl, "abc", ":", 0, 0); 135 tt_int_op(1,OP_EQ, smartlist_len(sl)); 136 tt_str_op("abc",OP_EQ, smartlist_get(sl, 0)); 137 smartlist_split_string(sl, "a::bc::", "::", 0, 0); 138 tt_int_op(4,OP_EQ, smartlist_len(sl)); 139 tt_str_op("a",OP_EQ, smartlist_get(sl, 1)); 140 tt_str_op("bc",OP_EQ, smartlist_get(sl, 2)); 141 tt_str_op("",OP_EQ, smartlist_get(sl, 3)); 142 cp_alloc = smartlist_join_strings(sl, "", 0, NULL); 143 tt_str_op(cp_alloc,OP_EQ, "abcabc"); 144 tor_free(cp_alloc); 145 cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); 146 tt_str_op(cp_alloc,OP_EQ, "abc!a!bc!"); 147 tor_free(cp_alloc); 148 cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); 149 tt_str_op(cp_alloc,OP_EQ, "abcXYaXYbcXY"); 150 tor_free(cp_alloc); 151 cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); 152 tt_str_op(cp_alloc,OP_EQ, "abcXYaXYbcXYXY"); 153 tor_free(cp_alloc); 154 cp_alloc = smartlist_join_strings(sl, "", 1, NULL); 155 tt_str_op(cp_alloc,OP_EQ, "abcabc"); 156 tor_free(cp_alloc); 157 158 smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); 159 tt_int_op(8,OP_EQ, smartlist_len(sl)); 160 tt_str_op("",OP_EQ, smartlist_get(sl, 4)); 161 tt_str_op("def",OP_EQ, smartlist_get(sl, 5)); 162 tt_str_op(" ",OP_EQ, smartlist_get(sl, 6)); 163 tt_str_op("ghijk",OP_EQ, smartlist_get(sl, 7)); 164 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 165 smartlist_clear(sl); 166 167 smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); 168 tt_int_op(3,OP_EQ, smartlist_len(sl)); 169 tt_str_op("a",OP_EQ, smartlist_get(sl,0)); 170 tt_str_op("bbd",OP_EQ, smartlist_get(sl,1)); 171 tt_str_op("cdef",OP_EQ, smartlist_get(sl,2)); 172 smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", 173 SPLIT_SKIP_SPACE, 0); 174 tt_int_op(8,OP_EQ, smartlist_len(sl)); 175 tt_str_op("z",OP_EQ, smartlist_get(sl,3)); 176 tt_str_op("zhasd",OP_EQ, smartlist_get(sl,4)); 177 tt_str_op("",OP_EQ, smartlist_get(sl,5)); 178 tt_str_op("bnud",OP_EQ, smartlist_get(sl,6)); 179 tt_str_op("",OP_EQ, smartlist_get(sl,7)); 180 181 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 182 smartlist_clear(sl); 183 184 smartlist_split_string(sl, " ab\tc \td ef ", NULL, 185 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); 186 tt_int_op(4,OP_EQ, smartlist_len(sl)); 187 tt_str_op("ab",OP_EQ, smartlist_get(sl,0)); 188 tt_str_op("c",OP_EQ, smartlist_get(sl,1)); 189 tt_str_op("d",OP_EQ, smartlist_get(sl,2)); 190 tt_str_op("ef",OP_EQ, smartlist_get(sl,3)); 191 smartlist_split_string(sl, "ghi\tj", NULL, 192 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); 193 tt_int_op(6,OP_EQ, smartlist_len(sl)); 194 tt_str_op("ghi",OP_EQ, smartlist_get(sl,4)); 195 tt_str_op("j",OP_EQ, smartlist_get(sl,5)); 196 197 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 198 smartlist_clear(sl); 199 200 cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); 201 tt_str_op(cp_alloc,OP_EQ, ""); 202 tor_free(cp_alloc); 203 cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); 204 tt_str_op(cp_alloc,OP_EQ, "XY"); 205 tor_free(cp_alloc); 206 207 smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", 208 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); 209 tt_int_op(3,OP_EQ, smartlist_len(sl)); 210 tt_str_op("z",OP_EQ, smartlist_get(sl, 0)); 211 tt_str_op("zhasd",OP_EQ, smartlist_get(sl, 1)); 212 tt_str_op("bnud",OP_EQ, smartlist_get(sl, 2)); 213 smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", 214 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); 215 tt_int_op(5,OP_EQ, smartlist_len(sl)); 216 tt_str_op("z",OP_EQ, smartlist_get(sl, 3)); 217 tt_str_op("zhasd <> <> bnud<>",OP_EQ, smartlist_get(sl, 4)); 218 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 219 smartlist_clear(sl); 220 221 smartlist_split_string(sl, "abcd\n", "\n", 222 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); 223 tt_int_op(1,OP_EQ, smartlist_len(sl)); 224 tt_str_op("abcd",OP_EQ, smartlist_get(sl, 0)); 225 smartlist_split_string(sl, "efgh", "\n", 226 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); 227 tt_int_op(2,OP_EQ, smartlist_len(sl)); 228 tt_str_op("efgh",OP_EQ, smartlist_get(sl, 1)); 229 230 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 231 smartlist_clear(sl); 232 233 /* Test swapping, shuffling, and sorting. */ 234 smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); 235 tt_int_op(7,OP_EQ, smartlist_len(sl)); 236 smartlist_sort(sl, compare_strs_); 237 cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); 238 tt_str_op(cp_alloc,OP_EQ, "and,arma,by,nickm,onion,router,the"); 239 tor_free(cp_alloc); 240 smartlist_swap(sl, 1, 5); 241 cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); 242 tt_str_op(cp_alloc,OP_EQ, "and,router,by,nickm,onion,arma,the"); 243 tor_free(cp_alloc); 244 smartlist_shuffle(sl); 245 tt_int_op(7,OP_EQ, smartlist_len(sl)); 246 tt_assert(smartlist_contains_string(sl, "and")); 247 tt_assert(smartlist_contains_string(sl, "router")); 248 tt_assert(smartlist_contains_string(sl, "by")); 249 tt_assert(smartlist_contains_string(sl, "nickm")); 250 tt_assert(smartlist_contains_string(sl, "onion")); 251 tt_assert(smartlist_contains_string(sl, "arma")); 252 tt_assert(smartlist_contains_string(sl, "the")); 253 254 /* Test bsearch. */ 255 smartlist_sort(sl, compare_strs_); 256 tt_str_op("nickm",OP_EQ, smartlist_bsearch(sl, "zNicKM", 257 cmp_without_first_)); 258 tt_str_op("and",OP_EQ, 259 smartlist_bsearch(sl, " AND", cmp_without_first_)); 260 tt_ptr_op(NULL,OP_EQ, smartlist_bsearch(sl, " ANz", cmp_without_first_)); 261 262 /* Test bsearch_idx */ 263 { 264 int f; 265 smartlist_t *tmp = NULL; 266 267 tt_int_op(0,OP_EQ,smartlist_bsearch_idx(sl," aaa",cmp_without_first_,&f)); 268 tt_int_op(f,OP_EQ, 0); 269 tt_int_op(0,OP_EQ, smartlist_bsearch_idx(sl," and",cmp_without_first_,&f)); 270 tt_int_op(f,OP_EQ, 1); 271 tt_int_op(1,OP_EQ, smartlist_bsearch_idx(sl," arm",cmp_without_first_,&f)); 272 tt_int_op(f,OP_EQ, 0); 273 tt_int_op(1,OP_EQ, 274 smartlist_bsearch_idx(sl," arma",cmp_without_first_,&f)); 275 tt_int_op(f,OP_EQ, 1); 276 tt_int_op(2,OP_EQ, 277 smartlist_bsearch_idx(sl," armb",cmp_without_first_,&f)); 278 tt_int_op(f,OP_EQ, 0); 279 tt_int_op(7,OP_EQ, 280 smartlist_bsearch_idx(sl," zzzz",cmp_without_first_,&f)); 281 tt_int_op(f,OP_EQ, 0); 282 283 /* Test trivial cases for list of length 0 or 1 */ 284 tmp = smartlist_new(); 285 tt_int_op(0,OP_EQ, smartlist_bsearch_idx(tmp, "foo", 286 compare_strs_for_bsearch_, &f)); 287 tt_int_op(f,OP_EQ, 0); 288 smartlist_insert(tmp, 0, (void *)("bar")); 289 tt_int_op(1,OP_EQ, smartlist_bsearch_idx(tmp, "foo", 290 compare_strs_for_bsearch_, &f)); 291 tt_int_op(f,OP_EQ, 0); 292 tt_int_op(0,OP_EQ, smartlist_bsearch_idx(tmp, "aaa", 293 compare_strs_for_bsearch_, &f)); 294 tt_int_op(f,OP_EQ, 0); 295 tt_int_op(0,OP_EQ, smartlist_bsearch_idx(tmp, "bar", 296 compare_strs_for_bsearch_, &f)); 297 tt_int_op(f,OP_EQ, 1); 298 /* ... and one for length 2 */ 299 smartlist_insert(tmp, 1, (void *)("foo")); 300 tt_int_op(1,OP_EQ, smartlist_bsearch_idx(tmp, "foo", 301 compare_strs_for_bsearch_, &f)); 302 tt_int_op(f,OP_EQ, 1); 303 tt_int_op(2,OP_EQ, smartlist_bsearch_idx(tmp, "goo", 304 compare_strs_for_bsearch_, &f)); 305 tt_int_op(f,OP_EQ, 0); 306 smartlist_free(tmp); 307 } 308 309 /* Test reverse() and pop_last() */ 310 smartlist_reverse(sl); 311 cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); 312 tt_str_op(cp_alloc,OP_EQ, "the,router,onion,nickm,by,arma,and"); 313 tor_free(cp_alloc); 314 cp_alloc = smartlist_pop_last(sl); 315 tt_str_op(cp_alloc,OP_EQ, "and"); 316 tor_free(cp_alloc); 317 tt_int_op(smartlist_len(sl),OP_EQ, 6); 318 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 319 smartlist_clear(sl); 320 cp_alloc = smartlist_pop_last(sl); 321 tt_ptr_op(cp_alloc,OP_EQ, NULL); 322 323 /* Test uniq() */ 324 smartlist_split_string(sl, 325 "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", 326 ",", 0, 0); 327 smartlist_sort(sl, compare_strs_); 328 smartlist_uniq(sl, compare_strs_, tor_free_); 329 cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); 330 tt_str_op(cp_alloc,OP_EQ, "50,a,canal,man,noon,panama,plan,radar"); 331 tor_free(cp_alloc); 332 333 /* Test contains_string, contains_string_case and contains_int_as_string */ 334 tt_assert(smartlist_contains_string(sl, "noon")); 335 tt_assert(!smartlist_contains_string(sl, "noonoon")); 336 tt_assert(smartlist_contains_string_case(sl, "nOOn")); 337 tt_assert(!smartlist_contains_string_case(sl, "nooNooN")); 338 tt_assert(smartlist_contains_int_as_string(sl, 50)); 339 tt_assert(!smartlist_contains_int_as_string(sl, 60)); 340 341 /* Test smartlist_choose */ 342 { 343 int i; 344 int allsame = 1; 345 int allin = 1; 346 void *first = smartlist_choose(sl); 347 tt_assert(smartlist_contains(sl, first)); 348 for (i = 0; i < 100; ++i) { 349 void *second = smartlist_choose(sl); 350 if (second != first) 351 allsame = 0; 352 if (!smartlist_contains(sl, second)) 353 allin = 0; 354 } 355 tt_assert(!allsame); 356 tt_assert(allin); 357 } 358 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 359 smartlist_clear(sl); 360 361 /* Test string_remove and remove and join_strings2 */ 362 smartlist_split_string(sl, 363 "Some say the Earth will end in ice and some in fire", 364 " ", 0, 0); 365 cp = smartlist_get(sl, 4); 366 tt_str_op(cp,OP_EQ, "will"); 367 smartlist_add(sl, cp); 368 smartlist_remove(sl, cp); 369 tor_free(cp); 370 cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); 371 tt_str_op(cp_alloc,OP_EQ, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); 372 tor_free(cp_alloc); 373 smartlist_string_remove(sl, "in"); 374 cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); 375 tt_str_op(cp_alloc,OP_EQ, "Some+say+the+Earth+fire+end+some+ice+and"); 376 tt_int_op((int)sz,OP_EQ, 40); 377 378 done: 379 380 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 381 smartlist_free(sl); 382 tor_free(cp_alloc); 383 } 384 385 /** Run unit tests for smartlist set manipulation functions. */ 386 static void 387 test_container_smartlist_overlap(void *arg) 388 { 389 smartlist_t *sl = smartlist_new(); 390 smartlist_t *ints = smartlist_new(); 391 smartlist_t *odds = smartlist_new(); 392 smartlist_t *evens = smartlist_new(); 393 smartlist_t *primes = smartlist_new(); 394 int i; 395 (void)arg; 396 for (i=1; i < 10; i += 2) 397 smartlist_add(odds, (void*)(uintptr_t)i); 398 for (i=0; i < 10; i += 2) 399 smartlist_add(evens, (void*)(uintptr_t)i); 400 401 /* add_all */ 402 smartlist_add_all(ints, odds); 403 smartlist_add_all(ints, evens); 404 tt_int_op(smartlist_len(ints),OP_EQ, 10); 405 406 smartlist_add(primes, (void*)2); 407 smartlist_add(primes, (void*)3); 408 smartlist_add(primes, (void*)5); 409 smartlist_add(primes, (void*)7); 410 411 /* overlap */ 412 tt_assert(smartlist_overlap(ints, odds)); 413 tt_assert(smartlist_overlap(odds, primes)); 414 tt_assert(smartlist_overlap(evens, primes)); 415 tt_assert(!smartlist_overlap(odds, evens)); 416 417 /* intersect */ 418 smartlist_add_all(sl, odds); 419 smartlist_intersect(sl, primes); 420 tt_int_op(smartlist_len(sl),OP_EQ, 3); 421 tt_assert(smartlist_contains(sl, (void*)3)); 422 tt_assert(smartlist_contains(sl, (void*)5)); 423 tt_assert(smartlist_contains(sl, (void*)7)); 424 425 /* subtract */ 426 smartlist_add_all(sl, primes); 427 smartlist_subtract(sl, odds); 428 tt_int_op(smartlist_len(sl),OP_EQ, 1); 429 tt_assert(smartlist_contains(sl, (void*)2)); 430 431 done: 432 smartlist_free(odds); 433 smartlist_free(evens); 434 smartlist_free(ints); 435 smartlist_free(primes); 436 smartlist_free(sl); 437 } 438 439 /** Run unit tests for smartlist-of-digests functions. */ 440 static void 441 test_container_smartlist_digests(void *arg) 442 { 443 smartlist_t *sl = smartlist_new(); 444 445 /* contains_digest */ 446 (void)arg; 447 smartlist_add(sl, tor_memdup("AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN)); 448 smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); 449 smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN)); 450 tt_int_op(0,OP_EQ, smartlist_contains_digest(NULL, "AAAAAAAAAAAAAAAAAAAA")); 451 tt_assert(smartlist_contains_digest(sl, "AAAAAAAAAAAAAAAAAAAA")); 452 tt_assert(smartlist_contains_digest(sl, "\00090AAB2AAAAaasdAAAAA")); 453 tt_int_op(0,OP_EQ, smartlist_contains_digest(sl, "\00090AAB2AAABaasdAAAAA")); 454 455 /* sort digests */ 456 smartlist_sort_digests(sl); 457 tt_mem_op(smartlist_get(sl, 0),OP_EQ, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); 458 tt_mem_op(smartlist_get(sl, 1),OP_EQ, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); 459 tt_mem_op(smartlist_get(sl, 2),OP_EQ, "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); 460 tt_int_op(3,OP_EQ, smartlist_len(sl)); 461 462 /* uniq_digests */ 463 smartlist_uniq_digests(sl); 464 tt_int_op(2,OP_EQ, smartlist_len(sl)); 465 tt_mem_op(smartlist_get(sl, 0),OP_EQ, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN); 466 tt_mem_op(smartlist_get(sl, 1),OP_EQ, "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN); 467 468 done: 469 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 470 smartlist_free(sl); 471 } 472 473 /** Run unit tests for concatenate-a-smartlist-of-strings functions. */ 474 static void 475 test_container_smartlist_join(void *arg) 476 { 477 smartlist_t *sl = smartlist_new(); 478 smartlist_t *sl2 = smartlist_new(), *sl3 = smartlist_new(), 479 *sl4 = smartlist_new(); 480 char *joined=NULL; 481 /* unique, sorted. */ 482 (void)arg; 483 smartlist_split_string(sl, 484 "Abashments Ambush Anchorman Bacon Banks Borscht " 485 "Bunks Inhumane Insurance Knish Know Manners " 486 "Maraschinos Stamina Sunbonnets Unicorns Wombats", 487 " ", 0, 0); 488 /* non-unique, sorted. */ 489 smartlist_split_string(sl2, 490 "Ambush Anchorman Anchorman Anemias Anemias Bacon " 491 "Crossbowmen Inhumane Insurance Knish Know Manners " 492 "Manners Maraschinos Wombats Wombats Work", 493 " ", 0, 0); 494 SMARTLIST_FOREACH_JOIN(sl, char *, cp1, 495 sl2, char *, cp2, 496 strcmp(cp1,cp2), 497 smartlist_add(sl3, cp2)) { 498 tt_str_op(cp1,OP_EQ, cp2); 499 smartlist_add(sl4, cp1); 500 } SMARTLIST_FOREACH_JOIN_END(cp1, cp2); 501 502 SMARTLIST_FOREACH(sl3, const char *, cp, 503 tt_assert(smartlist_contains(sl2, cp) && 504 !smartlist_contains_string(sl, cp))); 505 SMARTLIST_FOREACH(sl4, const char *, cp, 506 tt_assert(smartlist_contains(sl, cp) && 507 smartlist_contains_string(sl2, cp))); 508 joined = smartlist_join_strings(sl3, ",", 0, NULL); 509 tt_str_op(joined,OP_EQ, "Anemias,Anemias,Crossbowmen,Work"); 510 tor_free(joined); 511 joined = smartlist_join_strings(sl4, ",", 0, NULL); 512 tt_str_op(joined,OP_EQ, 513 "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance," 514 "Knish,Know,Manners,Manners,Maraschinos,Wombats,Wombats"); 515 tor_free(joined); 516 517 done: 518 smartlist_free(sl4); 519 smartlist_free(sl3); 520 SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); 521 smartlist_free(sl2); 522 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 523 smartlist_free(sl); 524 tor_free(joined); 525 } 526 527 static void 528 test_container_smartlist_pos(void *arg) 529 { 530 (void) arg; 531 smartlist_t *sl = smartlist_new(); 532 533 smartlist_add_strdup(sl, "This"); 534 smartlist_add_strdup(sl, "is"); 535 smartlist_add_strdup(sl, "a"); 536 smartlist_add_strdup(sl, "test"); 537 smartlist_add_strdup(sl, "for"); 538 smartlist_add_strdup(sl, "a"); 539 smartlist_add_strdup(sl, "function"); 540 541 /* Test string_pos */ 542 tt_int_op(smartlist_string_pos(NULL, "Fred"), OP_EQ, -1); 543 tt_int_op(smartlist_string_pos(sl, "Fred"), OP_EQ, -1); 544 tt_int_op(smartlist_string_pos(sl, "This"), OP_EQ, 0); 545 tt_int_op(smartlist_string_pos(sl, "a"), OP_EQ, 2); 546 tt_int_op(smartlist_string_pos(sl, "function"), OP_EQ, 6); 547 548 /* Test pos */ 549 tt_int_op(smartlist_pos(NULL, "Fred"), OP_EQ, -1); 550 tt_int_op(smartlist_pos(sl, "Fred"), OP_EQ, -1); 551 tt_int_op(smartlist_pos(sl, "This"), OP_EQ, -1); 552 tt_int_op(smartlist_pos(sl, "a"), OP_EQ, -1); 553 tt_int_op(smartlist_pos(sl, "function"), OP_EQ, -1); 554 tt_int_op(smartlist_pos(sl, smartlist_get(sl,0)), OP_EQ, 0); 555 tt_int_op(smartlist_pos(sl, smartlist_get(sl,2)), OP_EQ, 2); 556 tt_int_op(smartlist_pos(sl, smartlist_get(sl,5)), OP_EQ, 5); 557 tt_int_op(smartlist_pos(sl, smartlist_get(sl,6)), OP_EQ, 6); 558 559 done: 560 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 561 smartlist_free(sl); 562 } 563 564 static void 565 test_container_smartlist_ints_eq(void *arg) 566 { 567 smartlist_t *sl1 = NULL, *sl2 = NULL; 568 int x; 569 (void)arg; 570 571 tt_assert(smartlist_ints_eq(NULL, NULL)); 572 573 sl1 = smartlist_new(); 574 tt_assert(!smartlist_ints_eq(sl1, NULL)); 575 tt_assert(!smartlist_ints_eq(NULL, sl1)); 576 577 sl2 = smartlist_new(); 578 tt_assert(smartlist_ints_eq(sl1, sl2)); 579 580 x = 5; 581 smartlist_add(sl1, tor_memdup(&x, sizeof(int))); 582 smartlist_add(sl2, tor_memdup(&x, sizeof(int))); 583 x = 90; 584 smartlist_add(sl1, tor_memdup(&x, sizeof(int))); 585 smartlist_add(sl2, tor_memdup(&x, sizeof(int))); 586 tt_assert(smartlist_ints_eq(sl1, sl2)); 587 588 x = -50; 589 smartlist_add(sl1, tor_memdup(&x, sizeof(int))); 590 tt_assert(! smartlist_ints_eq(sl1, sl2)); 591 tt_assert(! smartlist_ints_eq(sl2, sl1)); 592 smartlist_add(sl2, tor_memdup(&x, sizeof(int))); 593 tt_assert(smartlist_ints_eq(sl1, sl2)); 594 595 *(int*)smartlist_get(sl1, 1) = 101010; 596 tt_assert(! smartlist_ints_eq(sl2, sl1)); 597 *(int*)smartlist_get(sl2, 1) = 101010; 598 tt_assert(smartlist_ints_eq(sl1, sl2)); 599 600 done: 601 if (sl1) 602 SMARTLIST_FOREACH(sl1, int *, ip, tor_free(ip)); 603 if (sl2) 604 SMARTLIST_FOREACH(sl2, int *, ip, tor_free(ip)); 605 smartlist_free(sl1); 606 smartlist_free(sl2); 607 } 608 609 static void 610 test_container_smartlist_grow(void *arg) 611 { 612 (void)arg; 613 smartlist_t *sl = smartlist_new(); 614 int i; 615 const char *s[] = { "first", "2nd", "3rd" }; 616 617 /* case 1: starting from empty. */ 618 smartlist_grow(sl, 10); 619 tt_int_op(10, OP_EQ, smartlist_len(sl)); 620 for (i = 0; i < 10; ++i) { 621 tt_ptr_op(smartlist_get(sl, i), OP_EQ, NULL); 622 } 623 624 /* case 2: starting with a few elements, probably not reallocating. */ 625 smartlist_free(sl); 626 sl = smartlist_new(); 627 smartlist_add(sl, (char*)s[0]); 628 smartlist_add(sl, (char*)s[1]); 629 smartlist_add(sl, (char*)s[2]); 630 smartlist_grow(sl, 5); 631 tt_int_op(5, OP_EQ, smartlist_len(sl)); 632 for (i = 0; i < 3; ++i) { 633 tt_ptr_op(smartlist_get(sl, i), OP_EQ, s[i]); 634 } 635 tt_ptr_op(smartlist_get(sl, 3), OP_EQ, NULL); 636 tt_ptr_op(smartlist_get(sl, 4), OP_EQ, NULL); 637 638 /* case 3: starting with a few elements, but reallocating. */ 639 smartlist_free(sl); 640 sl = smartlist_new(); 641 smartlist_add(sl, (char*)s[0]); 642 smartlist_add(sl, (char*)s[1]); 643 smartlist_add(sl, (char*)s[2]); 644 smartlist_grow(sl, 100); 645 tt_int_op(100, OP_EQ, smartlist_len(sl)); 646 for (i = 0; i < 3; ++i) { 647 tt_ptr_op(smartlist_get(sl, i), OP_EQ, s[i]); 648 } 649 for (i = 3; i < 100; ++i) { 650 tt_ptr_op(smartlist_get(sl, i), OP_EQ, NULL); 651 } 652 653 /* case 4: shrinking doesn't happen. */ 654 smartlist_free(sl); 655 sl = smartlist_new(); 656 smartlist_add(sl, (char*)s[0]); 657 smartlist_add(sl, (char*)s[1]); 658 smartlist_add(sl, (char*)s[2]); 659 smartlist_grow(sl, 1); 660 tt_int_op(3, OP_EQ, smartlist_len(sl)); 661 for (i = 0; i < 3; ++i) { 662 tt_ptr_op(smartlist_get(sl, i), OP_EQ, s[i]); 663 } 664 665 done: 666 smartlist_free(sl); 667 } 668 669 /** Run unit tests for bitarray code */ 670 static void 671 test_container_bitarray(void *arg) 672 { 673 bitarray_t *ba = NULL; 674 int i, j, ok=1; 675 676 (void)arg; 677 ba = bitarray_init_zero(1); 678 tt_assert(ba); 679 tt_assert(! bitarray_is_set(ba, 0)); 680 bitarray_set(ba, 0); 681 tt_assert(bitarray_is_set(ba, 0)); 682 bitarray_clear(ba, 0); 683 tt_assert(! bitarray_is_set(ba, 0)); 684 bitarray_free(ba); 685 686 ba = bitarray_init_zero(1023); 687 for (i = 1; i < 64; ) { 688 for (j = 0; j < 1023; ++j) { 689 if (j % i) 690 bitarray_set(ba, j); 691 else 692 bitarray_clear(ba, j); 693 } 694 for (j = 0; j < 1023; ++j) { 695 if (!bool_eq(bitarray_is_set(ba, j), j%i)) 696 ok = 0; 697 } 698 tt_assert(ok); 699 if (i < 7) 700 ++i; 701 else if (i == 28) 702 i = 32; 703 else 704 i += 7; 705 } 706 707 done: 708 if (ba) 709 bitarray_free(ba); 710 } 711 712 /** Run unit tests for digest set code (implemented as a hashtable or as a 713 * bloom filter) */ 714 static void 715 test_container_digestset(void *arg) 716 { 717 smartlist_t *included = smartlist_new(); 718 char d[DIGEST_LEN]; 719 int i; 720 int ok = 1; 721 int false_positives = 0; 722 digestset_t *set = NULL; 723 724 (void)arg; 725 for (i = 0; i < 1000; ++i) { 726 crypto_rand(d, DIGEST_LEN); 727 smartlist_add(included, tor_memdup(d, DIGEST_LEN)); 728 } 729 set = digestset_new(1000); 730 SMARTLIST_FOREACH(included, const char *, cp, 731 if (digestset_probably_contains(set, cp)) 732 ok = 0); 733 tt_assert(ok); 734 SMARTLIST_FOREACH(included, const char *, cp, 735 digestset_add(set, cp)); 736 SMARTLIST_FOREACH(included, const char *, cp, 737 if (!digestset_probably_contains(set, cp)) 738 ok = 0); 739 tt_assert(ok); 740 for (i = 0; i < 1000; ++i) { 741 crypto_rand(d, DIGEST_LEN); 742 if (digestset_probably_contains(set, d)) 743 ++false_positives; 744 } 745 tt_int_op(50, OP_GT, false_positives); /* Should be far lower. */ 746 747 done: 748 if (set) 749 digestset_free(set); 750 SMARTLIST_FOREACH(included, char *, cp, tor_free(cp)); 751 smartlist_free(included); 752 } 753 754 typedef struct pq_entry_t { 755 const char *val; 756 int idx; 757 } pq_entry_t; 758 759 /** Helper: return a tristate based on comparing two pq_entry_t values. */ 760 static int 761 compare_strings_for_pqueue_(const void *p1, const void *p2) 762 { 763 const pq_entry_t *e1=p1, *e2=p2; 764 return strcmp(e1->val, e2->val); 765 } 766 767 /** Run unit tests for heap-based priority queue functions. */ 768 static void 769 test_container_pqueue(void *arg) 770 { 771 smartlist_t *sl = smartlist_new(); 772 int (*cmp)(const void *, const void*); 773 const int offset = offsetof(pq_entry_t, idx); 774 #define ENTRY(s) pq_entry_t s = { #s, -1 } 775 ENTRY(cows); 776 ENTRY(zebras); 777 ENTRY(fish); 778 ENTRY(frogs); 779 ENTRY(apples); 780 ENTRY(squid); 781 ENTRY(daschunds); 782 ENTRY(eggplants); 783 ENTRY(weissbier); 784 ENTRY(lobsters); 785 ENTRY(roquefort); 786 ENTRY(chinchillas); 787 ENTRY(fireflies); 788 789 #define OK() smartlist_pqueue_assert_ok(sl, cmp, offset) 790 791 (void)arg; 792 793 cmp = compare_strings_for_pqueue_; 794 smartlist_pqueue_add(sl, cmp, offset, &cows); 795 smartlist_pqueue_add(sl, cmp, offset, &zebras); 796 smartlist_pqueue_add(sl, cmp, offset, &fish); 797 smartlist_pqueue_add(sl, cmp, offset, &frogs); 798 smartlist_pqueue_add(sl, cmp, offset, &apples); 799 smartlist_pqueue_add(sl, cmp, offset, &squid); 800 smartlist_pqueue_add(sl, cmp, offset, &daschunds); 801 smartlist_pqueue_add(sl, cmp, offset, &eggplants); 802 smartlist_pqueue_add(sl, cmp, offset, &weissbier); 803 smartlist_pqueue_add(sl, cmp, offset, &lobsters); 804 smartlist_pqueue_add(sl, cmp, offset, &roquefort); 805 806 OK(); 807 808 tt_int_op(smartlist_len(sl),OP_EQ, 11); 809 tt_ptr_op(smartlist_get(sl, 0),OP_EQ, &apples); 810 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &apples); 811 tt_int_op(smartlist_len(sl),OP_EQ, 10); 812 OK(); 813 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &cows); 814 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &daschunds); 815 smartlist_pqueue_add(sl, cmp, offset, &chinchillas); 816 OK(); 817 smartlist_pqueue_add(sl, cmp, offset, &fireflies); 818 OK(); 819 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &chinchillas); 820 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &eggplants); 821 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &fireflies); 822 OK(); 823 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &fish); 824 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &frogs); 825 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &lobsters); 826 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &roquefort); 827 OK(); 828 tt_int_op(smartlist_len(sl),OP_EQ, 3); 829 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &squid); 830 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &weissbier); 831 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &zebras); 832 tt_int_op(smartlist_len(sl),OP_EQ, 0); 833 OK(); 834 835 /* Now test remove. */ 836 smartlist_pqueue_add(sl, cmp, offset, &cows); 837 smartlist_pqueue_add(sl, cmp, offset, &fish); 838 smartlist_pqueue_add(sl, cmp, offset, &frogs); 839 smartlist_pqueue_add(sl, cmp, offset, &apples); 840 smartlist_pqueue_add(sl, cmp, offset, &squid); 841 smartlist_pqueue_add(sl, cmp, offset, &zebras); 842 tt_int_op(smartlist_len(sl),OP_EQ, 6); 843 OK(); 844 smartlist_pqueue_remove(sl, cmp, offset, &zebras); 845 tt_int_op(smartlist_len(sl),OP_EQ, 5); 846 OK(); 847 smartlist_pqueue_remove(sl, cmp, offset, &cows); 848 tt_int_op(smartlist_len(sl),OP_EQ, 4); 849 OK(); 850 smartlist_pqueue_remove(sl, cmp, offset, &apples); 851 tt_int_op(smartlist_len(sl),OP_EQ, 3); 852 OK(); 853 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &fish); 854 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &frogs); 855 tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),OP_EQ, &squid); 856 tt_int_op(smartlist_len(sl),OP_EQ, 0); 857 OK(); 858 859 #undef OK 860 861 done: 862 863 smartlist_free(sl); 864 } 865 866 /** Run unit tests for string-to-void* map functions */ 867 static void 868 test_container_strmap(void *arg) 869 { 870 strmap_t *map; 871 strmap_iter_t *iter; 872 const char *k; 873 void *v; 874 char *visited = NULL; 875 smartlist_t *found_keys = NULL; 876 char *v1 = tor_strdup("v1"); 877 char *v99 = tor_strdup("v99"); 878 char *v100 = tor_strdup("v100"); 879 char *v101 = tor_strdup("v101"); 880 char *v102 = tor_strdup("v102"); 881 char *v103 = tor_strdup("v103"); 882 char *v104 = tor_strdup("v104"); 883 char *v105 = tor_strdup("v105"); 884 885 (void)arg; 886 map = strmap_new(); 887 tt_assert(map); 888 tt_int_op(strmap_size(map),OP_EQ, 0); 889 tt_assert(strmap_isempty(map)); 890 v = strmap_set(map, "K1", v99); 891 tt_ptr_op(v,OP_EQ, NULL); 892 tt_assert(!strmap_isempty(map)); 893 v = strmap_set(map, "K2", v101); 894 tt_ptr_op(v,OP_EQ, NULL); 895 v = strmap_set(map, "K1", v100); 896 tt_ptr_op(v,OP_EQ, v99); 897 tt_ptr_op(strmap_get(map,"K1"),OP_EQ, v100); 898 tt_ptr_op(strmap_get(map,"K2"),OP_EQ, v101); 899 tt_ptr_op(strmap_get(map,"K-not-there"),OP_EQ, NULL); 900 strmap_assert_ok(map); 901 902 v = strmap_remove(map,"K2"); 903 strmap_assert_ok(map); 904 tt_ptr_op(v,OP_EQ, v101); 905 tt_ptr_op(strmap_get(map,"K2"),OP_EQ, NULL); 906 tt_ptr_op(strmap_remove(map,"K2"),OP_EQ, NULL); 907 908 strmap_set(map, "K2", v101); 909 strmap_set(map, "K3", v102); 910 strmap_set(map, "K4", v103); 911 tt_int_op(strmap_size(map),OP_EQ, 4); 912 strmap_assert_ok(map); 913 strmap_set(map, "K5", v104); 914 strmap_set(map, "K6", v105); 915 strmap_assert_ok(map); 916 917 /* Test iterator. */ 918 iter = strmap_iter_init(map); 919 found_keys = smartlist_new(); 920 while (!strmap_iter_done(iter)) { 921 strmap_iter_get(iter,&k,&v); 922 smartlist_add_strdup(found_keys, k); 923 tt_ptr_op(v,OP_EQ, strmap_get(map, k)); 924 925 if (!strcmp(k, "K2")) { 926 iter = strmap_iter_next_rmv(map,iter); 927 } else { 928 iter = strmap_iter_next(map,iter); 929 } 930 } 931 932 /* Make sure we removed K2, but not the others. */ 933 tt_ptr_op(strmap_get(map, "K2"),OP_EQ, NULL); 934 tt_ptr_op(strmap_get(map, "K5"),OP_EQ, v104); 935 /* Make sure we visited everyone once */ 936 smartlist_sort_strings(found_keys); 937 visited = smartlist_join_strings(found_keys, ":", 0, NULL); 938 tt_str_op(visited,OP_EQ, "K1:K2:K3:K4:K5:K6"); 939 940 strmap_assert_ok(map); 941 /* Clean up after ourselves. */ 942 strmap_free(map, NULL); 943 map = NULL; 944 945 /* Now try some lc functions. */ 946 map = strmap_new(); 947 strmap_set_lc(map,"Ab.C", v1); 948 tt_ptr_op(strmap_get(map,"ab.c"),OP_EQ, v1); 949 strmap_assert_ok(map); 950 tt_ptr_op(strmap_get_lc(map,"AB.C"),OP_EQ, v1); 951 tt_ptr_op(strmap_get(map,"AB.C"),OP_EQ, NULL); 952 tt_ptr_op(strmap_remove_lc(map,"aB.C"),OP_EQ, v1); 953 strmap_assert_ok(map); 954 tt_ptr_op(strmap_get_lc(map,"AB.C"),OP_EQ, NULL); 955 956 done: 957 if (map) 958 strmap_free(map,NULL); 959 if (found_keys) { 960 SMARTLIST_FOREACH(found_keys, char *, cp, tor_free(cp)); 961 smartlist_free(found_keys); 962 } 963 tor_free(visited); 964 tor_free(v1); 965 tor_free(v99); 966 tor_free(v100); 967 tor_free(v101); 968 tor_free(v102); 969 tor_free(v103); 970 tor_free(v104); 971 tor_free(v105); 972 } 973 974 static void 975 test_container_smartlist_remove(void *arg) 976 { 977 (void) arg; 978 int array[5]; 979 smartlist_t *sl = smartlist_new(); 980 int i,j; 981 982 for (j=0; j < 2; ++j) 983 for (i=0; i < 5; ++i) 984 smartlist_add(sl, &array[i]); 985 986 smartlist_remove(sl, &array[0]); 987 smartlist_remove(sl, &array[3]); 988 smartlist_remove(sl, &array[4]); 989 tt_assert(! smartlist_contains(sl, &array[0])); 990 tt_assert(smartlist_contains(sl, &array[1])); 991 tt_assert(smartlist_contains(sl, &array[2])); 992 tt_assert(! smartlist_contains(sl, &array[3])); 993 tt_assert(! smartlist_contains(sl, &array[4])); 994 tt_int_op(smartlist_len(sl), OP_EQ, 4); 995 996 smartlist_clear(sl); 997 for (j=0; j < 2; ++j) 998 for (i=0; i < 5; ++i) 999 smartlist_add(sl, &array[i]); 1000 1001 smartlist_remove_keeporder(sl, &array[0]); 1002 smartlist_remove_keeporder(sl, &array[3]); 1003 smartlist_remove_keeporder(sl, &array[4]); 1004 tt_int_op(smartlist_len(sl), OP_EQ, 4); 1005 tt_ptr_op(smartlist_get(sl, 0), OP_EQ, &array[1]); 1006 tt_ptr_op(smartlist_get(sl, 1), OP_EQ, &array[2]); 1007 tt_ptr_op(smartlist_get(sl, 2), OP_EQ, &array[1]); 1008 tt_ptr_op(smartlist_get(sl, 3), OP_EQ, &array[2]); 1009 /* Ordinary code should never look at this pointer; we're doing it here 1010 * to make sure that we really cleared the pointer we removed. 1011 */ 1012 tt_ptr_op(sl->list[4], OP_EQ, NULL); 1013 1014 done: 1015 smartlist_free(sl); 1016 } 1017 1018 /** Run unit tests for getting the median of a list. */ 1019 static void 1020 test_container_order_functions(void *arg) 1021 { 1022 int lst[25], n = 0; 1023 uint32_t lst_2[25]; 1024 // int a=12,b=24,c=25,d=60,e=77; 1025 1026 #define median() median_int(lst, n) 1027 1028 (void)arg; 1029 lst[n++] = 12; 1030 tt_int_op(12,OP_EQ, median()); /* 12 */ 1031 lst[n++] = 77; 1032 //smartlist_shuffle(sl); 1033 tt_int_op(12,OP_EQ, median()); /* 12, 77 */ 1034 lst[n++] = 77; 1035 //smartlist_shuffle(sl); 1036 tt_int_op(77,OP_EQ, median()); /* 12, 77, 77 */ 1037 lst[n++] = 24; 1038 tt_int_op(24,OP_EQ, median()); /* 12,24,77,77 */ 1039 lst[n++] = 60; 1040 lst[n++] = 12; 1041 lst[n++] = 25; 1042 //smartlist_shuffle(sl); 1043 tt_int_op(25,OP_EQ, median()); /* 12,12,24,25,60,77,77 */ 1044 #undef median 1045 1046 #define third_quartile() third_quartile_uint32(lst_2, n) 1047 1048 n = 0; 1049 lst_2[n++] = 1; 1050 tt_int_op(1,OP_EQ, third_quartile()); /* ~1~ */ 1051 lst_2[n++] = 2; 1052 tt_int_op(2,OP_EQ, third_quartile()); /* 1, ~2~ */ 1053 lst_2[n++] = 3; 1054 lst_2[n++] = 4; 1055 lst_2[n++] = 5; 1056 tt_int_op(4,OP_EQ, third_quartile()); /* 1, 2, 3, ~4~, 5 */ 1057 lst_2[n++] = 6; 1058 lst_2[n++] = 7; 1059 lst_2[n++] = 8; 1060 lst_2[n++] = 9; 1061 tt_int_op(7,OP_EQ, third_quartile()); /* 1, 2, 3, 4, 5, 6, ~7~, 8, 9 */ 1062 lst_2[n++] = 10; 1063 lst_2[n++] = 11; 1064 /* 1, 2, 3, 4, 5, 6, 7, 8, ~9~, 10, 11 */ 1065 tt_int_op(9,OP_EQ, third_quartile()); 1066 1067 #undef third_quartile 1068 1069 double dbls[] = { 1.0, 10.0, 100.0, 1e4, 1e5, 1e6 }; 1070 tt_double_eq(1.0, median_double(dbls, 1)); 1071 tt_double_eq(1.0, median_double(dbls, 2)); 1072 tt_double_eq(10.0, median_double(dbls, 3)); 1073 tt_double_eq(10.0, median_double(dbls, 4)); 1074 tt_double_eq(100.0, median_double(dbls, 5)); 1075 tt_double_eq(100.0, median_double(dbls, 6)); 1076 1077 time_t times[] = { 5, 10, 20, 25, 15 }; 1078 1079 tt_assert(5 == median_time(times, 1)); 1080 tt_assert(5 == median_time(times, 2)); 1081 tt_assert(10 == median_time(times, 3)); 1082 tt_assert(10 == median_time(times, 4)); 1083 tt_assert(15 == median_time(times, 5)); 1084 1085 int32_t int32s[] = { -5, -10, -50, 100 }; 1086 tt_int_op(-5, OP_EQ, median_int32(int32s, 1)); 1087 tt_int_op(-10, OP_EQ, median_int32(int32s, 2)); 1088 tt_int_op(-10, OP_EQ, median_int32(int32s, 3)); 1089 tt_int_op(-10, OP_EQ, median_int32(int32s, 4)); 1090 1091 long longs[] = { -30, 30, 100, -100, 7 }; 1092 tt_int_op(7, OP_EQ, find_nth_long(longs, 5, 2)); 1093 1094 done: 1095 ; 1096 } 1097 1098 static void 1099 test_container_di_map(void *arg) 1100 { 1101 di_digest256_map_t *map = NULL; 1102 const uint8_t key1[] = "In view of the fact that it was "; 1103 const uint8_t key2[] = "superficially convincing, being "; 1104 const uint8_t key3[] = "properly enciphered in a one-tim"; 1105 const uint8_t key4[] = "e cipher scheduled for use today"; 1106 char *v1 = tor_strdup(", it came close to causing a disaster..."); 1107 char *v2 = tor_strdup("I regret to have to advise you that the mission"); 1108 char *v3 = tor_strdup("was actually initiated..."); 1109 /* -- John Brunner, _The Shockwave Rider_ */ 1110 1111 (void)arg; 1112 1113 /* Try searching on an empty map. */ 1114 tt_ptr_op(NULL, OP_EQ, dimap_search(map, key1, NULL)); 1115 tt_ptr_op(NULL, OP_EQ, dimap_search(map, key2, NULL)); 1116 tt_ptr_op(v3, OP_EQ, dimap_search(map, key2, v3)); 1117 dimap_free(map, NULL); 1118 map = NULL; 1119 1120 /* Add a single entry. */ 1121 dimap_add_entry(&map, key1, v1); 1122 tt_ptr_op(NULL, OP_EQ, dimap_search(map, key2, NULL)); 1123 tt_ptr_op(v3, OP_EQ, dimap_search(map, key2, v3)); 1124 tt_ptr_op(v1, OP_EQ, dimap_search(map, key1, NULL)); 1125 1126 /* Now try it with three entries in the map. */ 1127 dimap_add_entry(&map, key2, v2); 1128 dimap_add_entry(&map, key3, v3); 1129 tt_ptr_op(v1, OP_EQ, dimap_search(map, key1, NULL)); 1130 tt_ptr_op(v2, OP_EQ, dimap_search(map, key2, NULL)); 1131 tt_ptr_op(v3, OP_EQ, dimap_search(map, key3, NULL)); 1132 tt_ptr_op(NULL, OP_EQ, dimap_search(map, key4, NULL)); 1133 tt_ptr_op(v1, OP_EQ, dimap_search(map, key4, v1)); 1134 1135 done: 1136 tor_free(v1); 1137 tor_free(v2); 1138 tor_free(v3); 1139 dimap_free(map, NULL); 1140 } 1141 1142 /** Run unit tests for fp_pair-to-void* map functions */ 1143 static void 1144 test_container_fp_pair_map(void *arg) 1145 { 1146 fp_pair_map_t *map; 1147 fp_pair_t fp1, fp2, fp3, fp4, fp5, fp6; 1148 void *v; 1149 fp_pair_map_iter_t *iter; 1150 fp_pair_t k; 1151 char *v99 = tor_strdup("99"); 1152 char *v100 = tor_strdup("v100"); 1153 char *v101 = tor_strdup("v101"); 1154 char *v102 = tor_strdup("v102"); 1155 char *v103 = tor_strdup("v103"); 1156 char *v104 = tor_strdup("v104"); 1157 char *v105 = tor_strdup("v105"); 1158 1159 (void)arg; 1160 map = fp_pair_map_new(); 1161 tt_assert(map); 1162 tt_int_op(fp_pair_map_size(map),OP_EQ, 0); 1163 tt_assert(fp_pair_map_isempty(map)); 1164 1165 memset(fp1.first, 0x11, DIGEST_LEN); 1166 memset(fp1.second, 0x12, DIGEST_LEN); 1167 memset(fp2.first, 0x21, DIGEST_LEN); 1168 memset(fp2.second, 0x22, DIGEST_LEN); 1169 memset(fp3.first, 0x31, DIGEST_LEN); 1170 memset(fp3.second, 0x32, DIGEST_LEN); 1171 memset(fp4.first, 0x41, DIGEST_LEN); 1172 memset(fp4.second, 0x42, DIGEST_LEN); 1173 memset(fp5.first, 0x51, DIGEST_LEN); 1174 memset(fp5.second, 0x52, DIGEST_LEN); 1175 memset(fp6.first, 0x61, DIGEST_LEN); 1176 memset(fp6.second, 0x62, DIGEST_LEN); 1177 1178 v = fp_pair_map_set(map, &fp1, v99); 1179 tt_ptr_op(v, OP_EQ, NULL); 1180 tt_assert(!fp_pair_map_isempty(map)); 1181 v = fp_pair_map_set(map, &fp2, v101); 1182 tt_ptr_op(v, OP_EQ, NULL); 1183 v = fp_pair_map_set(map, &fp1, v100); 1184 tt_ptr_op(v, OP_EQ, v99); 1185 tt_ptr_op(fp_pair_map_get(map, &fp1),OP_EQ, v100); 1186 tt_ptr_op(fp_pair_map_get(map, &fp2),OP_EQ, v101); 1187 tt_ptr_op(fp_pair_map_get(map, &fp3),OP_EQ, NULL); 1188 fp_pair_map_assert_ok(map); 1189 1190 v = fp_pair_map_remove(map, &fp2); 1191 fp_pair_map_assert_ok(map); 1192 tt_ptr_op(v,OP_EQ, v101); 1193 tt_ptr_op(fp_pair_map_get(map, &fp2),OP_EQ, NULL); 1194 tt_ptr_op(fp_pair_map_remove(map, &fp2),OP_EQ, NULL); 1195 1196 fp_pair_map_set(map, &fp2, v101); 1197 fp_pair_map_set(map, &fp3, v102); 1198 fp_pair_map_set(map, &fp4, v103); 1199 tt_int_op(fp_pair_map_size(map),OP_EQ, 4); 1200 fp_pair_map_assert_ok(map); 1201 fp_pair_map_set(map, &fp5, v104); 1202 fp_pair_map_set_by_digests(map, fp6.first, fp6.second, v105); 1203 fp_pair_map_assert_ok(map); 1204 1205 /* Test iterator. */ 1206 iter = fp_pair_map_iter_init(map); 1207 while (!fp_pair_map_iter_done(iter)) { 1208 fp_pair_map_iter_get(iter, &k, &v); 1209 tt_ptr_op(v,OP_EQ, fp_pair_map_get(map, &k)); 1210 1211 if (tor_memeq(&fp2, &k, sizeof(fp2))) { 1212 iter = fp_pair_map_iter_next_rmv(map, iter); 1213 } else { 1214 iter = fp_pair_map_iter_next(map, iter); 1215 } 1216 } 1217 1218 /* Make sure we removed fp2, but not the others. */ 1219 tt_ptr_op(fp_pair_map_get(map, &fp2),OP_EQ, NULL); 1220 tt_ptr_op(fp_pair_map_get_by_digests(map, fp5.first, fp5.second), 1221 OP_EQ, v104); 1222 1223 fp_pair_map_assert_ok(map); 1224 /* Clean up after ourselves. */ 1225 fp_pair_map_free(map, NULL); 1226 map = NULL; 1227 1228 done: 1229 if (map) 1230 fp_pair_map_free(map, NULL); 1231 tor_free(v99); 1232 tor_free(v100); 1233 tor_free(v101); 1234 tor_free(v102); 1235 tor_free(v103); 1236 tor_free(v104); 1237 tor_free(v105); 1238 } 1239 1240 static void 1241 test_container_smartlist_most_frequent(void *arg) 1242 { 1243 (void) arg; 1244 smartlist_t *sl = smartlist_new(); 1245 1246 int count = -1; 1247 const char *cp; 1248 1249 cp = smartlist_get_most_frequent_string_(sl, &count); 1250 tt_int_op(count, OP_EQ, 0); 1251 tt_ptr_op(cp, OP_EQ, NULL); 1252 1253 /* String must be sorted before we call get_most_frequent */ 1254 smartlist_split_string(sl, "abc:def:ghi", ":", 0, 0); 1255 1256 cp = smartlist_get_most_frequent_string_(sl, &count); 1257 tt_int_op(count, OP_EQ, 1); 1258 tt_str_op(cp, OP_EQ, "ghi"); /* Ties broken in favor of later element */ 1259 1260 smartlist_split_string(sl, "def:ghi", ":", 0, 0); 1261 smartlist_sort_strings(sl); 1262 1263 cp = smartlist_get_most_frequent_string_(sl, &count); 1264 tt_int_op(count, OP_EQ, 2); 1265 tt_ptr_op(cp, OP_NE, NULL); 1266 tt_str_op(cp, OP_EQ, "ghi"); /* Ties broken in favor of later element */ 1267 1268 smartlist_split_string(sl, "def:abc:qwop", ":", 0, 0); 1269 smartlist_sort_strings(sl); 1270 1271 cp = smartlist_get_most_frequent_string_(sl, &count); 1272 tt_int_op(count, OP_EQ, 3); 1273 tt_ptr_op(cp, OP_NE, NULL); 1274 tt_str_op(cp, OP_EQ, "def"); /* No tie */ 1275 1276 done: 1277 SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); 1278 smartlist_free(sl); 1279 } 1280 1281 static void 1282 test_container_smartlist_sort_ptrs(void *arg) 1283 { 1284 (void)arg; 1285 int array[10]; 1286 int *arrayptrs[11]; 1287 smartlist_t *sl = smartlist_new(); 1288 unsigned i=0, j; 1289 1290 for (j = 0; j < ARRAY_LENGTH(array); ++j) { 1291 smartlist_add(sl, &array[j]); 1292 arrayptrs[i++] = &array[j]; 1293 if (j == 5) { 1294 smartlist_add(sl, &array[j]); 1295 arrayptrs[i++] = &array[j]; 1296 } 1297 } 1298 1299 for (i = 0; i < 10; ++i) { 1300 smartlist_shuffle(sl); 1301 smartlist_sort_pointers(sl); 1302 for (j = 0; j < ARRAY_LENGTH(arrayptrs); ++j) { 1303 tt_ptr_op(smartlist_get(sl, j), OP_EQ, arrayptrs[j]); 1304 } 1305 } 1306 1307 done: 1308 smartlist_free(sl); 1309 } 1310 1311 static void 1312 test_container_smartlist_strings_eq(void *arg) 1313 { 1314 (void)arg; 1315 smartlist_t *sl1 = smartlist_new(); 1316 smartlist_t *sl2 = smartlist_new(); 1317 #define EQ_SHOULD_SAY(s1,s2,val) \ 1318 do { \ 1319 SMARTLIST_FOREACH(sl1, char *, cp, tor_free(cp)); \ 1320 SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); \ 1321 smartlist_clear(sl1); \ 1322 smartlist_clear(sl2); \ 1323 smartlist_split_string(sl1, (s1), ":", 0, 0); \ 1324 smartlist_split_string(sl2, (s2), ":", 0, 0); \ 1325 tt_int_op((val), OP_EQ, smartlist_strings_eq(sl1, sl2)); \ 1326 } while (0) 1327 1328 /* Both NULL, so equal */ 1329 tt_int_op(1, OP_EQ, smartlist_strings_eq(NULL, NULL)); 1330 1331 /* One NULL, not equal. */ 1332 tt_int_op(0, OP_EQ, smartlist_strings_eq(NULL, sl1)); 1333 tt_int_op(0, OP_EQ, smartlist_strings_eq(sl1, NULL)); 1334 1335 /* Both empty, both equal. */ 1336 EQ_SHOULD_SAY("", "", 1); 1337 1338 /* One empty, not equal */ 1339 EQ_SHOULD_SAY("", "ab", 0); 1340 EQ_SHOULD_SAY("", "xy:z", 0); 1341 EQ_SHOULD_SAY("abc", "", 0); 1342 EQ_SHOULD_SAY("abc:cd", "", 0); 1343 1344 /* Different lengths, not equal. */ 1345 EQ_SHOULD_SAY("hello:world", "hello", 0); 1346 EQ_SHOULD_SAY("hello", "hello:friends", 0); 1347 1348 /* Same lengths, not equal */ 1349 EQ_SHOULD_SAY("Hello:world", "goodbye:world", 0); 1350 EQ_SHOULD_SAY("Hello:world", "Hello:stars", 0); 1351 1352 /* Actually equal */ 1353 EQ_SHOULD_SAY("ABC", "ABC", 1); 1354 EQ_SHOULD_SAY(" ab : cd : e", " ab : cd : e", 1); 1355 1356 done: 1357 SMARTLIST_FOREACH(sl1, char *, cp, tor_free(cp)); 1358 SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); 1359 smartlist_free(sl1); 1360 smartlist_free(sl2); 1361 } 1362 1363 #define CONTAINER_LEGACY(name) \ 1364 { #name, test_container_ ## name , 0, NULL, NULL } 1365 1366 #define CONTAINER(name, flags) \ 1367 { #name, test_container_ ## name, (flags), NULL, NULL } 1368 1369 struct testcase_t container_tests[] = { 1370 CONTAINER_LEGACY(smartlist_basic), 1371 CONTAINER_LEGACY(smartlist_strings), 1372 CONTAINER_LEGACY(smartlist_foreach_reverse), 1373 CONTAINER_LEGACY(smartlist_overlap), 1374 CONTAINER_LEGACY(smartlist_digests), 1375 CONTAINER_LEGACY(smartlist_join), 1376 CONTAINER_LEGACY(smartlist_pos), 1377 CONTAINER(smartlist_remove, 0), 1378 CONTAINER(smartlist_ints_eq, 0), 1379 CONTAINER(smartlist_grow, 0), 1380 CONTAINER_LEGACY(bitarray), 1381 CONTAINER_LEGACY(digestset), 1382 CONTAINER_LEGACY(strmap), 1383 CONTAINER_LEGACY(pqueue), 1384 CONTAINER_LEGACY(order_functions), 1385 CONTAINER(di_map, 0), 1386 CONTAINER_LEGACY(fp_pair_map), 1387 CONTAINER(smartlist_most_frequent, 0), 1388 CONTAINER(smartlist_sort_ptrs, 0), 1389 CONTAINER(smartlist_strings_eq, 0), 1390 END_OF_TESTCASES 1391 };