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
compare_strs_(const void ** a,const void ** b)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
compare_strs_for_bsearch_(const void * a,const void ** b)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
cmp_without_first_(const void * a,const void ** b)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
test_container_smartlist_basic(void * arg)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
test_container_smartlist_foreach_reverse(void * arg)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
test_container_smartlist_strings(void * arg)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
test_container_smartlist_overlap(void * arg)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
test_container_smartlist_digests(void * arg)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
test_container_smartlist_join(void * arg)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
test_container_smartlist_pos(void * arg)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
test_container_smartlist_ints_eq(void * arg)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
test_container_smartlist_grow(void * arg)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
test_container_bitarray(void * arg)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
test_container_digestset(void * arg)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
compare_strings_for_pqueue_(const void * p1,const void * p2)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
test_container_pqueue(void * arg)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
test_container_strmap(void * arg)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
test_container_smartlist_remove(void * arg)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
test_container_order_functions(void * arg)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
test_container_di_map(void * arg)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
test_container_fp_pair_map(void * arg)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
test_container_smartlist_most_frequent(void * arg)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
test_container_smartlist_sort_ptrs(void * arg)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
test_container_smartlist_strings_eq(void * arg)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 };
1392