Refactor exit port statistics code and add unit tests.
[tor/rransom.git] / src / test / test_util.c
blob22f2707d758ca025274000f53527f8a6b0f13c80
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2010, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "orconfig.h"
7 #define CONTROL_PRIVATE
8 #define MEMPOOL_PRIVATE
9 #include "or.h"
10 #include "config.h"
11 #include "control.h"
12 #include "test.h"
13 #include "mempool.h"
14 #include "memarea.h"
16 static void
17 test_util_time(void)
19 struct timeval start, end;
20 struct tm a_time;
21 char timestr[RFC1123_TIME_LEN+1];
22 time_t t_res;
23 int i;
25 start.tv_sec = 5;
26 start.tv_usec = 5000;
28 end.tv_sec = 5;
29 end.tv_usec = 5000;
31 test_eq(0L, tv_udiff(&start, &end));
33 end.tv_usec = 7000;
35 test_eq(2000L, tv_udiff(&start, &end));
37 end.tv_sec = 6;
39 test_eq(1002000L, tv_udiff(&start, &end));
41 end.tv_usec = 0;
43 test_eq(995000L, tv_udiff(&start, &end));
45 end.tv_sec = 4;
47 test_eq(-1005000L, tv_udiff(&start, &end));
49 end.tv_usec = 999990;
50 start.tv_sec = 1;
51 start.tv_usec = 500;
53 /* The test values here are confirmed to be correct on a platform
54 * with a working timegm. */
55 a_time.tm_year = 2003-1900;
56 a_time.tm_mon = 7;
57 a_time.tm_mday = 30;
58 a_time.tm_hour = 6;
59 a_time.tm_min = 14;
60 a_time.tm_sec = 55;
61 test_eq((time_t) 1062224095UL, tor_timegm(&a_time));
62 a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
63 test_eq((time_t) 1093846495UL, tor_timegm(&a_time));
64 a_time.tm_mon = 1; /* Try a leap year, in feb. */
65 a_time.tm_mday = 10;
66 test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
68 format_rfc1123_time(timestr, 0);
69 test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr);
70 format_rfc1123_time(timestr, (time_t)1091580502UL);
71 test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr);
73 t_res = 0;
74 i = parse_rfc1123_time(timestr, &t_res);
75 test_eq(i,0);
76 test_eq(t_res, (time_t)1091580502UL);
77 test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
79 tor_gettimeofday(&start);
80 /* now make sure time works. */
81 tor_gettimeofday(&end);
82 /* We might've timewarped a little. */
83 tt_int_op(tv_udiff(&start, &end), >=, -5000);
85 done:
89 static void
90 test_util_config_line(void)
92 char buf[1024];
93 char *k=NULL, *v=NULL;
94 const char *str;
96 /* Test parse_config_line_from_str */
97 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
98 "k2\n"
99 "k3 \n" "\n" " \n" "#comment\n"
100 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
101 "kseven \"a quoted 'string\"\n"
102 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
103 , sizeof(buf));
104 str = buf;
106 str = parse_config_line_from_str(str, &k, &v);
107 test_streq(k, "k");
108 test_streq(v, "v");
109 tor_free(k); tor_free(v);
110 test_assert(!strcmpstart(str, "key value with"));
112 str = parse_config_line_from_str(str, &k, &v);
113 test_streq(k, "key");
114 test_streq(v, "value with spaces");
115 tor_free(k); tor_free(v);
116 test_assert(!strcmpstart(str, "keykey"));
118 str = parse_config_line_from_str(str, &k, &v);
119 test_streq(k, "keykey");
120 test_streq(v, "val");
121 tor_free(k); tor_free(v);
122 test_assert(!strcmpstart(str, "k2\n"));
124 str = parse_config_line_from_str(str, &k, &v);
125 test_streq(k, "k2");
126 test_streq(v, "");
127 tor_free(k); tor_free(v);
128 test_assert(!strcmpstart(str, "k3 \n"));
130 str = parse_config_line_from_str(str, &k, &v);
131 test_streq(k, "k3");
132 test_streq(v, "");
133 tor_free(k); tor_free(v);
134 test_assert(!strcmpstart(str, "#comment"));
136 str = parse_config_line_from_str(str, &k, &v);
137 test_streq(k, "k4");
138 test_streq(v, "");
139 tor_free(k); tor_free(v);
140 test_assert(!strcmpstart(str, "k5#abc"));
142 str = parse_config_line_from_str(str, &k, &v);
143 test_streq(k, "k5");
144 test_streq(v, "");
145 tor_free(k); tor_free(v);
146 test_assert(!strcmpstart(str, "k6"));
148 str = parse_config_line_from_str(str, &k, &v);
149 test_streq(k, "k6");
150 test_streq(v, "val");
151 tor_free(k); tor_free(v);
152 test_assert(!strcmpstart(str, "kseven"));
154 str = parse_config_line_from_str(str, &k, &v);
155 test_streq(k, "kseven");
156 test_streq(v, "a quoted \'string");
157 tor_free(k); tor_free(v);
158 test_assert(!strcmpstart(str, "k8 "));
160 str = parse_config_line_from_str(str, &k, &v);
161 test_streq(k, "k8");
162 test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
163 tor_free(k); tor_free(v);
164 test_streq(str, "");
165 done:
166 tor_free(k);
167 tor_free(v);
170 /** Test basic string functionality. */
171 static void
172 test_util_strmisc(void)
174 char buf[1024];
175 int i;
176 char *cp;
178 /* Tests for corner cases of strl operations */
179 test_eq(5, strlcpy(buf, "Hello", 0));
180 strlcpy(buf, "Hello", sizeof(buf));
181 test_eq(10, strlcat(buf, "Hello", 5));
183 /* Test tor_strstrip() */
184 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
185 tor_strstrip(buf, ",!");
186 test_streq(buf, "Testing 1 2 3");
187 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
188 tor_strstrip(buf, "!? ");
189 test_streq(buf, "Testing123");
191 /* Test tor_parse_long. */
192 test_eq(10L, tor_parse_long("10",10,0,100,NULL,NULL));
193 test_eq(0L, tor_parse_long("10",10,50,100,NULL,NULL));
194 test_eq(-50L, tor_parse_long("-50",10,-100,100,NULL,NULL));
196 /* Test tor_parse_ulong */
197 test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL));
198 test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL));
200 /* Test tor_parse_uint64. */
201 test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
202 test_assert(i == 1);
203 test_streq(cp, " x");
204 test_assert(U64_LITERAL(12345678901) ==
205 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
206 test_assert(i == 1);
207 test_streq(cp, "");
208 test_assert(U64_LITERAL(0) ==
209 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
210 test_assert(i == 0);
213 /* Test tor_parse_double. */
214 double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL);
215 test_assert(i == 1);
216 test_assert(DBL_TO_U64(d) == 10);
217 d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL);
218 test_assert(i == 1);
219 test_assert(DBL_TO_U64(d) == 0);
220 d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL);
221 test_assert(i == 0);
222 d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL);
223 test_assert(i == 0);
224 d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp);
225 test_assert(i == 1);
226 d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL);
227 test_assert(i == 1);
230 /* Test failing snprintf cases */
231 test_eq(-1, tor_snprintf(buf, 0, "Foo"));
232 test_eq(-1, tor_snprintf(buf, 2, "Foo"));
234 /* Test printf with uint64 */
235 tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
236 U64_PRINTF_ARG(U64_LITERAL(12345678901)));
237 test_streq(buf, "x!12345678901!x");
239 /* Test for strcmpstart and strcmpend. */
240 test_assert(strcmpstart("abcdef", "abcdef")==0);
241 test_assert(strcmpstart("abcdef", "abc")==0);
242 test_assert(strcmpstart("abcdef", "abd")<0);
243 test_assert(strcmpstart("abcdef", "abb")>0);
244 test_assert(strcmpstart("ab", "abb")<0);
246 test_assert(strcmpend("abcdef", "abcdef")==0);
247 test_assert(strcmpend("abcdef", "def")==0);
248 test_assert(strcmpend("abcdef", "deg")<0);
249 test_assert(strcmpend("abcdef", "dee")>0);
250 test_assert(strcmpend("ab", "abb")<0);
252 test_assert(strcasecmpend("AbcDEF", "abcdef")==0);
253 test_assert(strcasecmpend("abcdef", "dEF")==0);
254 test_assert(strcasecmpend("abcDEf", "deg")<0);
255 test_assert(strcasecmpend("abcdef", "DEE")>0);
256 test_assert(strcasecmpend("ab", "abB")<0);
258 /* Test mem_is_zero */
259 memset(buf,0,128);
260 buf[128] = 'x';
261 test_assert(tor_digest_is_zero(buf));
262 test_assert(tor_mem_is_zero(buf, 10));
263 test_assert(tor_mem_is_zero(buf, 20));
264 test_assert(tor_mem_is_zero(buf, 128));
265 test_assert(!tor_mem_is_zero(buf, 129));
266 buf[60] = (char)255;
267 test_assert(!tor_mem_is_zero(buf, 128));
268 buf[0] = (char)1;
269 test_assert(!tor_mem_is_zero(buf, 10));
271 /* Test 'escaped' */
272 test_streq("\"\"", escaped(""));
273 test_streq("\"abcd\"", escaped("abcd"));
274 test_streq("\"\\\\\\n\\r\\t\\\"\\'\"", escaped("\\\n\r\t\"\'"));
275 test_streq("\"z\\001abc\\277d\"", escaped("z\001abc\277d"));
276 test_assert(NULL == escaped(NULL));
278 /* Test strndup and memdup */
280 const char *s = "abcdefghijklmnopqrstuvwxyz";
281 cp = tor_strndup(s, 30);
282 test_streq(cp, s); /* same string, */
283 test_neq(cp, s); /* but different pointers. */
284 tor_free(cp);
286 cp = tor_strndup(s, 5);
287 test_streq(cp, "abcde");
288 tor_free(cp);
290 s = "a\0b\0c\0d\0e\0";
291 cp = tor_memdup(s,10);
292 test_memeq(cp, s, 10); /* same ram, */
293 test_neq(cp, s); /* but different pointers. */
294 tor_free(cp);
297 /* Test str-foo functions */
298 cp = tor_strdup("abcdef");
299 test_assert(tor_strisnonupper(cp));
300 cp[3] = 'D';
301 test_assert(!tor_strisnonupper(cp));
302 tor_strupper(cp);
303 test_streq(cp, "ABCDEF");
304 test_assert(tor_strisprint(cp));
305 cp[3] = 3;
306 test_assert(!tor_strisprint(cp));
307 tor_free(cp);
309 /* Test eat_whitespace. */
311 const char *s = " \n a";
312 test_eq_ptr(eat_whitespace(s), s+4);
313 s = "abcd";
314 test_eq_ptr(eat_whitespace(s), s);
315 s = "#xyz\nab";
316 test_eq_ptr(eat_whitespace(s), s+5);
319 /* Test memmem and memstr */
321 const char *haystack = "abcde";
322 tor_assert(!tor_memmem(haystack, 5, "ef", 2));
323 test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
324 test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
325 haystack = "ababcad";
326 test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2);
327 test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2);
328 test_assert(!tor_memstr(haystack, 7, "fe"));
329 test_assert(!tor_memstr(haystack, 7, "longerthantheoriginal"));
332 /* Test wrap_string */
334 smartlist_t *sl = smartlist_create();
335 wrap_string(sl, "This is a test of string wrapping functionality: woot.",
336 10, "", "");
337 cp = smartlist_join_strings(sl, "", 0, NULL);
338 test_streq(cp,
339 "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n");
340 tor_free(cp);
341 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
342 smartlist_clear(sl);
344 wrap_string(sl, "This is a test of string wrapping functionality: woot.",
345 16, "### ", "# ");
346 cp = smartlist_join_strings(sl, "", 0, NULL);
347 test_streq(cp,
348 "### This is a\n# test of string\n# wrapping\n# functionality:\n"
349 "# woot.\n");
351 tor_free(cp);
352 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
353 smartlist_free(sl);
355 done:
359 static void
360 test_util_pow2(void)
362 /* Test tor_log2(). */
363 test_eq(tor_log2(64), 6);
364 test_eq(tor_log2(65), 6);
365 test_eq(tor_log2(63), 5);
366 test_eq(tor_log2(1), 0);
367 test_eq(tor_log2(2), 1);
368 test_eq(tor_log2(3), 1);
369 test_eq(tor_log2(4), 2);
370 test_eq(tor_log2(5), 2);
371 test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55);
372 test_eq(tor_log2(UINT64_MAX), 63);
374 /* Test round_to_power_of_2 */
375 test_eq(round_to_power_of_2(120), 128);
376 test_eq(round_to_power_of_2(128), 128);
377 test_eq(round_to_power_of_2(130), 128);
378 test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)),
379 U64_LITERAL(1)<<55);
380 test_eq(round_to_power_of_2(0), 2);
382 done:
386 /** mutex for thread test to stop the threads hitting data at the same time. */
387 static tor_mutex_t *_thread_test_mutex = NULL;
388 /** mutexes for the thread test to make sure that the threads have to
389 * interleave somewhat. */
390 static tor_mutex_t *_thread_test_start1 = NULL,
391 *_thread_test_start2 = NULL;
392 /** Shared strmap for the thread test. */
393 static strmap_t *_thread_test_strmap = NULL;
394 /** The name of thread1 for the thread test */
395 static char *_thread1_name = NULL;
396 /** The name of thread2 for the thread test */
397 static char *_thread2_name = NULL;
399 static void _thread_test_func(void* _s) ATTR_NORETURN;
401 /** How many iterations have the threads in the unit test run? */
402 static int t1_count = 0, t2_count = 0;
404 /** Helper function for threading unit tests: This function runs in a
405 * subthread. It grabs its own mutex (start1 or start2) to make sure that it
406 * should start, then it repeatedly alters _test_thread_strmap protected by
407 * _thread_test_mutex. */
408 static void
409 _thread_test_func(void* _s)
411 char *s = _s;
412 int i, *count;
413 tor_mutex_t *m;
414 char buf[64];
415 char **cp;
416 if (!strcmp(s, "thread 1")) {
417 m = _thread_test_start1;
418 cp = &_thread1_name;
419 count = &t1_count;
420 } else {
421 m = _thread_test_start2;
422 cp = &_thread2_name;
423 count = &t2_count;
426 tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id());
427 *cp = tor_strdup(buf);
429 tor_mutex_acquire(m);
431 for (i=0; i<10000; ++i) {
432 tor_mutex_acquire(_thread_test_mutex);
433 strmap_set(_thread_test_strmap, "last to run", *cp);
434 ++*count;
435 tor_mutex_release(_thread_test_mutex);
437 tor_mutex_acquire(_thread_test_mutex);
438 strmap_set(_thread_test_strmap, s, *cp);
439 tor_mutex_release(_thread_test_mutex);
441 tor_mutex_release(m);
443 spawn_exit();
446 /** Run unit tests for threading logic. */
447 static void
448 test_util_threads(void)
450 char *s1 = NULL, *s2 = NULL;
451 int done = 0, timedout = 0;
452 time_t started;
453 #ifndef MS_WINDOWS
454 struct timeval tv;
455 tv.tv_sec=0;
456 tv.tv_usec=10;
457 #endif
458 #ifndef TOR_IS_MULTITHREADED
459 /* Skip this test if we aren't threading. We should be threading most
460 * everywhere by now. */
461 if (1)
462 return;
463 #endif
464 _thread_test_mutex = tor_mutex_new();
465 _thread_test_start1 = tor_mutex_new();
466 _thread_test_start2 = tor_mutex_new();
467 _thread_test_strmap = strmap_new();
468 s1 = tor_strdup("thread 1");
469 s2 = tor_strdup("thread 2");
470 tor_mutex_acquire(_thread_test_start1);
471 tor_mutex_acquire(_thread_test_start2);
472 spawn_func(_thread_test_func, s1);
473 spawn_func(_thread_test_func, s2);
474 tor_mutex_release(_thread_test_start2);
475 tor_mutex_release(_thread_test_start1);
476 started = time(NULL);
477 while (!done) {
478 tor_mutex_acquire(_thread_test_mutex);
479 strmap_assert_ok(_thread_test_strmap);
480 if (strmap_get(_thread_test_strmap, "thread 1") &&
481 strmap_get(_thread_test_strmap, "thread 2")) {
482 done = 1;
483 } else if (time(NULL) > started + 25) {
484 timedout = done = 1;
486 tor_mutex_release(_thread_test_mutex);
487 #ifndef MS_WINDOWS
488 /* Prevent the main thread from starving the worker threads. */
489 select(0, NULL, NULL, NULL, &tv);
490 #endif
492 tor_mutex_acquire(_thread_test_start1);
493 tor_mutex_release(_thread_test_start1);
494 tor_mutex_acquire(_thread_test_start2);
495 tor_mutex_release(_thread_test_start2);
497 tor_mutex_free(_thread_test_mutex);
499 if (timedout) {
500 printf("\nTimed out: %d %d", t1_count, t2_count);
501 test_assert(strmap_get(_thread_test_strmap, "thread 1"));
502 test_assert(strmap_get(_thread_test_strmap, "thread 2"));
503 test_assert(!timedout);
506 /* different thread IDs. */
507 test_assert(strcmp(strmap_get(_thread_test_strmap, "thread 1"),
508 strmap_get(_thread_test_strmap, "thread 2")));
509 test_assert(!strcmp(strmap_get(_thread_test_strmap, "thread 1"),
510 strmap_get(_thread_test_strmap, "last to run")) ||
511 !strcmp(strmap_get(_thread_test_strmap, "thread 2"),
512 strmap_get(_thread_test_strmap, "last to run")));
514 done:
515 tor_free(s1);
516 tor_free(s2);
517 tor_free(_thread1_name);
518 tor_free(_thread2_name);
519 if (_thread_test_strmap)
520 strmap_free(_thread_test_strmap, NULL);
521 if (_thread_test_start1)
522 tor_mutex_free(_thread_test_start1);
523 if (_thread_test_start2)
524 tor_mutex_free(_thread_test_start2);
527 /** Run unit tests for compression functions */
528 static void
529 test_util_gzip(void)
531 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
532 const char *ccp2;
533 size_t len1, len2;
534 tor_zlib_state_t *state = NULL;
536 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
537 test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
538 if (is_gzip_supported()) {
539 test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
540 GZIP_METHOD));
541 test_assert(buf2);
542 test_assert(!memcmp(buf2, "\037\213", 2)); /* Gzip magic. */
543 test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
545 test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
546 GZIP_METHOD, 1, LOG_INFO));
547 test_assert(buf3);
548 test_streq(buf1,buf3);
550 tor_free(buf2);
551 tor_free(buf3);
554 test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
555 ZLIB_METHOD));
556 test_assert(buf2);
557 test_assert(!memcmp(buf2, "\x78\xDA", 2)); /* deflate magic. */
558 test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
560 test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
561 ZLIB_METHOD, 1, LOG_INFO));
562 test_assert(buf3);
563 test_streq(buf1,buf3);
565 /* Check whether we can uncompress concatenated, compressed strings. */
566 tor_free(buf3);
567 buf2 = tor_realloc(buf2, len1*2);
568 memcpy(buf2+len1, buf2, len1);
569 test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
570 ZLIB_METHOD, 1, LOG_INFO));
571 test_eq(len2, (strlen(buf1)+1)*2);
572 test_memeq(buf3,
573 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
574 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
575 (strlen(buf1)+1)*2);
577 tor_free(buf1);
578 tor_free(buf2);
579 tor_free(buf3);
581 /* Check whether we can uncompress partial strings. */
582 buf1 =
583 tor_strdup("String with low redundancy that won't be compressed much.");
584 test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
585 ZLIB_METHOD));
586 tor_assert(len1>16);
587 /* when we allow an incomplete string, we should succeed.*/
588 tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
589 ZLIB_METHOD, 0, LOG_INFO));
590 buf3[len2]='\0';
591 tor_assert(len2 > 5);
592 tor_assert(!strcmpstart(buf1, buf3));
594 /* when we demand a complete string, this must fail. */
595 tor_free(buf3);
596 tor_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
597 ZLIB_METHOD, 1, LOG_INFO));
598 tor_assert(!buf3);
600 /* Now, try streaming compression. */
601 tor_free(buf1);
602 tor_free(buf2);
603 tor_free(buf3);
604 state = tor_zlib_new(1, ZLIB_METHOD);
605 tor_assert(state);
606 cp1 = buf1 = tor_malloc(1024);
607 len1 = 1024;
608 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
609 len2 = 21;
610 test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
611 == TOR_ZLIB_OK);
612 test_eq(len2, 0); /* Make sure we compressed it all. */
613 test_assert(cp1 > buf1);
615 len2 = 0;
616 cp2 = cp1;
617 test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
618 == TOR_ZLIB_DONE);
619 test_eq(len2, 0);
620 test_assert(cp1 > cp2); /* Make sure we really added something. */
622 tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
623 ZLIB_METHOD, 1, LOG_WARN));
624 test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
626 done:
627 if (state)
628 tor_zlib_free(state);
629 tor_free(buf2);
630 tor_free(buf3);
631 tor_free(buf1);
634 /** Run unit tests for mmap() wrapper functionality. */
635 static void
636 test_util_mmap(void)
638 char *fname1 = tor_strdup(get_fname("mapped_1"));
639 char *fname2 = tor_strdup(get_fname("mapped_2"));
640 char *fname3 = tor_strdup(get_fname("mapped_3"));
641 const size_t buflen = 17000;
642 char *buf = tor_malloc(17000);
643 tor_mmap_t *mapping = NULL;
645 crypto_rand(buf, buflen);
647 mapping = tor_mmap_file(fname1);
648 test_assert(! mapping);
650 write_str_to_file(fname1, "Short file.", 1);
651 write_bytes_to_file(fname2, buf, buflen, 1);
652 write_bytes_to_file(fname3, buf, 16384, 1);
654 mapping = tor_mmap_file(fname1);
655 test_assert(mapping);
656 test_eq(mapping->size, strlen("Short file."));
657 test_streq(mapping->data, "Short file.");
658 #ifdef MS_WINDOWS
659 tor_munmap_file(mapping);
660 mapping = NULL;
661 test_assert(unlink(fname1) == 0);
662 #else
663 /* make sure we can unlink. */
664 test_assert(unlink(fname1) == 0);
665 test_streq(mapping->data, "Short file.");
666 tor_munmap_file(mapping);
667 mapping = NULL;
668 #endif
670 /* Now a zero-length file. */
671 write_str_to_file(fname1, "", 1);
672 mapping = tor_mmap_file(fname1);
673 test_eq(mapping, NULL);
674 test_eq(ERANGE, errno);
675 unlink(fname1);
677 /* Make sure that we fail to map a no-longer-existent file. */
678 mapping = tor_mmap_file(fname1);
679 test_assert(mapping == NULL);
681 /* Now try a big file that stretches across a few pages and isn't aligned */
682 mapping = tor_mmap_file(fname2);
683 test_assert(mapping);
684 test_eq(mapping->size, buflen);
685 test_memeq(mapping->data, buf, buflen);
686 tor_munmap_file(mapping);
687 mapping = NULL;
689 /* Now try a big aligned file. */
690 mapping = tor_mmap_file(fname3);
691 test_assert(mapping);
692 test_eq(mapping->size, 16384);
693 test_memeq(mapping->data, buf, 16384);
694 tor_munmap_file(mapping);
695 mapping = NULL;
697 done:
698 unlink(fname1);
699 unlink(fname2);
700 unlink(fname3);
702 tor_free(fname1);
703 tor_free(fname2);
704 tor_free(fname3);
705 tor_free(buf);
707 if (mapping)
708 tor_munmap_file(mapping);
711 /** Run unit tests for escaping/unescaping data for use by controllers. */
712 static void
713 test_util_control_formats(void)
715 char *out = NULL;
716 const char *inp =
717 "..This is a test\r\nof the emergency \nbroadcast\r\n..system.\r\nZ.\r\n";
718 size_t sz;
720 sz = read_escaped_data(inp, strlen(inp), &out);
721 test_streq(out,
722 ".This is a test\nof the emergency \nbroadcast\n.system.\nZ.\n");
723 test_eq(sz, strlen(out));
725 done:
726 tor_free(out);
729 static void
730 test_util_sscanf(void)
732 unsigned u1, u2, u3;
733 char s1[10], s2[10], s3[10], ch;
734 int r;
736 r = tor_sscanf("hello world", "hello world"); /* String match: success */
737 test_eq(r, 0);
738 r = tor_sscanf("hello world 3", "hello worlb %u", &u1); /* String fail */
739 test_eq(r, 0);
740 r = tor_sscanf("12345", "%u", &u1); /* Simple number */
741 test_eq(r, 1);
742 test_eq(u1, 12345u);
743 r = tor_sscanf("", "%u", &u1); /* absent number */
744 test_eq(r, 0);
745 r = tor_sscanf("A", "%u", &u1); /* bogus number */
746 test_eq(r, 0);
747 r = tor_sscanf("4294967295", "%u", &u1); /* UINT32_MAX should work. */
748 test_eq(r, 1);
749 test_eq(u1, 4294967295u);
750 r = tor_sscanf("4294967296", "%u", &u1); /* Always say -1 at 32 bits. */
751 test_eq(r, 0);
752 r = tor_sscanf("123456", "%2u%u", &u1, &u2); /* Width */
753 test_eq(r, 2);
754 test_eq(u1, 12u);
755 test_eq(u2, 3456u);
756 r = tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3); /* separators */
757 test_eq(r, 3);
758 test_eq(u1, 12u);
759 test_eq(u2, 3u);
760 test_eq(u3, 456u);
761 r = tor_sscanf("12:3:045", "%2u:%2u:%3u", &u1, &u2, &u3); /* 0s */
762 test_eq(r, 3);
763 test_eq(u1, 12u);
764 test_eq(u2, 3u);
765 test_eq(u3, 45u);
766 /* %u does not match space.*/
767 r = tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3);
768 test_eq(r, 2);
769 /* %u does not match negative numbers. */
770 r = tor_sscanf("12:3:-4", "%2u:%2u:%3u", &u1, &u2, &u3);
771 test_eq(r, 2);
772 /* Arbitrary amounts of 0-padding are okay */
773 r = tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u", &u1, &u2, &u3);
774 test_eq(r, 3);
775 test_eq(u1, 12u);
776 test_eq(u2, 3u);
777 test_eq(u3, 99u);
779 r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/
780 test_eq(r, 1);
781 test_eq(u1, 99);
783 r = tor_sscanf("hello", "%s", s1); /* %s needs a number. */
784 test_eq(r, -1);
786 r = tor_sscanf("hello", "%3s%7s", s1, s2); /* %s matches characters. */
787 test_eq(r, 2);
788 test_streq(s1, "hel");
789 test_streq(s2, "lo");
790 r = tor_sscanf("WD40", "%2s%u", s3, &u1); /* %s%u */
791 test_eq(r, 2);
792 test_streq(s3, "WD");
793 test_eq(u1, 40);
794 r = tor_sscanf("76trombones", "%6u%9s", &u1, s1); /* %u%s */
795 test_eq(r, 2);
796 test_eq(u1, 76);
797 test_streq(s1, "trombones");
798 r = tor_sscanf("hello world", "%9s %9s", s1, s2); /* %s doesn't eat space. */
799 test_eq(r, 2);
800 test_streq(s1, "hello");
801 test_streq(s2, "world");
802 r = tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3); /* %s can be empty. */
803 test_eq(r, 3);
804 test_streq(s1, "hi");
805 test_streq(s2, "");
806 test_streq(s3, "");
808 r = tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch);
809 test_eq(r, 3);
810 r = tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch);
811 test_eq(r, 4);
813 done:
817 /** Run unittests for memory pool allocator */
818 static void
819 test_util_mempool(void)
821 mp_pool_t *pool = NULL;
822 smartlist_t *allocated = NULL;
823 int i;
825 pool = mp_pool_new(1, 100);
826 test_assert(pool);
827 test_assert(pool->new_chunk_capacity >= 100);
828 test_assert(pool->item_alloc_size >= sizeof(void*)+1);
829 mp_pool_destroy(pool);
830 pool = NULL;
832 pool = mp_pool_new(241, 2500);
833 test_assert(pool);
834 test_assert(pool->new_chunk_capacity >= 10);
835 test_assert(pool->item_alloc_size >= sizeof(void*)+241);
836 test_eq(pool->item_alloc_size & 0x03, 0);
837 test_assert(pool->new_chunk_capacity < 60);
839 allocated = smartlist_create();
840 for (i = 0; i < 20000; ++i) {
841 if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) {
842 void *m = mp_pool_get(pool);
843 memset(m, 0x09, 241);
844 smartlist_add(allocated, m);
845 //printf("%d: %p\n", i, m);
846 //mp_pool_assert_ok(pool);
847 } else {
848 int idx = crypto_rand_int(smartlist_len(allocated));
849 void *m = smartlist_get(allocated, idx);
850 //printf("%d: free %p\n", i, m);
851 smartlist_del(allocated, idx);
852 mp_pool_release(m);
853 //mp_pool_assert_ok(pool);
855 if (crypto_rand_int(777)==0)
856 mp_pool_clean(pool, 1, 1);
858 if (i % 777)
859 mp_pool_assert_ok(pool);
862 done:
863 if (allocated) {
864 SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m));
865 mp_pool_assert_ok(pool);
866 mp_pool_clean(pool, 0, 0);
867 mp_pool_assert_ok(pool);
868 smartlist_free(allocated);
871 if (pool)
872 mp_pool_destroy(pool);
875 /** Run unittests for memory area allocator */
876 static void
877 test_util_memarea(void)
879 memarea_t *area = memarea_new();
880 char *p1, *p2, *p3, *p1_orig;
881 void *malloced_ptr = NULL;
882 int i;
884 test_assert(area);
886 p1_orig = p1 = memarea_alloc(area,64);
887 p2 = memarea_alloc_zero(area,52);
888 p3 = memarea_alloc(area,11);
890 test_assert(memarea_owns_ptr(area, p1));
891 test_assert(memarea_owns_ptr(area, p2));
892 test_assert(memarea_owns_ptr(area, p3));
893 /* Make sure we left enough space. */
894 test_assert(p1+64 <= p2);
895 test_assert(p2+52 <= p3);
896 /* Make sure we aligned. */
897 test_eq(((uintptr_t)p1) % sizeof(void*), 0);
898 test_eq(((uintptr_t)p2) % sizeof(void*), 0);
899 test_eq(((uintptr_t)p3) % sizeof(void*), 0);
900 test_assert(!memarea_owns_ptr(area, p3+8192));
901 test_assert(!memarea_owns_ptr(area, p3+30));
902 test_assert(tor_mem_is_zero(p2, 52));
903 /* Make sure we don't overalign. */
904 p1 = memarea_alloc(area, 1);
905 p2 = memarea_alloc(area, 1);
906 test_eq(p1+sizeof(void*), p2);
908 malloced_ptr = tor_malloc(64);
909 test_assert(!memarea_owns_ptr(area, malloced_ptr));
910 tor_free(malloced_ptr);
913 /* memarea_memdup */
915 malloced_ptr = tor_malloc(64);
916 crypto_rand((char*)malloced_ptr, 64);
917 p1 = memarea_memdup(area, malloced_ptr, 64);
918 test_assert(p1 != malloced_ptr);
919 test_memeq(p1, malloced_ptr, 64);
920 tor_free(malloced_ptr);
923 /* memarea_strdup. */
924 p1 = memarea_strdup(area,"");
925 p2 = memarea_strdup(area, "abcd");
926 test_assert(p1);
927 test_assert(p2);
928 test_streq(p1, "");
929 test_streq(p2, "abcd");
931 /* memarea_strndup. */
933 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
934 /* (From Turandot, act 3.) */
935 size_t len = strlen(s);
936 p1 = memarea_strndup(area, s, 1000);
937 p2 = memarea_strndup(area, s, 10);
938 test_streq(p1, s);
939 test_assert(p2 >= p1 + len + 1);
940 test_memeq(s, p2, 10);
941 test_eq(p2[10], '\0');
942 p3 = memarea_strndup(area, s, len);
943 test_streq(p3, s);
944 p3 = memarea_strndup(area, s, len-1);
945 test_memeq(s, p3, len-1);
946 test_eq(p3[len-1], '\0');
949 memarea_clear(area);
950 p1 = memarea_alloc(area, 1);
951 test_eq(p1, p1_orig);
952 memarea_clear(area);
954 /* Check for running over an area's size. */
955 for (i = 0; i < 512; ++i) {
956 p1 = memarea_alloc(area, crypto_rand_int(5)+1);
957 test_assert(memarea_owns_ptr(area, p1));
959 memarea_assert_ok(area);
960 /* Make sure we can allocate a too-big object. */
961 p1 = memarea_alloc_zero(area, 9000);
962 p2 = memarea_alloc_zero(area, 16);
963 test_assert(memarea_owns_ptr(area, p1));
964 test_assert(memarea_owns_ptr(area, p2));
966 done:
967 memarea_drop_all(area);
968 tor_free(malloced_ptr);
971 /** Run unit tests for utility functions to get file names relative to
972 * the data directory. */
973 static void
974 test_util_datadir(void)
976 char buf[1024];
977 char *f = NULL;
978 char *temp_dir = NULL;
980 temp_dir = get_datadir_fname(NULL);
981 f = get_datadir_fname("state");
982 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
983 test_streq(f, buf);
984 tor_free(f);
985 f = get_datadir_fname2("cache", "thingy");
986 tor_snprintf(buf, sizeof(buf),
987 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
988 test_streq(f, buf);
989 tor_free(f);
990 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
991 tor_snprintf(buf, sizeof(buf),
992 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
993 test_streq(f, buf);
994 tor_free(f);
995 f = get_datadir_fname_suffix("cache", ".foo");
996 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
997 temp_dir);
998 test_streq(f, buf);
1000 done:
1001 tor_free(f);
1002 tor_free(temp_dir);
1005 static void
1006 test_util_strtok(void)
1008 char buf[128];
1009 char buf2[128];
1010 char *cp1, *cp2;
1011 strlcpy(buf, "Graved on the dark in gestures of descent", sizeof(buf));
1012 strlcpy(buf2, "they.seemed;their!own;most.perfect;monument", sizeof(buf2));
1013 /* -- "Year's End", Richard Wilbur */
1015 test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1));
1016 test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2));
1017 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
1018 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
1019 test_streq("on", S1());
1020 test_streq("the", S1());
1021 test_streq("dark", S1());
1022 test_streq("seemed", S2());
1023 test_streq("their", S2());
1024 test_streq("own", S2());
1025 test_streq("in", S1());
1026 test_streq("gestures", S1());
1027 test_streq("of", S1());
1028 test_streq("most", S2());
1029 test_streq("perfect", S2());
1030 test_streq("descent", S1());
1031 test_streq("monument", S2());
1032 test_assert(NULL == S1());
1033 test_assert(NULL == S2());
1034 done:
1038 static void
1039 test_util_find_str_at_start_of_line(void *ptr)
1041 const char *long_string =
1042 "hello world. hello world. hello hello. howdy.\n"
1043 "hello hello world\n";
1045 (void)ptr;
1047 /* not-found case. */
1048 tt_assert(! find_str_at_start_of_line(long_string, "fred"));
1050 /* not-found case where haystack doesn't end with \n */
1051 tt_assert(! find_str_at_start_of_line("foobar\nbaz", "fred"));
1053 /* start-of-string case */
1054 tt_assert(long_string ==
1055 find_str_at_start_of_line(long_string, "hello world."));
1057 /* start-of-line case */
1058 tt_assert(strchr(long_string,'\n')+1 ==
1059 find_str_at_start_of_line(long_string, "hello hello"));
1060 done:
1064 static void
1065 test_util_asprintf(void *ptr)
1067 #define LOREMIPSUM \
1068 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
1069 char *cp=NULL, *cp2=NULL;
1070 int r;
1071 (void)ptr;
1073 /* empty string. */
1074 r = tor_asprintf(&cp, "%s", "");
1075 tt_assert(cp);
1076 tt_int_op(r, ==, strlen(cp));
1077 tt_str_op(cp, ==, "");
1079 /* Short string with some printing in it. */
1080 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
1081 tt_assert(cp2);
1082 tt_int_op(r, ==, strlen(cp2));
1083 tt_str_op(cp2, ==, "First=101, Second=202");
1084 tt_assert(cp != cp2);
1085 tor_free(cp);
1086 tor_free(cp2);
1088 /* Glass-box test: a string exactly 128 characters long. */
1089 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
1090 tt_assert(cp);
1091 tt_int_op(r, ==, 128);
1092 tt_assert(cp[128] == '\0');
1093 tt_str_op(cp, ==,
1094 "Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM);
1095 tor_free(cp);
1097 /* String longer than 128 characters */
1098 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
1099 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
1100 tt_assert(cp);
1101 tt_int_op(r, ==, strlen(cp));
1102 tt_str_op(cp, ==, "1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM);
1104 done:
1105 tor_free(cp);
1106 tor_free(cp2);
1109 #define UTIL_LEGACY(name) \
1110 { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
1112 #define UTIL_TEST(name, flags) \
1113 { #name, test_util_ ## name, flags, NULL, NULL }
1115 struct testcase_t util_tests[] = {
1116 UTIL_LEGACY(time),
1117 UTIL_LEGACY(config_line),
1118 UTIL_LEGACY(strmisc),
1119 UTIL_LEGACY(pow2),
1120 UTIL_LEGACY(gzip),
1121 UTIL_LEGACY(datadir),
1122 UTIL_LEGACY(mempool),
1123 UTIL_LEGACY(memarea),
1124 UTIL_LEGACY(control_formats),
1125 UTIL_LEGACY(mmap),
1126 UTIL_LEGACY(threads),
1127 UTIL_LEGACY(sscanf),
1128 UTIL_LEGACY(strtok),
1129 UTIL_TEST(find_str_at_start_of_line, 0),
1130 UTIL_TEST(asprintf, 0),
1131 END_OF_TESTCASES