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