fold in more changes files
[tor.git] / src / test / test_util.c
blob9eca90492d5afaae5bdb696eda7baf8fa5471d38
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2012, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "orconfig.h"
7 #define CONTROL_PRIVATE
8 #define MEMPOOL_PRIVATE
9 #define UTIL_PRIVATE
10 #include "or.h"
11 #include "config.h"
12 #include "control.h"
13 #include "test.h"
14 #include "mempool.h"
15 #include "memarea.h"
17 #ifdef _WIN32
18 #include <tchar.h>
19 #endif
21 static void
22 test_util_time(void)
24 struct timeval start, end;
25 struct tm a_time;
26 char timestr[128];
27 time_t t_res;
28 int i;
29 struct timeval tv;
31 /* Test tv_udiff */
33 start.tv_sec = 5;
34 start.tv_usec = 5000;
36 end.tv_sec = 5;
37 end.tv_usec = 5000;
39 test_eq(0L, tv_udiff(&start, &end));
41 end.tv_usec = 7000;
43 test_eq(2000L, tv_udiff(&start, &end));
45 end.tv_sec = 6;
47 test_eq(1002000L, tv_udiff(&start, &end));
49 end.tv_usec = 0;
51 test_eq(995000L, tv_udiff(&start, &end));
53 end.tv_sec = 4;
55 test_eq(-1005000L, tv_udiff(&start, &end));
57 /* Test tor_timegm */
59 /* The test values here are confirmed to be correct on a platform
60 * with a working timegm. */
61 a_time.tm_year = 2003-1900;
62 a_time.tm_mon = 7;
63 a_time.tm_mday = 30;
64 a_time.tm_hour = 6;
65 a_time.tm_min = 14;
66 a_time.tm_sec = 55;
67 test_eq((time_t) 1062224095UL, tor_timegm(&a_time));
68 a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
69 test_eq((time_t) 1093846495UL, tor_timegm(&a_time));
70 a_time.tm_mon = 1; /* Try a leap year, in feb. */
71 a_time.tm_mday = 10;
72 test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
73 a_time.tm_mon = 0;
74 a_time.tm_mday = 10;
75 test_eq((time_t) 1073715295UL, tor_timegm(&a_time));
76 a_time.tm_mon = 12; /* Wrong month, it's 0-based */
77 a_time.tm_mday = 10;
78 test_eq((time_t) -1, tor_timegm(&a_time));
79 a_time.tm_mon = -1; /* Wrong month */
80 a_time.tm_mday = 10;
81 test_eq((time_t) -1, tor_timegm(&a_time));
83 /* Test {format,parse}_rfc1123_time */
85 format_rfc1123_time(timestr, 0);
86 test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr);
87 format_rfc1123_time(timestr, (time_t)1091580502UL);
88 test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr);
90 t_res = 0;
91 i = parse_rfc1123_time(timestr, &t_res);
92 test_eq(0,i);
93 test_eq(t_res, (time_t)1091580502UL);
94 /* The timezone doesn't matter */
95 t_res = 0;
96 test_eq(0, parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
97 test_eq(t_res, (time_t)1091580502UL);
98 test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
99 test_eq(-1, parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
100 test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
101 test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
102 test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
103 test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
104 test_eq(-1, parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
105 test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
107 #if 0
108 /* This fails, I imagine it's important and should be fixed? */
109 test_eq(-1, parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
110 /* Why is this string valid (ie. the test fails because it doesn't
111 return -1)? */
112 test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
113 #endif
115 /* Test parse_iso_time */
117 t_res = 0;
118 i = parse_iso_time("", &t_res);
119 test_eq(-1, i);
120 t_res = 0;
121 i = parse_iso_time("2004-08-32 00:48:22", &t_res);
122 test_eq(-1, i);
123 t_res = 0;
124 i = parse_iso_time("1969-08-03 00:48:22", &t_res);
125 test_eq(-1, i);
127 t_res = 0;
128 i = parse_iso_time("2004-08-04 00:48:22", &t_res);
129 test_eq(0,i);
130 test_eq(t_res, (time_t)1091580502UL);
131 t_res = 0;
132 i = parse_iso_time("2004-8-4 0:48:22", &t_res);
133 test_eq(0, i);
134 test_eq(t_res, (time_t)1091580502UL);
135 test_eq(-1, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res));
136 test_eq(-1, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res));
137 test_eq(-1, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res));
138 test_eq(-1, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res));
139 test_eq(-1, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res));
140 test_eq(-1, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res));
141 test_eq(-1, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res));
142 test_eq(-1, parse_iso_time("2011-03-30 23:59", &t_res));
144 /* Test tor_gettimeofday */
146 end.tv_sec = 4;
147 end.tv_usec = 999990;
148 start.tv_sec = 1;
149 start.tv_usec = 500;
151 tor_gettimeofday(&start);
152 /* now make sure time works. */
153 tor_gettimeofday(&end);
154 /* We might've timewarped a little. */
155 tt_int_op(tv_udiff(&start, &end), >=, -5000);
157 /* Test format_iso_time */
159 tv.tv_sec = (time_t)1326296338;
160 tv.tv_usec = 3060;
161 format_iso_time(timestr, tv.tv_sec);
162 test_streq("2012-01-11 15:38:58", timestr);
163 /* The output of format_local_iso_time will vary by timezone, and setting
164 our timezone for testing purposes would be a nontrivial flaky pain.
165 Skip this test for now.
166 format_local_iso_time(timestr, tv.tv_sec);
167 test_streq("2012-01-11 10:38:58", timestr);
169 format_iso_time_nospace(timestr, tv.tv_sec);
170 test_streq("2012-01-11T15:38:58", timestr);
171 test_eq(strlen(timestr), ISO_TIME_LEN);
172 format_iso_time_nospace_usec(timestr, &tv);
173 test_streq("2012-01-11T15:38:58.003060", timestr);
174 test_eq(strlen(timestr), ISO_TIME_USEC_LEN);
176 done:
180 static void
181 test_util_parse_http_time(void *arg)
183 struct tm a_time;
184 char b[ISO_TIME_LEN+1];
185 (void)arg;
187 #define T(s) do { \
188 format_iso_time(b, tor_timegm(&a_time)); \
189 tt_str_op(b, ==, (s)); \
190 b[0]='\0'; \
191 } while (0)
193 /* Test parse_http_time */
195 test_eq(-1, parse_http_time("", &a_time));
196 test_eq(-1, parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
197 test_eq(-1, parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
198 test_eq(-1, parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
199 test_eq(-1, parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
200 test_eq(-1, parse_http_time("Sunday, August the third", &a_time));
201 test_eq(-1, parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
203 test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
204 test_eq((time_t)775961302UL, tor_timegm(&a_time));
205 T("1994-08-04 00:48:22");
206 test_eq(0, parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
207 test_eq((time_t)775961302UL, tor_timegm(&a_time));
208 T("1994-08-04 00:48:22");
209 test_eq(0, parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
210 test_eq((time_t)775961302UL, tor_timegm(&a_time));
211 T("1994-08-04 00:48:22");
212 test_eq(0, parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
213 test_eq((time_t)775961302UL, tor_timegm(&a_time));
214 T("1994-08-04 00:48:22");
215 test_eq(0, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
216 test_eq((time_t)775961302UL, tor_timegm(&a_time));
217 T("1994-08-04 00:48:22");
218 test_eq(0, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
219 test_eq((time_t)775961302UL, tor_timegm(&a_time));
220 T("1994-08-04 00:48:22");
221 test_eq(0, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
222 test_eq((time_t)775961302UL, tor_timegm(&a_time));
223 T("1994-08-04 00:48:22");
224 test_eq(0, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
225 test_eq((time_t)775961302UL, tor_timegm(&a_time));
226 T("1994-08-04 00:48:22");
227 test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
228 test_eq((time_t)775961302UL, tor_timegm(&a_time));
229 T("1994-08-04 00:48:22");
230 test_eq(0, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
231 test_eq((time_t)1325376000UL, tor_timegm(&a_time));
232 T("2012-01-01 00:00:00");
233 test_eq(0, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
234 test_eq((time_t)1356912000UL, tor_timegm(&a_time));
235 T("2012-12-31 00:00:00");
236 test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
237 test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
238 test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
239 test_eq(-1, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
240 test_eq(-1, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
241 test_eq(-1, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
242 test_eq(-1, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
243 test_eq(-1, parse_http_time("2011-03-30 23:59", &a_time));
245 #undef T
246 done:
250 static void
251 test_util_config_line(void)
253 char buf[1024];
254 char *k=NULL, *v=NULL;
255 const char *str;
257 /* Test parse_config_line_from_str */
258 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
259 "k2\n"
260 "k3 \n" "\n" " \n" "#comment\n"
261 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
262 "kseven \"a quoted 'string\"\n"
263 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
264 "k9 a line that\\\n spans two lines.\n\n"
265 "k10 more than\\\n one contin\\\nuation\n"
266 "k11 \\\ncontinuation at the start\n"
267 "k12 line with a\\\n#comment\n embedded\n"
268 "k13\\\ncontinuation at the very start\n"
269 "k14 a line that has a comment and # ends with a slash \\\n"
270 "k15 this should be the next new line\n"
271 "k16 a line that has a comment and # ends without a slash \n"
272 "k17 this should be the next new line\n"
273 , sizeof(buf));
274 str = buf;
276 str = parse_config_line_from_str(str, &k, &v);
277 test_streq(k, "k");
278 test_streq(v, "v");
279 tor_free(k); tor_free(v);
280 test_assert(!strcmpstart(str, "key value with"));
282 str = parse_config_line_from_str(str, &k, &v);
283 test_streq(k, "key");
284 test_streq(v, "value with spaces");
285 tor_free(k); tor_free(v);
286 test_assert(!strcmpstart(str, "keykey"));
288 str = parse_config_line_from_str(str, &k, &v);
289 test_streq(k, "keykey");
290 test_streq(v, "val");
291 tor_free(k); tor_free(v);
292 test_assert(!strcmpstart(str, "k2\n"));
294 str = parse_config_line_from_str(str, &k, &v);
295 test_streq(k, "k2");
296 test_streq(v, "");
297 tor_free(k); tor_free(v);
298 test_assert(!strcmpstart(str, "k3 \n"));
300 str = parse_config_line_from_str(str, &k, &v);
301 test_streq(k, "k3");
302 test_streq(v, "");
303 tor_free(k); tor_free(v);
304 test_assert(!strcmpstart(str, "#comment"));
306 str = parse_config_line_from_str(str, &k, &v);
307 test_streq(k, "k4");
308 test_streq(v, "");
309 tor_free(k); tor_free(v);
310 test_assert(!strcmpstart(str, "k5#abc"));
312 str = parse_config_line_from_str(str, &k, &v);
313 test_streq(k, "k5");
314 test_streq(v, "");
315 tor_free(k); tor_free(v);
316 test_assert(!strcmpstart(str, "k6"));
318 str = parse_config_line_from_str(str, &k, &v);
319 test_streq(k, "k6");
320 test_streq(v, "val");
321 tor_free(k); tor_free(v);
322 test_assert(!strcmpstart(str, "kseven"));
324 str = parse_config_line_from_str(str, &k, &v);
325 test_streq(k, "kseven");
326 test_streq(v, "a quoted \'string");
327 tor_free(k); tor_free(v);
328 test_assert(!strcmpstart(str, "k8 "));
330 str = parse_config_line_from_str(str, &k, &v);
331 test_streq(k, "k8");
332 test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
333 tor_free(k); tor_free(v);
335 str = parse_config_line_from_str(str, &k, &v);
336 test_streq(k, "k9");
337 test_streq(v, "a line that spans two lines.");
338 tor_free(k); tor_free(v);
340 str = parse_config_line_from_str(str, &k, &v);
341 test_streq(k, "k10");
342 test_streq(v, "more than one continuation");
343 tor_free(k); tor_free(v);
345 str = parse_config_line_from_str(str, &k, &v);
346 test_streq(k, "k11");
347 test_streq(v, "continuation at the start");
348 tor_free(k); tor_free(v);
350 str = parse_config_line_from_str(str, &k, &v);
351 test_streq(k, "k12");
352 test_streq(v, "line with a embedded");
353 tor_free(k); tor_free(v);
355 str = parse_config_line_from_str(str, &k, &v);
356 test_streq(k, "k13");
357 test_streq(v, "continuation at the very start");
358 tor_free(k); tor_free(v);
360 str = parse_config_line_from_str(str, &k, &v);
361 test_streq(k, "k14");
362 test_streq(v, "a line that has a comment and" );
363 tor_free(k); tor_free(v);
365 str = parse_config_line_from_str(str, &k, &v);
366 test_streq(k, "k15");
367 test_streq(v, "this should be the next new line");
368 tor_free(k); tor_free(v);
370 str = parse_config_line_from_str(str, &k, &v);
371 test_streq(k, "k16");
372 test_streq(v, "a line that has a comment and" );
373 tor_free(k); tor_free(v);
375 str = parse_config_line_from_str(str, &k, &v);
376 test_streq(k, "k17");
377 test_streq(v, "this should be the next new line");
378 tor_free(k); tor_free(v);
380 test_streq(str, "");
382 done:
383 tor_free(k);
384 tor_free(v);
387 static void
388 test_util_config_line_quotes(void)
390 char buf1[1024];
391 char buf2[128];
392 char buf3[128];
393 char buf4[128];
394 char *k=NULL, *v=NULL;
395 const char *str;
397 /* Test parse_config_line_from_str */
398 strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
399 "kTrailingGarbage \"quoted value\"trailing garbage\n"
400 , sizeof(buf1));
401 strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
402 , sizeof(buf2));
403 strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
404 , sizeof(buf3));
405 strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
406 , sizeof(buf4));
407 str = buf1;
409 str = parse_config_line_from_str(str, &k, &v);
410 test_streq(k, "kTrailingSpace");
411 test_streq(v, "quoted value");
412 tor_free(k); tor_free(v);
414 str = parse_config_line_from_str(str, &k, &v);
415 test_eq_ptr(str, NULL);
416 tor_free(k); tor_free(v);
418 str = buf2;
420 str = parse_config_line_from_str(str, &k, &v);
421 test_eq_ptr(str, NULL);
422 tor_free(k); tor_free(v);
424 str = buf3;
426 str = parse_config_line_from_str(str, &k, &v);
427 test_eq_ptr(str, NULL);
428 tor_free(k); tor_free(v);
430 str = buf4;
432 str = parse_config_line_from_str(str, &k, &v);
433 test_eq_ptr(str, NULL);
434 tor_free(k); tor_free(v);
436 done:
437 tor_free(k);
438 tor_free(v);
441 static void
442 test_util_config_line_comment_character(void)
444 char buf[1024];
445 char *k=NULL, *v=NULL;
446 const char *str;
448 /* Test parse_config_line_from_str */
449 strlcpy(buf, "k1 \"# in quotes\"\n"
450 "k2 some value # some comment\n"
451 "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
452 , sizeof(buf));
453 str = buf;
455 str = parse_config_line_from_str(str, &k, &v);
456 test_streq(k, "k1");
457 test_streq(v, "# in quotes");
458 tor_free(k); tor_free(v);
460 str = parse_config_line_from_str(str, &k, &v);
461 test_streq(k, "k2");
462 test_streq(v, "some value");
463 tor_free(k); tor_free(v);
465 test_streq(str, "k3 /home/user/myTorNetwork#2\n");
467 #if 0
468 str = parse_config_line_from_str(str, &k, &v);
469 test_streq(k, "k3");
470 test_streq(v, "/home/user/myTorNetwork#2");
471 tor_free(k); tor_free(v);
473 test_streq(str, "");
474 #endif
476 done:
477 tor_free(k);
478 tor_free(v);
481 static void
482 test_util_config_line_escaped_content(void)
484 char buf1[1024];
485 char buf2[128];
486 char buf3[128];
487 char buf4[128];
488 char buf5[128];
489 char buf6[128];
490 char *k=NULL, *v=NULL;
491 const char *str;
493 /* Test parse_config_line_from_str */
494 strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
495 "HexadecimalUpper \"\\x2A\"\n"
496 "HexadecimalUpperX \"\\X2A\"\n"
497 "Octal \"\\52\"\n"
498 "Newline \"\\n\"\n"
499 "Tab \"\\t\"\n"
500 "CarriageReturn \"\\r\"\n"
501 "DoubleQuote \"\\\"\"\n"
502 "SimpleQuote \"\\'\"\n"
503 "Backslash \"\\\\\"\n"
504 "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
505 , sizeof(buf1));
507 strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
508 , sizeof(buf2));
510 strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
511 , sizeof(buf3));
513 strlcpy(buf4, "BrokenOctal \"\\8\"\n"
514 , sizeof(buf4));
516 strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
517 , sizeof(buf5));
519 strlcpy(buf6, "BrokenEscape \"\\"
520 , sizeof(buf6));
522 str = buf1;
524 str = parse_config_line_from_str(str, &k, &v);
525 test_streq(k, "HexadecimalLower");
526 test_streq(v, "*");
527 tor_free(k); tor_free(v);
529 str = parse_config_line_from_str(str, &k, &v);
530 test_streq(k, "HexadecimalUpper");
531 test_streq(v, "*");
532 tor_free(k); tor_free(v);
534 str = parse_config_line_from_str(str, &k, &v);
535 test_streq(k, "HexadecimalUpperX");
536 test_streq(v, "*");
537 tor_free(k); tor_free(v);
539 str = parse_config_line_from_str(str, &k, &v);
540 test_streq(k, "Octal");
541 test_streq(v, "*");
542 tor_free(k); tor_free(v);
544 str = parse_config_line_from_str(str, &k, &v);
545 test_streq(k, "Newline");
546 test_streq(v, "\n");
547 tor_free(k); tor_free(v);
549 str = parse_config_line_from_str(str, &k, &v);
550 test_streq(k, "Tab");
551 test_streq(v, "\t");
552 tor_free(k); tor_free(v);
554 str = parse_config_line_from_str(str, &k, &v);
555 test_streq(k, "CarriageReturn");
556 test_streq(v, "\r");
557 tor_free(k); tor_free(v);
559 str = parse_config_line_from_str(str, &k, &v);
560 test_streq(k, "DoubleQuote");
561 test_streq(v, "\"");
562 tor_free(k); tor_free(v);
564 str = parse_config_line_from_str(str, &k, &v);
565 test_streq(k, "SimpleQuote");
566 test_streq(v, "'");
567 tor_free(k); tor_free(v);
569 str = parse_config_line_from_str(str, &k, &v);
570 test_streq(k, "Backslash");
571 test_streq(v, "\\");
572 tor_free(k); tor_free(v);
574 str = parse_config_line_from_str(str, &k, &v);
575 test_streq(k, "Mix");
576 test_streq(v, "This is a \"star\":\t'*'\nAnd second line");
577 tor_free(k); tor_free(v);
578 test_streq(str, "");
580 str = buf2;
582 str = parse_config_line_from_str(str, &k, &v);
583 test_eq_ptr(str, NULL);
584 tor_free(k); tor_free(v);
586 str = buf3;
588 str = parse_config_line_from_str(str, &k, &v);
589 test_eq_ptr(str, NULL);
590 tor_free(k); tor_free(v);
592 str = buf4;
594 str = parse_config_line_from_str(str, &k, &v);
595 test_eq_ptr(str, NULL);
596 tor_free(k); tor_free(v);
598 #if 0
599 str = buf5;
601 str = parse_config_line_from_str(str, &k, &v);
602 test_eq_ptr(str, NULL);
603 tor_free(k); tor_free(v);
604 #endif
606 str = buf6;
608 str = parse_config_line_from_str(str, &k, &v);
609 test_eq_ptr(str, NULL);
610 tor_free(k); tor_free(v);
612 done:
613 tor_free(k);
614 tor_free(v);
617 #ifndef _WIN32
618 static void
619 test_util_expand_filename(void)
621 char *str;
623 setenv("HOME", "/home/itv", 1); /* For "internal test value" */
625 str = expand_filename("");
626 test_streq("", str);
627 tor_free(str);
629 str = expand_filename("/normal/path");
630 test_streq("/normal/path", str);
631 tor_free(str);
633 str = expand_filename("/normal/trailing/path/");
634 test_streq("/normal/trailing/path/", str);
635 tor_free(str);
637 str = expand_filename("~");
638 test_streq("/home/itv/", str);
639 tor_free(str);
641 str = expand_filename("$HOME/nodice");
642 test_streq("$HOME/nodice", str);
643 tor_free(str);
645 str = expand_filename("~/");
646 test_streq("/home/itv/", str);
647 tor_free(str);
649 str = expand_filename("~/foobarqux");
650 test_streq("/home/itv/foobarqux", str);
651 tor_free(str);
653 str = expand_filename("~/../../etc/passwd");
654 test_streq("/home/itv/../../etc/passwd", str);
655 tor_free(str);
657 str = expand_filename("~/trailing/");
658 test_streq("/home/itv/trailing/", str);
659 tor_free(str);
660 /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
661 have to somehow inject/fake the get_user_homedir call) */
663 /* $HOME ending in a trailing slash */
664 setenv("HOME", "/home/itv/", 1);
666 str = expand_filename("~");
667 test_streq("/home/itv/", str);
668 tor_free(str);
670 str = expand_filename("~/");
671 test_streq("/home/itv/", str);
672 tor_free(str);
674 str = expand_filename("~/foo");
675 test_streq("/home/itv/foo", str);
676 tor_free(str);
678 /* Try with empty $HOME */
680 setenv("HOME", "", 1);
682 str = expand_filename("~");
683 test_streq("/", str);
684 tor_free(str);
686 str = expand_filename("~/");
687 test_streq("/", str);
688 tor_free(str);
690 str = expand_filename("~/foobar");
691 test_streq("/foobar", str);
692 tor_free(str);
694 /* Try with $HOME unset */
696 unsetenv("HOME");
698 str = expand_filename("~");
699 test_streq("/", str);
700 tor_free(str);
702 str = expand_filename("~/");
703 test_streq("/", str);
704 tor_free(str);
706 str = expand_filename("~/foobar");
707 test_streq("/foobar", str);
708 tor_free(str);
710 done:
711 tor_free(str);
713 #endif
715 /** Test basic string functionality. */
716 static void
717 test_util_strmisc(void)
719 char buf[1024];
720 int i;
721 char *cp;
723 /* Test strl operations */
724 test_eq(5, strlcpy(buf, "Hello", 0));
725 test_eq(5, strlcpy(buf, "Hello", 10));
726 test_streq(buf, "Hello");
727 test_eq(5, strlcpy(buf, "Hello", 6));
728 test_streq(buf, "Hello");
729 test_eq(5, strlcpy(buf, "Hello", 5));
730 test_streq(buf, "Hell");
731 strlcpy(buf, "Hello", sizeof(buf));
732 test_eq(10, strlcat(buf, "Hello", 5));
734 /* Test strstrip() */
735 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
736 tor_strstrip(buf, ",!");
737 test_streq(buf, "Testing 1 2 3");
738 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
739 tor_strstrip(buf, "!? ");
740 test_streq(buf, "Testing123");
741 strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
742 tor_strstrip(buf, "!? ");
743 test_streq(buf, "Testing123");
745 /* Test parse_long */
746 /* Empty/zero input */
747 test_eq(0L, tor_parse_long("",10,0,100,&i,NULL));
748 test_eq(0, i);
749 test_eq(0L, tor_parse_long("0",10,0,100,&i,NULL));
750 test_eq(1, i);
751 /* Normal cases */
752 test_eq(10L, tor_parse_long("10",10,0,100,&i,NULL));
753 test_eq(1, i);
754 test_eq(10L, tor_parse_long("10",10,0,10,&i,NULL));
755 test_eq(1, i);
756 test_eq(10L, tor_parse_long("10",10,10,100,&i,NULL));
757 test_eq(1, i);
758 test_eq(-50L, tor_parse_long("-50",10,-100,100,&i,NULL));
759 test_eq(1, i);
760 test_eq(-50L, tor_parse_long("-50",10,-100,0,&i,NULL));
761 test_eq(1, i);
762 test_eq(-50L, tor_parse_long("-50",10,-50,0,&i,NULL));
763 test_eq(1, i);
764 /* Extra garbage */
765 test_eq(0L, tor_parse_long("10m",10,0,100,&i,NULL));
766 test_eq(0, i);
767 test_eq(0L, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
768 test_eq(0, i);
769 test_eq(10L, tor_parse_long("10m",10,0,100,&i,&cp));
770 test_eq(1, i);
771 test_streq(cp, "m");
772 test_eq(-50L, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
773 test_eq(1, i);
774 test_streq(cp, " plus garbage");
775 /* Out of bounds */
776 test_eq(0L, tor_parse_long("10",10,50,100,&i,NULL));
777 test_eq(0, i);
778 test_eq(0L, tor_parse_long("-50",10,0,100,&i,NULL));
779 test_eq(0, i);
780 /* Base different than 10 */
781 test_eq(2L, tor_parse_long("10",2,0,100,NULL,NULL));
782 test_eq(0L, tor_parse_long("2",2,0,100,NULL,NULL));
783 test_eq(0L, tor_parse_long("10",-2,0,100,NULL,NULL));
784 test_eq(68284L, tor_parse_long("10abc",16,0,70000,NULL,NULL));
785 test_eq(68284L, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
787 /* Test parse_ulong */
788 test_eq(0UL, tor_parse_ulong("",10,0,100,NULL,NULL));
789 test_eq(0UL, tor_parse_ulong("0",10,0,100,NULL,NULL));
790 test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL));
791 test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL));
792 test_eq(10UL, tor_parse_ulong("10",10,0,10,NULL,NULL));
793 test_eq(10UL, tor_parse_ulong("10",10,10,100,NULL,NULL));
794 test_eq(0UL, tor_parse_ulong("8",8,0,100,NULL,NULL));
795 test_eq(50UL, tor_parse_ulong("50",10,50,100,NULL,NULL));
796 test_eq(0UL, tor_parse_ulong("-50",10,-100,100,NULL,NULL));
798 /* Test parse_uint64 */
799 test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
800 test_eq(1, i);
801 test_streq(cp, " x");
802 test_assert(U64_LITERAL(12345678901) ==
803 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
804 test_eq(1, i);
805 test_streq(cp, "");
806 test_assert(U64_LITERAL(0) ==
807 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
808 test_eq(0, i);
811 /* Test parse_double */
812 double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL);
813 test_eq(1, i);
814 test_assert(DBL_TO_U64(d) == 10);
815 d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL);
816 test_eq(1, i);
817 test_assert(DBL_TO_U64(d) == 0);
818 d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL);
819 test_eq(0, i);
820 d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL);
821 test_eq(0, i);
822 d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp);
823 test_eq(1, i);
824 d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL);
825 test_eq(1, i);
826 test_assert(DBL_TO_U64(d) == 0);
827 d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
828 test_eq(1, i);
829 test_eq(-10.0, d);
833 /* Test tor_parse_* where we overflow/underflow the underlying type. */
834 /* This string should overflow 64-bit ints. */
835 #define TOOBIG "100000000000000000000000000"
836 test_eq(0L, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
837 test_eq(i, 0);
838 test_eq(0L, tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
839 test_eq(i, 0);
840 test_eq(0UL, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
841 test_eq(i, 0);
842 test_eq(U64_LITERAL(0), tor_parse_uint64(TOOBIG, 10,
843 0, UINT64_MAX, &i, NULL));
844 test_eq(i, 0);
847 /* Test snprintf */
848 /* Returning -1 when there's not enough room in the output buffer */
849 test_eq(-1, tor_snprintf(buf, 0, "Foo"));
850 test_eq(-1, tor_snprintf(buf, 2, "Foo"));
851 test_eq(-1, tor_snprintf(buf, 3, "Foo"));
852 test_neq(-1, tor_snprintf(buf, 4, "Foo"));
853 /* Always NUL-terminate the output */
854 tor_snprintf(buf, 5, "abcdef");
855 test_eq(0, buf[4]);
856 tor_snprintf(buf, 10, "abcdef");
857 test_eq(0, buf[6]);
858 /* uint64 */
859 tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
860 U64_PRINTF_ARG(U64_LITERAL(12345678901)));
861 test_streq("x!12345678901!x", buf);
863 /* Test str{,case}cmpstart */
864 test_assert(strcmpstart("abcdef", "abcdef")==0);
865 test_assert(strcmpstart("abcdef", "abc")==0);
866 test_assert(strcmpstart("abcdef", "abd")<0);
867 test_assert(strcmpstart("abcdef", "abb")>0);
868 test_assert(strcmpstart("ab", "abb")<0);
869 test_assert(strcmpstart("ab", "")==0);
870 test_assert(strcmpstart("ab", "ab ")<0);
871 test_assert(strcasecmpstart("abcdef", "abCdEF")==0);
872 test_assert(strcasecmpstart("abcDeF", "abc")==0);
873 test_assert(strcasecmpstart("abcdef", "Abd")<0);
874 test_assert(strcasecmpstart("Abcdef", "abb")>0);
875 test_assert(strcasecmpstart("ab", "Abb")<0);
876 test_assert(strcasecmpstart("ab", "")==0);
877 test_assert(strcasecmpstart("ab", "ab ")<0);
879 /* Test str{,case}cmpend */
880 test_assert(strcmpend("abcdef", "abcdef")==0);
881 test_assert(strcmpend("abcdef", "def")==0);
882 test_assert(strcmpend("abcdef", "deg")<0);
883 test_assert(strcmpend("abcdef", "dee")>0);
884 test_assert(strcmpend("ab", "aab")>0);
885 test_assert(strcasecmpend("AbcDEF", "abcdef")==0);
886 test_assert(strcasecmpend("abcdef", "dEF")==0);
887 test_assert(strcasecmpend("abcdef", "Deg")<0);
888 test_assert(strcasecmpend("abcDef", "dee")>0);
889 test_assert(strcasecmpend("AB", "abb")<0);
891 /* Test digest_is_zero */
892 memset(buf,0,20);
893 buf[20] = 'x';
894 test_assert(tor_digest_is_zero(buf));
895 buf[19] = 'x';
896 test_assert(!tor_digest_is_zero(buf));
898 /* Test mem_is_zero */
899 memset(buf,0,128);
900 buf[128] = 'x';
901 test_assert(tor_mem_is_zero(buf, 10));
902 test_assert(tor_mem_is_zero(buf, 20));
903 test_assert(tor_mem_is_zero(buf, 128));
904 test_assert(!tor_mem_is_zero(buf, 129));
905 buf[60] = (char)255;
906 test_assert(!tor_mem_is_zero(buf, 128));
907 buf[0] = (char)1;
908 test_assert(!tor_mem_is_zero(buf, 10));
910 /* Test 'escaped' */
911 test_assert(NULL == escaped(NULL));
912 test_streq("\"\"", escaped(""));
913 test_streq("\"abcd\"", escaped("abcd"));
914 test_streq("\"\\\\ \\n\\r\\t\\\"\\'\"", escaped("\\ \n\r\t\"'"));
915 test_streq("\"unnecessary \\'backslashes\\'\"",
916 escaped("unnecessary \'backslashes\'"));
917 /* Non-printable characters appear as octal */
918 test_streq("\"z\\001abc\\277d\"", escaped("z\001abc\277d"));
919 test_streq("\"z\\336\\255 ;foo\"", escaped("z\xde\xad\x20;foo"));
921 /* Test strndup and memdup */
923 const char *s = "abcdefghijklmnopqrstuvwxyz";
924 cp = tor_strndup(s, 30);
925 test_streq(cp, s); /* same string, */
926 test_neq(cp, s); /* but different pointers. */
927 tor_free(cp);
929 cp = tor_strndup(s, 5);
930 test_streq(cp, "abcde");
931 tor_free(cp);
933 s = "a\0b\0c\0d\0e\0";
934 cp = tor_memdup(s,10);
935 test_memeq(cp, s, 10); /* same ram, */
936 test_neq(cp, s); /* but different pointers. */
937 tor_free(cp);
940 /* Test str-foo functions */
941 cp = tor_strdup("abcdef");
942 test_assert(tor_strisnonupper(cp));
943 cp[3] = 'D';
944 test_assert(!tor_strisnonupper(cp));
945 tor_strupper(cp);
946 test_streq(cp, "ABCDEF");
947 tor_strlower(cp);
948 test_streq(cp, "abcdef");
949 test_assert(tor_strisnonupper(cp));
950 test_assert(tor_strisprint(cp));
951 cp[3] = 3;
952 test_assert(!tor_strisprint(cp));
953 tor_free(cp);
955 /* Test memmem and memstr */
957 const char *haystack = "abcde";
958 test_assert(!tor_memmem(haystack, 5, "ef", 2));
959 test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
960 test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
961 test_assert(!tor_memmem(haystack, 4, "cde", 3));
962 haystack = "ababcad";
963 test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2);
964 /* memstr */
965 test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2);
966 test_eq_ptr(tor_memstr(haystack, 7, "cad"), haystack + 4);
967 test_assert(!tor_memstr(haystack, 6, "cad"));
968 test_assert(!tor_memstr(haystack, 7, "cadd"));
969 test_assert(!tor_memstr(haystack, 7, "fe"));
970 test_assert(!tor_memstr(haystack, 7, "ababcade"));
973 /* Test wrap_string */
975 smartlist_t *sl = smartlist_new();
976 wrap_string(sl,
977 "This is a test of string wrapping functionality: woot. "
978 "a functionality? w00t w00t...!",
979 10, "", "");
980 cp = smartlist_join_strings(sl, "", 0, NULL);
981 test_streq(cp,
982 "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n"
983 "a\nfunctional\nity? w00t\nw00t...!\n");
984 tor_free(cp);
985 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
986 smartlist_clear(sl);
988 wrap_string(sl, "This is a test of string wrapping functionality: woot.",
989 16, "### ", "# ");
990 cp = smartlist_join_strings(sl, "", 0, NULL);
991 test_streq(cp,
992 "### This is a\n# test of string\n# wrapping\n# functionality:\n"
993 "# woot.\n");
994 tor_free(cp);
995 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
996 smartlist_clear(sl);
998 wrap_string(sl, "A test of string wrapping...", 6, "### ", "# ");
999 cp = smartlist_join_strings(sl, "", 0, NULL);
1000 test_streq(cp,
1001 "### A\n# test\n# of\n# stri\n# ng\n# wrap\n# ping\n# ...\n");
1002 tor_free(cp);
1003 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
1004 smartlist_clear(sl);
1006 wrap_string(sl, "Wrapping test", 6, "#### ", "# ");
1007 cp = smartlist_join_strings(sl, "", 0, NULL);
1008 test_streq(cp, "#### W\n# rapp\n# ing\n# test\n");
1009 tor_free(cp);
1010 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
1011 smartlist_clear(sl);
1013 wrap_string(sl, "Small test", 6, "### ", "#### ");
1014 cp = smartlist_join_strings(sl, "", 0, NULL);
1015 test_streq(cp, "### Sm\n#### a\n#### l\n#### l\n#### t\n#### e"
1016 "\n#### s\n#### t\n");
1017 tor_free(cp);
1018 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
1019 smartlist_clear(sl);
1021 wrap_string(sl, "First null", 6, NULL, "> ");
1022 cp = smartlist_join_strings(sl, "", 0, NULL);
1023 test_streq(cp, "First\n> null\n");
1024 tor_free(cp);
1025 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
1026 smartlist_clear(sl);
1028 wrap_string(sl, "Second null", 6, "> ", NULL);
1029 cp = smartlist_join_strings(sl, "", 0, NULL);
1030 test_streq(cp, "> Seco\nnd\nnull\n");
1031 tor_free(cp);
1032 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
1033 smartlist_clear(sl);
1035 wrap_string(sl, "Both null", 6, NULL, NULL);
1036 cp = smartlist_join_strings(sl, "", 0, NULL);
1037 test_streq(cp, "Both\nnull\n");
1038 tor_free(cp);
1039 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
1040 smartlist_free(sl);
1042 /* Can't test prefixes that have the same length as the line width, because
1043 the function has an assert */
1046 /* Test hex_str */
1048 char binary_data[68];
1049 size_t i;
1050 for (i = 0; i < sizeof(binary_data); ++i)
1051 binary_data[i] = i;
1052 test_streq(hex_str(binary_data, 0), "");
1053 test_streq(hex_str(binary_data, 1), "00");
1054 test_streq(hex_str(binary_data, 17), "000102030405060708090A0B0C0D0E0F10");
1055 test_streq(hex_str(binary_data, 32),
1056 "000102030405060708090A0B0C0D0E0F"
1057 "101112131415161718191A1B1C1D1E1F");
1058 test_streq(hex_str(binary_data, 34),
1059 "000102030405060708090A0B0C0D0E0F"
1060 "101112131415161718191A1B1C1D1E1F");
1061 /* Repeat these tests for shorter strings after longer strings
1062 have been tried, to make sure we're correctly terminating strings */
1063 test_streq(hex_str(binary_data, 1), "00");
1064 test_streq(hex_str(binary_data, 0), "");
1067 /* Test strcmp_opt */
1068 tt_int_op(strcmp_opt("", "foo"), <, 0);
1069 tt_int_op(strcmp_opt("", ""), ==, 0);
1070 tt_int_op(strcmp_opt("foo", ""), >, 0);
1072 tt_int_op(strcmp_opt(NULL, ""), <, 0);
1073 tt_int_op(strcmp_opt(NULL, NULL), ==, 0);
1074 tt_int_op(strcmp_opt("", NULL), >, 0);
1076 tt_int_op(strcmp_opt(NULL, "foo"), <, 0);
1077 tt_int_op(strcmp_opt("foo", NULL), >, 0);
1079 /* Test strcmp_len */
1080 tt_int_op(strcmp_len("foo", "bar", 3), >, 0);
1081 tt_int_op(strcmp_len("foo", "bar", 2), <, 0); /* First len, then lexical */
1082 tt_int_op(strcmp_len("foo2", "foo1", 4), >, 0);
1083 tt_int_op(strcmp_len("foo2", "foo1", 3), <, 0); /* Really stop at len */
1084 tt_int_op(strcmp_len("foo2", "foo", 3), ==, 0); /* Really stop at len */
1085 tt_int_op(strcmp_len("blah", "", 4), >, 0);
1086 tt_int_op(strcmp_len("blah", "", 0), ==, 0);
1088 done:
1092 static void
1093 test_util_pow2(void)
1095 /* Test tor_log2(). */
1096 test_eq(tor_log2(64), 6);
1097 test_eq(tor_log2(65), 6);
1098 test_eq(tor_log2(63), 5);
1099 test_eq(tor_log2(1), 0);
1100 test_eq(tor_log2(2), 1);
1101 test_eq(tor_log2(3), 1);
1102 test_eq(tor_log2(4), 2);
1103 test_eq(tor_log2(5), 2);
1104 test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55);
1105 test_eq(tor_log2(UINT64_MAX), 63);
1107 /* Test round_to_power_of_2 */
1108 test_eq(round_to_power_of_2(120), 128);
1109 test_eq(round_to_power_of_2(128), 128);
1110 test_eq(round_to_power_of_2(130), 128);
1111 test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)),
1112 U64_LITERAL(1)<<55);
1113 test_eq(round_to_power_of_2(0), 2);
1115 done:
1119 /** mutex for thread test to stop the threads hitting data at the same time. */
1120 static tor_mutex_t *_thread_test_mutex = NULL;
1121 /** mutexes for the thread test to make sure that the threads have to
1122 * interleave somewhat. */
1123 static tor_mutex_t *_thread_test_start1 = NULL,
1124 *_thread_test_start2 = NULL;
1125 /** Shared strmap for the thread test. */
1126 static strmap_t *_thread_test_strmap = NULL;
1127 /** The name of thread1 for the thread test */
1128 static char *_thread1_name = NULL;
1129 /** The name of thread2 for the thread test */
1130 static char *_thread2_name = NULL;
1132 static void _thread_test_func(void* _s) ATTR_NORETURN;
1134 /** How many iterations have the threads in the unit test run? */
1135 static int t1_count = 0, t2_count = 0;
1137 /** Helper function for threading unit tests: This function runs in a
1138 * subthread. It grabs its own mutex (start1 or start2) to make sure that it
1139 * should start, then it repeatedly alters _test_thread_strmap protected by
1140 * _thread_test_mutex. */
1141 static void
1142 _thread_test_func(void* _s)
1144 char *s = _s;
1145 int i, *count;
1146 tor_mutex_t *m;
1147 char buf[64];
1148 char **cp;
1149 if (!strcmp(s, "thread 1")) {
1150 m = _thread_test_start1;
1151 cp = &_thread1_name;
1152 count = &t1_count;
1153 } else {
1154 m = _thread_test_start2;
1155 cp = &_thread2_name;
1156 count = &t2_count;
1159 tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id());
1160 *cp = tor_strdup(buf);
1162 tor_mutex_acquire(m);
1164 for (i=0; i<10000; ++i) {
1165 tor_mutex_acquire(_thread_test_mutex);
1166 strmap_set(_thread_test_strmap, "last to run", *cp);
1167 ++*count;
1168 tor_mutex_release(_thread_test_mutex);
1170 tor_mutex_acquire(_thread_test_mutex);
1171 strmap_set(_thread_test_strmap, s, *cp);
1172 tor_mutex_release(_thread_test_mutex);
1174 tor_mutex_release(m);
1176 spawn_exit();
1179 /** Run unit tests for threading logic. */
1180 static void
1181 test_util_threads(void)
1183 char *s1 = NULL, *s2 = NULL;
1184 int done = 0, timedout = 0;
1185 time_t started;
1186 #ifndef _WIN32
1187 struct timeval tv;
1188 tv.tv_sec=0;
1189 tv.tv_usec=100*1000;
1190 #endif
1191 #ifndef TOR_IS_MULTITHREADED
1192 /* Skip this test if we aren't threading. We should be threading most
1193 * everywhere by now. */
1194 if (1)
1195 return;
1196 #endif
1197 _thread_test_mutex = tor_mutex_new();
1198 _thread_test_start1 = tor_mutex_new();
1199 _thread_test_start2 = tor_mutex_new();
1200 _thread_test_strmap = strmap_new();
1201 s1 = tor_strdup("thread 1");
1202 s2 = tor_strdup("thread 2");
1203 tor_mutex_acquire(_thread_test_start1);
1204 tor_mutex_acquire(_thread_test_start2);
1205 spawn_func(_thread_test_func, s1);
1206 spawn_func(_thread_test_func, s2);
1207 tor_mutex_release(_thread_test_start2);
1208 tor_mutex_release(_thread_test_start1);
1209 started = time(NULL);
1210 while (!done) {
1211 tor_mutex_acquire(_thread_test_mutex);
1212 strmap_assert_ok(_thread_test_strmap);
1213 if (strmap_get(_thread_test_strmap, "thread 1") &&
1214 strmap_get(_thread_test_strmap, "thread 2")) {
1215 done = 1;
1216 } else if (time(NULL) > started + 150) {
1217 timedout = done = 1;
1219 tor_mutex_release(_thread_test_mutex);
1220 #ifndef _WIN32
1221 /* Prevent the main thread from starving the worker threads. */
1222 select(0, NULL, NULL, NULL, &tv);
1223 #endif
1225 tor_mutex_acquire(_thread_test_start1);
1226 tor_mutex_release(_thread_test_start1);
1227 tor_mutex_acquire(_thread_test_start2);
1228 tor_mutex_release(_thread_test_start2);
1230 tor_mutex_free(_thread_test_mutex);
1232 if (timedout) {
1233 printf("\nTimed out: %d %d", t1_count, t2_count);
1234 test_assert(strmap_get(_thread_test_strmap, "thread 1"));
1235 test_assert(strmap_get(_thread_test_strmap, "thread 2"));
1236 test_assert(!timedout);
1239 /* different thread IDs. */
1240 test_assert(strcmp(strmap_get(_thread_test_strmap, "thread 1"),
1241 strmap_get(_thread_test_strmap, "thread 2")));
1242 test_assert(!strcmp(strmap_get(_thread_test_strmap, "thread 1"),
1243 strmap_get(_thread_test_strmap, "last to run")) ||
1244 !strcmp(strmap_get(_thread_test_strmap, "thread 2"),
1245 strmap_get(_thread_test_strmap, "last to run")));
1247 done:
1248 tor_free(s1);
1249 tor_free(s2);
1250 tor_free(_thread1_name);
1251 tor_free(_thread2_name);
1252 if (_thread_test_strmap)
1253 strmap_free(_thread_test_strmap, NULL);
1254 if (_thread_test_start1)
1255 tor_mutex_free(_thread_test_start1);
1256 if (_thread_test_start2)
1257 tor_mutex_free(_thread_test_start2);
1260 /** Run unit tests for compression functions */
1261 static void
1262 test_util_gzip(void)
1264 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
1265 const char *ccp2;
1266 size_t len1, len2;
1267 tor_zlib_state_t *state = NULL;
1269 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
1270 test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
1271 if (is_gzip_supported()) {
1272 test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
1273 GZIP_METHOD));
1274 test_assert(buf2);
1275 test_assert(len1 < strlen(buf1));
1276 test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
1278 test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
1279 GZIP_METHOD, 1, LOG_INFO));
1280 test_assert(buf3);
1281 test_eq(strlen(buf1) + 1, len2);
1282 test_streq(buf1, buf3);
1284 tor_free(buf2);
1285 tor_free(buf3);
1288 test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
1289 ZLIB_METHOD));
1290 test_assert(buf2);
1291 test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
1293 test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
1294 ZLIB_METHOD, 1, LOG_INFO));
1295 test_assert(buf3);
1296 test_eq(strlen(buf1) + 1, len2);
1297 test_streq(buf1, buf3);
1299 /* Check whether we can uncompress concatenated, compressed strings. */
1300 tor_free(buf3);
1301 buf2 = tor_realloc(buf2, len1*2);
1302 memcpy(buf2+len1, buf2, len1);
1303 test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
1304 ZLIB_METHOD, 1, LOG_INFO));
1305 test_eq((strlen(buf1)+1)*2, len2);
1306 test_memeq(buf3,
1307 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
1308 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
1309 (strlen(buf1)+1)*2);
1311 tor_free(buf1);
1312 tor_free(buf2);
1313 tor_free(buf3);
1315 /* Check whether we can uncompress partial strings. */
1316 buf1 =
1317 tor_strdup("String with low redundancy that won't be compressed much.");
1318 test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
1319 ZLIB_METHOD));
1320 tt_assert(len1>16);
1321 /* when we allow an incomplete string, we should succeed.*/
1322 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
1323 ZLIB_METHOD, 0, LOG_INFO));
1324 tt_assert(len2 > 5);
1325 buf3[len2]='\0';
1326 tt_assert(!strcmpstart(buf1, buf3));
1328 /* when we demand a complete string, this must fail. */
1329 tor_free(buf3);
1330 tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
1331 ZLIB_METHOD, 1, LOG_INFO));
1332 tt_assert(!buf3);
1334 /* Now, try streaming compression. */
1335 tor_free(buf1);
1336 tor_free(buf2);
1337 tor_free(buf3);
1338 state = tor_zlib_new(1, ZLIB_METHOD);
1339 tt_assert(state);
1340 cp1 = buf1 = tor_malloc(1024);
1341 len1 = 1024;
1342 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
1343 len2 = 21;
1344 test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
1345 == TOR_ZLIB_OK);
1346 test_eq(0, len2); /* Make sure we compressed it all. */
1347 test_assert(cp1 > buf1);
1349 len2 = 0;
1350 cp2 = cp1;
1351 test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
1352 == TOR_ZLIB_DONE);
1353 test_eq(0, len2);
1354 test_assert(cp1 > cp2); /* Make sure we really added something. */
1356 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
1357 ZLIB_METHOD, 1, LOG_WARN));
1358 test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
1359 test_eq(21, len2);
1361 done:
1362 if (state)
1363 tor_zlib_free(state);
1364 tor_free(buf2);
1365 tor_free(buf3);
1366 tor_free(buf1);
1369 /** Run unit tests for mmap() wrapper functionality. */
1370 static void
1371 test_util_mmap(void)
1373 char *fname1 = tor_strdup(get_fname("mapped_1"));
1374 char *fname2 = tor_strdup(get_fname("mapped_2"));
1375 char *fname3 = tor_strdup(get_fname("mapped_3"));
1376 const size_t buflen = 17000;
1377 char *buf = tor_malloc(17000);
1378 tor_mmap_t *mapping = NULL;
1380 crypto_rand(buf, buflen);
1382 mapping = tor_mmap_file(fname1);
1383 test_assert(! mapping);
1385 write_str_to_file(fname1, "Short file.", 1);
1387 mapping = tor_mmap_file(fname1);
1388 test_assert(mapping);
1389 test_eq(mapping->size, strlen("Short file."));
1390 test_streq(mapping->data, "Short file.");
1391 #ifdef _WIN32
1392 tor_munmap_file(mapping);
1393 mapping = NULL;
1394 test_assert(unlink(fname1) == 0);
1395 #else
1396 /* make sure we can unlink. */
1397 test_assert(unlink(fname1) == 0);
1398 test_streq(mapping->data, "Short file.");
1399 tor_munmap_file(mapping);
1400 mapping = NULL;
1401 #endif
1403 /* Now a zero-length file. */
1404 write_str_to_file(fname1, "", 1);
1405 mapping = tor_mmap_file(fname1);
1406 test_eq(mapping, NULL);
1407 test_eq(ERANGE, errno);
1408 unlink(fname1);
1410 /* Make sure that we fail to map a no-longer-existent file. */
1411 mapping = tor_mmap_file(fname1);
1412 test_assert(! mapping);
1414 /* Now try a big file that stretches across a few pages and isn't aligned */
1415 write_bytes_to_file(fname2, buf, buflen, 1);
1416 mapping = tor_mmap_file(fname2);
1417 test_assert(mapping);
1418 test_eq(mapping->size, buflen);
1419 test_memeq(mapping->data, buf, buflen);
1420 tor_munmap_file(mapping);
1421 mapping = NULL;
1423 /* Now try a big aligned file. */
1424 write_bytes_to_file(fname3, buf, 16384, 1);
1425 mapping = tor_mmap_file(fname3);
1426 test_assert(mapping);
1427 test_eq(mapping->size, 16384);
1428 test_memeq(mapping->data, buf, 16384);
1429 tor_munmap_file(mapping);
1430 mapping = NULL;
1432 done:
1433 unlink(fname1);
1434 unlink(fname2);
1435 unlink(fname3);
1437 tor_free(fname1);
1438 tor_free(fname2);
1439 tor_free(fname3);
1440 tor_free(buf);
1442 if (mapping)
1443 tor_munmap_file(mapping);
1446 /** Run unit tests for escaping/unescaping data for use by controllers. */
1447 static void
1448 test_util_control_formats(void)
1450 char *out = NULL;
1451 const char *inp =
1452 "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
1453 size_t sz;
1455 sz = read_escaped_data(inp, strlen(inp), &out);
1456 test_streq(out,
1457 ".This is a test\nof the emergency \n.system.\n\rZ.\n");
1458 test_eq(sz, strlen(out));
1460 done:
1461 tor_free(out);
1464 static void
1465 test_util_sscanf(void)
1467 unsigned u1, u2, u3;
1468 char s1[20], s2[10], s3[10], ch;
1469 int r;
1471 /* Simple tests (malformed patterns, literal matching, ...) */
1472 test_eq(-1, tor_sscanf("123", "%i", &r)); /* %i is not supported */
1473 test_eq(-1, tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
1474 test_eq(-1, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
1475 test_eq(-1, tor_sscanf("prettylongstring", "%999999s", s1));
1476 #if 0
1477 /* GCC thinks these two are illegal. */
1478 test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
1479 test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
1480 #endif
1481 /* No '%'-strings: always "success" */
1482 test_eq(0, tor_sscanf("hello world", "hello world"));
1483 test_eq(0, tor_sscanf("hello world", "good bye"));
1484 /* Excess data */
1485 test_eq(0, tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
1486 test_eq(0, tor_sscanf(" 3 hello", "%u", &u1));
1487 test_eq(0, tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
1488 test_eq(1, tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
1490 /* Numbers (ie. %u) */
1491 test_eq(0, tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
1492 test_eq(1, tor_sscanf("12345", "%u", &u1));
1493 test_eq(12345u, u1);
1494 test_eq(1, tor_sscanf("12346 ", "%u", &u1));
1495 test_eq(12346u, u1);
1496 test_eq(0, tor_sscanf(" 12347", "%u", &u1));
1497 test_eq(1, tor_sscanf(" 12348", " %u", &u1));
1498 test_eq(12348u, u1);
1499 test_eq(1, tor_sscanf("0", "%u", &u1));
1500 test_eq(0u, u1);
1501 test_eq(1, tor_sscanf("0000", "%u", &u2));
1502 test_eq(0u, u2);
1503 test_eq(0, tor_sscanf("", "%u", &u1)); /* absent number */
1504 test_eq(0, tor_sscanf("A", "%u", &u1)); /* bogus number */
1505 test_eq(0, tor_sscanf("-1", "%u", &u1)); /* negative number */
1506 test_eq(1, tor_sscanf("4294967295", "%u", &u1)); /* UINT32_MAX should work */
1507 test_eq(4294967295u, u1);
1508 test_eq(0, tor_sscanf("4294967296", "%u", &u1)); /* But not at 32 bits */
1509 test_eq(1, tor_sscanf("4294967296", "%9u", &u1)); /* but parsing only 9... */
1510 test_eq(429496729u, u1);
1512 /* Numbers with size (eg. %2u) */
1513 test_eq(0, tor_sscanf("-1", "%2u", &u1));
1514 test_eq(2, tor_sscanf("123456", "%2u%u", &u1, &u2));
1515 test_eq(12u, u1);
1516 test_eq(3456u, u2);
1517 test_eq(1, tor_sscanf("123456", "%8u", &u1));
1518 test_eq(123456u, u1);
1519 test_eq(1, tor_sscanf("123457 ", "%8u", &u1));
1520 test_eq(123457u, u1);
1521 test_eq(0, tor_sscanf(" 123456", "%8u", &u1));
1522 test_eq(3, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
1523 test_eq(12u, u1);
1524 test_eq(3u, u2);
1525 test_eq(456u, u3);
1526 test_eq(3, tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
1527 test_eq(67u, u1);
1528 test_eq(8u, u2);
1529 test_eq(99u, u3);
1530 /* %u does not match space.*/
1531 test_eq(2, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
1532 test_eq(12u, u1);
1533 test_eq(3u, u2);
1534 /* %u does not match negative numbers. */
1535 test_eq(2, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
1536 test_eq(67u, u1);
1537 test_eq(8u, u2);
1538 /* Arbitrary amounts of 0-padding are okay */
1539 test_eq(3, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
1540 &u1, &u2, &u3));
1541 test_eq(12u, u1);
1542 test_eq(3u, u2);
1543 test_eq(99u, u3);
1545 /* Hex (ie. %x) */
1546 test_eq(3, tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
1547 test_eq(0x1234, u1);
1548 test_eq(0x2ABCDEF, u2);
1549 test_eq(0xFF, u3);
1550 /* Width works on %x */
1551 test_eq(3, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
1552 test_eq(0xf00d, u1);
1553 test_eq(0xcafe, u2);
1554 test_eq(444, u3);
1556 /* Literal '%' (ie. '%%') */
1557 test_eq(1, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
1558 test_eq(99, u1);
1559 test_eq(0, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
1560 test_eq(1, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
1561 test_eq(2, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
1562 test_eq(99, u1);
1563 test_streq(s1, "fresh");
1564 test_eq(1, tor_sscanf("% boo", "%% %3s", s1));
1565 test_streq("boo", s1);
1567 /* Strings (ie. %s) */
1568 test_eq(2, tor_sscanf("hello", "%3s%7s", s1, s2));
1569 test_streq(s1, "hel");
1570 test_streq(s2, "lo");
1571 test_eq(2, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
1572 test_streq(s3, "WD");
1573 test_eq(40, u1);
1574 test_eq(2, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
1575 test_streq(s3, "WD4");
1576 test_eq(0, u1);
1577 test_eq(2, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
1578 test_eq(76, u1);
1579 test_streq(s1, "trombones");
1580 test_eq(1, tor_sscanf("prettylongstring", "%999s", s1));
1581 test_streq(s1, "prettylongstring");
1582 /* %s doesn't eat spaces */
1583 test_eq(2, tor_sscanf("hello world", "%9s %9s", s1, s2));
1584 test_streq(s1, "hello");
1585 test_streq(s2, "world");
1586 test_eq(2, tor_sscanf("bye world?", "%9s %9s", s1, s2));
1587 test_streq(s1, "bye");
1588 test_streq(s2, "");
1589 test_eq(3, tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
1590 test_streq(s1, "hi");
1591 test_streq(s2, "");
1592 test_streq(s3, "");
1594 test_eq(3, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
1595 test_eq(4, tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
1596 test_eq(' ', ch);
1598 done:
1602 static void
1603 test_util_path_is_relative(void)
1605 /* OS-independent tests */
1606 test_eq(1, path_is_relative(""));
1607 test_eq(1, path_is_relative("dir"));
1608 test_eq(1, path_is_relative("dir/"));
1609 test_eq(1, path_is_relative("./dir"));
1610 test_eq(1, path_is_relative("../dir"));
1612 test_eq(0, path_is_relative("/"));
1613 test_eq(0, path_is_relative("/dir"));
1614 test_eq(0, path_is_relative("/dir/"));
1616 /* Windows */
1617 #ifdef _WIN32
1618 /* I don't have Windows so I can't test this, hence the "#ifdef
1619 0". These are tests that look useful, so please try to get them
1620 running and uncomment if it all works as it should */
1621 test_eq(1, path_is_relative("dir"));
1622 test_eq(1, path_is_relative("dir\\"));
1623 test_eq(1, path_is_relative("dir\\a:"));
1624 test_eq(1, path_is_relative("dir\\a:\\"));
1625 test_eq(1, path_is_relative("http:\\dir"));
1627 test_eq(0, path_is_relative("\\dir"));
1628 test_eq(0, path_is_relative("a:\\dir"));
1629 test_eq(0, path_is_relative("z:\\dir"));
1630 #endif
1632 done:
1636 /** Run unittests for memory pool allocator */
1637 static void
1638 test_util_mempool(void)
1640 mp_pool_t *pool = NULL;
1641 smartlist_t *allocated = NULL;
1642 int i;
1644 pool = mp_pool_new(1, 100);
1645 test_assert(pool);
1646 test_assert(pool->new_chunk_capacity >= 100);
1647 test_assert(pool->item_alloc_size >= sizeof(void*)+1);
1648 mp_pool_destroy(pool);
1649 pool = NULL;
1651 pool = mp_pool_new(241, 2500);
1652 test_assert(pool);
1653 test_assert(pool->new_chunk_capacity >= 10);
1654 test_assert(pool->item_alloc_size >= sizeof(void*)+241);
1655 test_eq(pool->item_alloc_size & 0x03, 0);
1656 test_assert(pool->new_chunk_capacity < 60);
1658 allocated = smartlist_new();
1659 for (i = 0; i < 20000; ++i) {
1660 if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) {
1661 void *m = mp_pool_get(pool);
1662 memset(m, 0x09, 241);
1663 smartlist_add(allocated, m);
1664 //printf("%d: %p\n", i, m);
1665 //mp_pool_assert_ok(pool);
1666 } else {
1667 int idx = crypto_rand_int(smartlist_len(allocated));
1668 void *m = smartlist_get(allocated, idx);
1669 //printf("%d: free %p\n", i, m);
1670 smartlist_del(allocated, idx);
1671 mp_pool_release(m);
1672 //mp_pool_assert_ok(pool);
1674 if (crypto_rand_int(777)==0)
1675 mp_pool_clean(pool, 1, 1);
1677 if (i % 777)
1678 mp_pool_assert_ok(pool);
1681 done:
1682 if (allocated) {
1683 SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m));
1684 mp_pool_assert_ok(pool);
1685 mp_pool_clean(pool, 0, 0);
1686 mp_pool_assert_ok(pool);
1687 smartlist_free(allocated);
1690 if (pool)
1691 mp_pool_destroy(pool);
1694 /** Run unittests for memory area allocator */
1695 static void
1696 test_util_memarea(void)
1698 memarea_t *area = memarea_new();
1699 char *p1, *p2, *p3, *p1_orig;
1700 void *malloced_ptr = NULL;
1701 int i;
1703 test_assert(area);
1705 p1_orig = p1 = memarea_alloc(area,64);
1706 p2 = memarea_alloc_zero(area,52);
1707 p3 = memarea_alloc(area,11);
1709 test_assert(memarea_owns_ptr(area, p1));
1710 test_assert(memarea_owns_ptr(area, p2));
1711 test_assert(memarea_owns_ptr(area, p3));
1712 /* Make sure we left enough space. */
1713 test_assert(p1+64 <= p2);
1714 test_assert(p2+52 <= p3);
1715 /* Make sure we aligned. */
1716 test_eq(((uintptr_t)p1) % sizeof(void*), 0);
1717 test_eq(((uintptr_t)p2) % sizeof(void*), 0);
1718 test_eq(((uintptr_t)p3) % sizeof(void*), 0);
1719 test_assert(!memarea_owns_ptr(area, p3+8192));
1720 test_assert(!memarea_owns_ptr(area, p3+30));
1721 test_assert(tor_mem_is_zero(p2, 52));
1722 /* Make sure we don't overalign. */
1723 p1 = memarea_alloc(area, 1);
1724 p2 = memarea_alloc(area, 1);
1725 test_eq(p1+sizeof(void*), p2);
1727 malloced_ptr = tor_malloc(64);
1728 test_assert(!memarea_owns_ptr(area, malloced_ptr));
1729 tor_free(malloced_ptr);
1732 /* memarea_memdup */
1734 malloced_ptr = tor_malloc(64);
1735 crypto_rand((char*)malloced_ptr, 64);
1736 p1 = memarea_memdup(area, malloced_ptr, 64);
1737 test_assert(p1 != malloced_ptr);
1738 test_memeq(p1, malloced_ptr, 64);
1739 tor_free(malloced_ptr);
1742 /* memarea_strdup. */
1743 p1 = memarea_strdup(area,"");
1744 p2 = memarea_strdup(area, "abcd");
1745 test_assert(p1);
1746 test_assert(p2);
1747 test_streq(p1, "");
1748 test_streq(p2, "abcd");
1750 /* memarea_strndup. */
1752 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
1753 /* (From Turandot, act 3.) */
1754 size_t len = strlen(s);
1755 p1 = memarea_strndup(area, s, 1000);
1756 p2 = memarea_strndup(area, s, 10);
1757 test_streq(p1, s);
1758 test_assert(p2 >= p1 + len + 1);
1759 test_memeq(s, p2, 10);
1760 test_eq(p2[10], '\0');
1761 p3 = memarea_strndup(area, s, len);
1762 test_streq(p3, s);
1763 p3 = memarea_strndup(area, s, len-1);
1764 test_memeq(s, p3, len-1);
1765 test_eq(p3[len-1], '\0');
1768 memarea_clear(area);
1769 p1 = memarea_alloc(area, 1);
1770 test_eq(p1, p1_orig);
1771 memarea_clear(area);
1773 /* Check for running over an area's size. */
1774 for (i = 0; i < 512; ++i) {
1775 p1 = memarea_alloc(area, crypto_rand_int(5)+1);
1776 test_assert(memarea_owns_ptr(area, p1));
1778 memarea_assert_ok(area);
1779 /* Make sure we can allocate a too-big object. */
1780 p1 = memarea_alloc_zero(area, 9000);
1781 p2 = memarea_alloc_zero(area, 16);
1782 test_assert(memarea_owns_ptr(area, p1));
1783 test_assert(memarea_owns_ptr(area, p2));
1785 done:
1786 memarea_drop_all(area);
1787 tor_free(malloced_ptr);
1790 /** Run unit tests for utility functions to get file names relative to
1791 * the data directory. */
1792 static void
1793 test_util_datadir(void)
1795 char buf[1024];
1796 char *f = NULL;
1797 char *temp_dir = NULL;
1799 temp_dir = get_datadir_fname(NULL);
1800 f = get_datadir_fname("state");
1801 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
1802 test_streq(f, buf);
1803 tor_free(f);
1804 f = get_datadir_fname2("cache", "thingy");
1805 tor_snprintf(buf, sizeof(buf),
1806 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
1807 test_streq(f, buf);
1808 tor_free(f);
1809 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
1810 tor_snprintf(buf, sizeof(buf),
1811 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
1812 test_streq(f, buf);
1813 tor_free(f);
1814 f = get_datadir_fname_suffix("cache", ".foo");
1815 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
1816 temp_dir);
1817 test_streq(f, buf);
1819 done:
1820 tor_free(f);
1821 tor_free(temp_dir);
1824 static void
1825 test_util_strtok(void)
1827 char buf[128];
1828 char buf2[128];
1829 int i;
1830 char *cp1, *cp2;
1832 for (i = 0; i < 3; i++) {
1833 const char *pad1="", *pad2="";
1834 switch (i) {
1835 case 0:
1836 break;
1837 case 1:
1838 pad1 = " ";
1839 pad2 = "!";
1840 break;
1841 case 2:
1842 pad1 = " ";
1843 pad2 = ";!";
1844 break;
1846 tor_snprintf(buf, sizeof(buf), "%s", pad1);
1847 tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
1848 test_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1));
1849 test_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2));
1851 tor_snprintf(buf, sizeof(buf),
1852 "%sGraved on the dark in gestures of descent%s", pad1, pad1);
1853 tor_snprintf(buf2, sizeof(buf2),
1854 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
1855 /* -- "Year's End", Richard Wilbur */
1857 test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1));
1858 test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2));
1859 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
1860 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
1861 test_streq("on", S1());
1862 test_streq("the", S1());
1863 test_streq("dark", S1());
1864 test_streq("seemed", S2());
1865 test_streq("their", S2());
1866 test_streq("own", S2());
1867 test_streq("in", S1());
1868 test_streq("gestures", S1());
1869 test_streq("of", S1());
1870 test_streq("most", S2());
1871 test_streq("perfect", S2());
1872 test_streq("descent", S1());
1873 test_streq("monument", S2());
1874 test_eq_ptr(NULL, S1());
1875 test_eq_ptr(NULL, S2());
1878 buf[0] = 0;
1879 test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
1880 test_eq_ptr(NULL, tor_strtok_r_impl(buf, "!", &cp1));
1882 strlcpy(buf, "Howdy!", sizeof(buf));
1883 test_streq("Howdy", tor_strtok_r_impl(buf, "!", &cp1));
1884 test_eq_ptr(NULL, tor_strtok_r_impl(NULL, "!", &cp1));
1886 strlcpy(buf, " ", sizeof(buf));
1887 test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
1888 strlcpy(buf, " ", sizeof(buf));
1889 test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
1891 strlcpy(buf, "something ", sizeof(buf));
1892 test_streq("something", tor_strtok_r_impl(buf, " ", &cp1));
1893 test_eq_ptr(NULL, tor_strtok_r_impl(NULL, ";", &cp1));
1894 done:
1898 static void
1899 test_util_find_str_at_start_of_line(void *ptr)
1901 const char *long_string =
1902 "howdy world. how are you? i hope it's fine.\n"
1903 "hello kitty\n"
1904 "third line";
1905 char *line2 = strchr(long_string,'\n')+1;
1906 char *line3 = strchr(line2,'\n')+1;
1907 const char *short_string = "hello kitty\n"
1908 "second line\n";
1909 char *short_line2 = strchr(short_string,'\n')+1;
1911 (void)ptr;
1913 test_eq_ptr(long_string, find_str_at_start_of_line(long_string, ""));
1914 test_eq_ptr(NULL, find_str_at_start_of_line(short_string, "nonsense"));
1915 test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "nonsense"));
1916 test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "\n"));
1917 test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "how "));
1918 test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "kitty"));
1919 test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "h"));
1920 test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "how"));
1921 test_eq_ptr(line2, find_str_at_start_of_line(long_string, "he"));
1922 test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hell"));
1923 test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello k"));
1924 test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\n"));
1925 test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\nt"));
1926 test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third"));
1927 test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third line"));
1928 test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "third line\n"));
1929 test_eq_ptr(short_line2, find_str_at_start_of_line(short_string,
1930 "second line\n"));
1931 done:
1935 static void
1936 test_util_string_is_C_identifier(void *ptr)
1938 (void)ptr;
1940 test_eq(1, string_is_C_identifier("string_is_C_identifier"));
1941 test_eq(1, string_is_C_identifier("_string_is_C_identifier"));
1942 test_eq(1, string_is_C_identifier("_"));
1943 test_eq(1, string_is_C_identifier("i"));
1944 test_eq(1, string_is_C_identifier("_____"));
1945 test_eq(1, string_is_C_identifier("__00__"));
1946 test_eq(1, string_is_C_identifier("__init__"));
1947 test_eq(1, string_is_C_identifier("_0"));
1948 test_eq(1, string_is_C_identifier("_0string_is_C_identifier"));
1949 test_eq(1, string_is_C_identifier("_0"));
1951 test_eq(0, string_is_C_identifier("0_string_is_C_identifier"));
1952 test_eq(0, string_is_C_identifier("0"));
1953 test_eq(0, string_is_C_identifier(""));
1954 test_eq(0, string_is_C_identifier(";"));
1955 test_eq(0, string_is_C_identifier("i;"));
1956 test_eq(0, string_is_C_identifier("_;"));
1957 test_eq(0, string_is_C_identifier("í"));
1958 test_eq(0, string_is_C_identifier("ñ"));
1960 done:
1964 static void
1965 test_util_asprintf(void *ptr)
1967 #define LOREMIPSUM \
1968 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
1969 char *cp=NULL, *cp2=NULL;
1970 int r;
1971 (void)ptr;
1973 /* simple string */
1974 r = tor_asprintf(&cp, "simple string 100%% safe");
1975 test_assert(cp);
1976 test_streq("simple string 100% safe", cp);
1977 test_eq(strlen(cp), r);
1979 /* empty string */
1980 r = tor_asprintf(&cp, "%s", "");
1981 test_assert(cp);
1982 test_streq("", cp);
1983 test_eq(strlen(cp), r);
1985 /* numbers (%i) */
1986 r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
1987 test_assert(cp);
1988 test_streq("I like numbers--1, 2, etc.", cp);
1989 test_eq(strlen(cp), r);
1991 /* numbers (%d) */
1992 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
1993 test_assert(cp2);
1994 test_eq(strlen(cp2), r);
1995 test_streq("First=101, Second=202", cp2);
1996 test_assert(cp != cp2);
1997 tor_free(cp);
1998 tor_free(cp2);
2000 /* Glass-box test: a string exactly 128 characters long. */
2001 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
2002 test_assert(cp);
2003 test_eq(128, r);
2004 test_assert(cp[128] == '\0');
2005 test_streq("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM, cp);
2006 tor_free(cp);
2008 /* String longer than 128 characters */
2009 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
2010 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
2011 test_assert(cp);
2012 test_eq(strlen(cp), r);
2013 test_streq("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM, cp);
2015 done:
2016 tor_free(cp);
2017 tor_free(cp2);
2020 static void
2021 test_util_listdir(void *ptr)
2023 smartlist_t *dir_contents = NULL;
2024 char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
2025 int r;
2026 (void)ptr;
2028 fname1 = tor_strdup(get_fname("hopscotch"));
2029 fname2 = tor_strdup(get_fname("mumblety-peg"));
2030 fname3 = tor_strdup(get_fname(".hidden-file"));
2031 dir1 = tor_strdup(get_fname("some-directory"));
2032 dirname = tor_strdup(get_fname(NULL));
2034 test_eq(0, write_str_to_file(fname1, "X\n", 0));
2035 test_eq(0, write_str_to_file(fname2, "Y\n", 0));
2036 test_eq(0, write_str_to_file(fname3, "Z\n", 0));
2037 #ifdef _WIN32
2038 r = mkdir(dir1);
2039 #else
2040 r = mkdir(dir1, 0700);
2041 #endif
2042 if (r) {
2043 fprintf(stderr, "Can't create directory %s:", dir1);
2044 perror("");
2045 exit(1);
2048 dir_contents = tor_listdir(dirname);
2049 test_assert(dir_contents);
2050 /* make sure that each filename is listed. */
2051 test_assert(smartlist_string_isin_case(dir_contents, "hopscotch"));
2052 test_assert(smartlist_string_isin_case(dir_contents, "mumblety-peg"));
2053 test_assert(smartlist_string_isin_case(dir_contents, ".hidden-file"));
2054 test_assert(smartlist_string_isin_case(dir_contents, "some-directory"));
2056 test_assert(!smartlist_string_isin(dir_contents, "."));
2057 test_assert(!smartlist_string_isin(dir_contents, ".."));
2059 done:
2060 tor_free(fname1);
2061 tor_free(fname2);
2062 tor_free(dirname);
2063 if (dir_contents) {
2064 SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
2065 smartlist_free(dir_contents);
2069 static void
2070 test_util_parent_dir(void *ptr)
2072 char *cp;
2073 (void)ptr;
2075 #define T(output,expect_ok,input) \
2076 do { \
2077 int ok; \
2078 cp = tor_strdup(input); \
2079 ok = get_parent_directory(cp); \
2080 tt_int_op(expect_ok, ==, ok); \
2081 if (ok==0) \
2082 tt_str_op(output, ==, cp); \
2083 tor_free(cp); \
2084 } while (0);
2086 T("/home/wombat", 0, "/home/wombat/knish");
2087 T("/home/wombat", 0, "/home/wombat/knish/");
2088 T("/home/wombat", 0, "/home/wombat/knish///");
2089 T("./home/wombat", 0, "./home/wombat/knish/");
2090 T("/", 0, "/home");
2091 T("/", 0, "/home//");
2092 T(".", 0, "./wombat");
2093 T(".", 0, "./wombat/");
2094 T(".", 0, "./wombat//");
2095 T("wombat", 0, "wombat/foo");
2096 T("wombat/..", 0, "wombat/../foo");
2097 T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
2098 T("wombat/.", 0, "wombat/./foo");
2099 T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
2100 T("wombat", 0, "wombat/..//");
2101 T("wombat", 0, "wombat/foo/");
2102 T("wombat", 0, "wombat/.foo");
2103 T("wombat", 0, "wombat/.foo/");
2105 T("wombat", -1, "");
2106 T("w", -1, "");
2107 T("wombat", 0, "wombat/knish");
2109 T("/", 0, "/");
2110 T("/", 0, "////");
2112 done:
2113 tor_free(cp);
2116 #ifdef _WIN32
2117 static void
2118 test_util_load_win_lib(void *ptr)
2120 HANDLE h = load_windows_system_library(_T("advapi32.dll"));
2121 (void) ptr;
2123 tt_assert(h);
2124 done:
2125 if (h)
2126 CloseHandle(h);
2128 #endif
2130 static void
2131 clear_hex_errno(char *hex_errno)
2133 memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
2136 static void
2137 test_util_exit_status(void *ptr)
2139 /* Leave an extra byte for a \0 so we can do string comparison */
2140 char hex_errno[HEX_ERRNO_SIZE + 1];
2141 int n;
2143 (void)ptr;
2145 clear_hex_errno(hex_errno);
2146 n = format_helper_exit_status(0, 0, hex_errno);
2147 test_streq("0/0\n", hex_errno);
2148 test_eq(n, strlen(hex_errno));
2150 clear_hex_errno(hex_errno);
2151 n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
2152 test_streq("0/7FFFFFFF\n", hex_errno);
2153 test_eq(n, strlen(hex_errno));
2155 clear_hex_errno(hex_errno);
2156 n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
2157 test_streq("FF/-80000000\n", hex_errno);
2158 test_eq(n, strlen(hex_errno));
2160 clear_hex_errno(hex_errno);
2161 n = format_helper_exit_status(0x7F, 0, hex_errno);
2162 test_streq("7F/0\n", hex_errno);
2163 test_eq(n, strlen(hex_errno));
2165 clear_hex_errno(hex_errno);
2166 n = format_helper_exit_status(0x08, -0x242, hex_errno);
2167 test_streq("8/-242\n", hex_errno);
2168 test_eq(n, strlen(hex_errno));
2170 done:
2174 #ifndef _WIN32
2175 /** Check that fgets waits until a full line, and not return a partial line, on
2176 * a EAGAIN with a non-blocking pipe */
2177 static void
2178 test_util_fgets_eagain(void *ptr)
2180 int test_pipe[2] = {-1, -1};
2181 int retval;
2182 ssize_t retlen;
2183 char *retptr;
2184 FILE *test_stream = NULL;
2185 char buf[10];
2187 (void)ptr;
2189 /* Set up a pipe to test on */
2190 retval = pipe(test_pipe);
2191 tt_int_op(retval, >=, 0);
2193 /* Set up the read-end to be non-blocking */
2194 retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
2195 tt_int_op(retval, >=, 0);
2197 /* Open it as a stdio stream */
2198 test_stream = fdopen(test_pipe[0], "r");
2199 tt_ptr_op(test_stream, !=, NULL);
2201 /* Send in a partial line */
2202 retlen = write(test_pipe[1], "A", 1);
2203 tt_int_op(retlen, ==, 1);
2204 retptr = fgets(buf, sizeof(buf), test_stream);
2205 tt_want(retptr == NULL);
2206 tt_int_op(errno, ==, EAGAIN);
2208 /* Send in the rest */
2209 retlen = write(test_pipe[1], "B\n", 2);
2210 tt_int_op(retlen, ==, 2);
2211 retptr = fgets(buf, sizeof(buf), test_stream);
2212 tt_ptr_op(retptr, ==, buf);
2213 tt_str_op(buf, ==, "AB\n");
2215 /* Send in a full line */
2216 retlen = write(test_pipe[1], "CD\n", 3);
2217 tt_int_op(retlen, ==, 3);
2218 retptr = fgets(buf, sizeof(buf), test_stream);
2219 tt_ptr_op(retptr, ==, buf);
2220 tt_str_op(buf, ==, "CD\n");
2222 /* Send in a partial line */
2223 retlen = write(test_pipe[1], "E", 1);
2224 tt_int_op(retlen, ==, 1);
2225 retptr = fgets(buf, sizeof(buf), test_stream);
2226 tt_ptr_op(retptr, ==, NULL);
2227 tt_int_op(errno, ==, EAGAIN);
2229 /* Send in the rest */
2230 retlen = write(test_pipe[1], "F\n", 2);
2231 tt_int_op(retlen, ==, 2);
2232 retptr = fgets(buf, sizeof(buf), test_stream);
2233 tt_ptr_op(retptr, ==, buf);
2234 tt_str_op(buf, ==, "EF\n");
2236 /* Send in a full line and close */
2237 retlen = write(test_pipe[1], "GH", 2);
2238 tt_int_op(retlen, ==, 2);
2239 retval = close(test_pipe[1]);
2240 test_pipe[1] = -1;
2241 tt_int_op(retval, ==, 0);
2242 retptr = fgets(buf, sizeof(buf), test_stream);
2243 tt_ptr_op(retptr, ==, buf);
2244 tt_str_op(buf, ==, "GH");
2246 /* Check for EOF */
2247 retptr = fgets(buf, sizeof(buf), test_stream);
2248 tt_ptr_op(retptr, ==, NULL);
2249 tt_int_op(feof(test_stream), >, 0);
2251 done:
2252 if (test_stream != NULL)
2253 fclose(test_stream);
2254 if (test_pipe[0] != -1)
2255 close(test_pipe[0]);
2256 if (test_pipe[1] != -1)
2257 close(test_pipe[1]);
2259 #endif
2261 /** Helper function for testing tor_spawn_background */
2262 static void
2263 run_util_spawn_background(const char *argv[], const char *expected_out,
2264 const char *expected_err, int expected_exit,
2265 int expected_status)
2267 int retval, exit_code;
2268 ssize_t pos;
2269 process_handle_t *process_handle=NULL;
2270 char stdout_buf[100], stderr_buf[100];
2271 int status;
2273 /* Start the program */
2274 #ifdef _WIN32
2275 status = tor_spawn_background(NULL, argv, NULL, &process_handle);
2276 #else
2277 status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
2278 #endif
2280 test_eq(expected_status, status);
2281 if (status == PROCESS_STATUS_ERROR)
2282 return;
2284 test_assert(process_handle != NULL);
2285 test_eq(expected_status, process_handle->status);
2287 #ifdef _WIN32
2288 test_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE);
2289 test_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE);
2290 #else
2291 test_assert(process_handle->stdout_pipe > 0);
2292 test_assert(process_handle->stderr_pipe > 0);
2293 #endif
2295 /* Check stdout */
2296 pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
2297 sizeof(stdout_buf) - 1);
2298 tt_assert(pos >= 0);
2299 stdout_buf[pos] = '\0';
2300 test_eq(strlen(expected_out), pos);
2301 test_streq(expected_out, stdout_buf);
2303 /* Check it terminated correctly */
2304 retval = tor_get_exit_code(process_handle, 1, &exit_code);
2305 test_eq(PROCESS_EXIT_EXITED, retval);
2306 test_eq(expected_exit, exit_code);
2307 // TODO: Make test-child exit with something other than 0
2309 /* Check stderr */
2310 pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
2311 sizeof(stderr_buf) - 1);
2312 test_assert(pos >= 0);
2313 stderr_buf[pos] = '\0';
2314 test_streq(expected_err, stderr_buf);
2315 test_eq(strlen(expected_err), pos);
2317 done:
2318 if (process_handle)
2319 tor_process_handle_destroy(process_handle, 1);
2322 /** Check that we can launch a process and read the output */
2323 static void
2324 test_util_spawn_background_ok(void *ptr)
2326 #ifdef _WIN32
2327 const char *argv[] = {"test-child.exe", "--test", NULL};
2328 const char *expected_out = "OUT\r\n--test\r\nSLEEPING\r\nDONE\r\n";
2329 const char *expected_err = "ERR\r\n";
2330 #else
2331 const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
2332 const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
2333 const char *expected_err = "ERR\n";
2334 #endif
2336 (void)ptr;
2338 run_util_spawn_background(argv, expected_out, expected_err, 0,
2339 PROCESS_STATUS_RUNNING);
2342 /** Check that failing to find the executable works as expected */
2343 static void
2344 test_util_spawn_background_fail(void *ptr)
2346 #ifndef BUILDDIR
2347 #define BUILDDIR "."
2348 #endif
2349 const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
2350 const char *expected_err = "";
2351 char expected_out[1024];
2352 char code[32];
2353 #ifdef _WIN32
2354 const int expected_status = PROCESS_STATUS_ERROR;
2355 #else
2356 /* TODO: Once we can signal failure to exec, set this to be
2357 * PROCESS_STATUS_ERROR */
2358 const int expected_status = PROCESS_STATUS_RUNNING;
2359 #endif
2361 (void)ptr;
2363 tor_snprintf(code, sizeof(code), "%x/%x",
2364 9 /* CHILD_STATE_FAILEXEC */ , ENOENT);
2365 tor_snprintf(expected_out, sizeof(expected_out),
2366 "ERR: Failed to spawn background process - code %s\n", code);
2368 run_util_spawn_background(argv, expected_out, expected_err, 255,
2369 expected_status);
2372 /** Test that reading from a handle returns a partial read rather than
2373 * blocking */
2374 static void
2375 test_util_spawn_background_partial_read(void *ptr)
2377 const int expected_exit = 0;
2378 const int expected_status = PROCESS_STATUS_RUNNING;
2380 int retval, exit_code;
2381 ssize_t pos = -1;
2382 process_handle_t *process_handle=NULL;
2383 int status;
2384 char stdout_buf[100], stderr_buf[100];
2385 #ifdef _WIN32
2386 const char *argv[] = {"test-child.exe", "--test", NULL};
2387 const char *expected_out[] = { "OUT\r\n--test\r\nSLEEPING\r\n",
2388 "DONE\r\n",
2389 NULL };
2390 const char *expected_err = "ERR\r\n";
2391 #else
2392 const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
2393 const char *expected_out[] = { "OUT\n--test\nSLEEPING\n",
2394 "DONE\n",
2395 NULL };
2396 const char *expected_err = "ERR\n";
2397 int eof = 0;
2398 #endif
2399 int expected_out_ctr;
2400 (void)ptr;
2402 /* Start the program */
2403 #ifdef _WIN32
2404 status = tor_spawn_background(NULL, argv, NULL, &process_handle);
2405 #else
2406 status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
2407 #endif
2408 test_eq(expected_status, status);
2409 test_assert(process_handle);
2410 test_eq(expected_status, process_handle->status);
2412 /* Check stdout */
2413 for (expected_out_ctr = 0; expected_out[expected_out_ctr] != NULL;) {
2414 #ifdef _WIN32
2415 pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
2416 sizeof(stdout_buf) - 1, NULL);
2417 #else
2418 /* Check that we didn't read the end of file last time */
2419 test_assert(!eof);
2420 pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
2421 sizeof(stdout_buf) - 1, NULL, &eof);
2422 #endif
2423 log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
2425 /* We would have blocked, keep on trying */
2426 if (0 == pos)
2427 continue;
2429 test_assert(pos > 0);
2430 stdout_buf[pos] = '\0';
2431 test_streq(expected_out[expected_out_ctr], stdout_buf);
2432 test_eq(strlen(expected_out[expected_out_ctr]), pos);
2433 expected_out_ctr++;
2436 /* The process should have exited without writing more */
2437 #ifdef _WIN32
2438 pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
2439 sizeof(stdout_buf) - 1,
2440 process_handle);
2441 test_eq(0, pos);
2442 #else
2443 if (!eof) {
2444 /* We should have got all the data, but maybe not the EOF flag */
2445 pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
2446 sizeof(stdout_buf) - 1,
2447 process_handle, &eof);
2448 test_eq(0, pos);
2449 test_assert(eof);
2451 /* Otherwise, we got the EOF on the last read */
2452 #endif
2454 /* Check it terminated correctly */
2455 retval = tor_get_exit_code(process_handle, 1, &exit_code);
2456 test_eq(PROCESS_EXIT_EXITED, retval);
2457 test_eq(expected_exit, exit_code);
2459 // TODO: Make test-child exit with something other than 0
2461 /* Check stderr */
2462 pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
2463 sizeof(stderr_buf) - 1);
2464 test_assert(pos >= 0);
2465 stderr_buf[pos] = '\0';
2466 test_streq(expected_err, stderr_buf);
2467 test_eq(strlen(expected_err), pos);
2469 done:
2470 tor_process_handle_destroy(process_handle, 1);
2474 * Test for format_hex_number_for_helper_exit_status()
2477 static void
2478 test_util_format_hex_number(void *ptr)
2480 int i, len;
2481 char buf[HEX_ERRNO_SIZE + 1];
2482 const struct {
2483 const char *str;
2484 unsigned int x;
2485 } test_data[] = {
2486 {"0", 0},
2487 {"1", 1},
2488 {"273A", 0x273a},
2489 {"FFFF", 0xffff},
2490 #if UINT_MAX >= 0xffffffff
2491 {"31BC421D", 0x31bc421d},
2492 {"FFFFFFFF", 0xffffffff},
2493 #endif
2494 {NULL, 0}
2497 (void)ptr;
2499 for (i = 0; test_data[i].str != NULL; ++i) {
2500 len = format_hex_number_for_helper_exit_status(test_data[i].x,
2501 buf, HEX_ERRNO_SIZE);
2502 test_neq(len, 0);
2503 buf[len] = '\0';
2504 test_streq(buf, test_data[i].str);
2507 done:
2508 return;
2512 * Test that we can properly format q Windows command line
2514 static void
2515 test_util_join_win_cmdline(void *ptr)
2517 /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
2518 * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
2519 * will try to only generate simple cases for the child process to parse;
2520 * i.e. we never embed quoted strings in arguments. */
2522 const char *argvs[][4] = {
2523 {"a", "bb", "CCC", NULL}, // Normal
2524 {NULL, NULL, NULL, NULL}, // Empty argument list
2525 {"", NULL, NULL, NULL}, // Empty argument
2526 {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
2527 {"a\tbc", "dd dd", "E", NULL}, // Whitespace
2528 {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
2529 {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
2530 {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
2531 { NULL } // Terminator
2534 const char *cmdlines[] = {
2535 "a bb CCC",
2537 "\"\"",
2538 "\\\"a b\\\"b CCC\\\"",
2539 "\"a\tbc\" \"dd dd\" E",
2540 "a\\\\\\b \"de fg\" H",
2541 "a\\\\\\\"b \\c D\\",
2542 "\"a\\\\b c\" d E",
2543 NULL // Terminator
2546 int i;
2547 char *joined_argv;
2549 (void)ptr;
2551 for (i=0; cmdlines[i]!=NULL; i++) {
2552 log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
2553 joined_argv = tor_join_win_cmdline(argvs[i]);
2554 test_streq(cmdlines[i], joined_argv);
2555 tor_free(joined_argv);
2558 done:
2562 #define MAX_SPLIT_LINE_COUNT 4
2563 struct split_lines_test_t {
2564 const char *orig_line; // Line to be split (may contain \0's)
2565 int orig_length; // Length of orig_line
2566 const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
2570 * Test that we properly split a buffer into lines
2572 static void
2573 test_util_split_lines(void *ptr)
2575 /* Test cases. orig_line of last test case must be NULL.
2576 * The last element of split_line[i] must be NULL. */
2577 struct split_lines_test_t tests[] = {
2578 {"", 0, {NULL}},
2579 {"foo", 3, {"foo", NULL}},
2580 {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
2581 {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
2582 {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
2583 {"line 1\r\nline 2", 14, {"line 1", "line 2", NULL}},
2584 {"line 1\r\n\r\nline 2", 16, {"line 1", "line 2", NULL}},
2585 {"line 1\r\n\r\r\r\nline 2", 18, {"line 1", "line 2", NULL}},
2586 {"line 1\r\n\n\n\n\rline 2", 18, {"line 1", "line 2", NULL}},
2587 {"line 1\r\n\r\t\r\nline 3", 18, {"line 1", ".", "line 3", NULL}},
2588 {"\n\t\r\t\nline 3", 11, {".", ".", "line 3", NULL}},
2589 {NULL, 0, { NULL }}
2592 int i, j;
2593 char *orig_line=NULL;
2594 smartlist_t *sl=NULL;
2596 (void)ptr;
2598 for (i=0; tests[i].orig_line; i++) {
2599 sl = smartlist_new();
2600 /* Allocate space for string and trailing NULL */
2601 orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
2602 tor_split_lines(sl, orig_line, tests[i].orig_length);
2604 j = 0;
2605 log_info(LD_GENERAL, "Splitting test %d of length %d",
2606 i, tests[i].orig_length);
2607 SMARTLIST_FOREACH_BEGIN(sl, const char *, line) {
2608 /* Check we have not got too many lines */
2609 test_assert(j < MAX_SPLIT_LINE_COUNT);
2610 /* Check that there actually should be a line here */
2611 test_assert(tests[i].split_line[j] != NULL);
2612 log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
2613 j, i, tests[i].split_line[j]);
2614 /* Check that the line is as expected */
2615 test_streq(line, tests[i].split_line[j]);
2616 j++;
2617 } SMARTLIST_FOREACH_END(line);
2618 /* Check that we didn't miss some lines */
2619 test_eq_ptr(NULL, tests[i].split_line[j]);
2620 tor_free(orig_line);
2621 smartlist_free(sl);
2622 sl = NULL;
2625 done:
2626 tor_free(orig_line);
2627 smartlist_free(sl);
2630 static void
2631 test_util_di_ops(void)
2633 #define LT -1
2634 #define GT 1
2635 #define EQ 0
2636 const struct {
2637 const char *a; int want_sign; const char *b;
2638 } examples[] = {
2639 { "Foo", EQ, "Foo" },
2640 { "foo", GT, "bar", },
2641 { "foobar", EQ ,"foobar" },
2642 { "foobar", LT, "foobaw" },
2643 { "foobar", GT, "f00bar" },
2644 { "foobar", GT, "boobar" },
2645 { "", EQ, "" },
2646 { NULL, 0, NULL },
2649 int i;
2651 for (i = 0; examples[i].a; ++i) {
2652 size_t len = strlen(examples[i].a);
2653 int eq1, eq2, neq1, neq2, cmp1, cmp2;
2654 test_eq(len, strlen(examples[i].b));
2655 /* We do all of the operations, with operands in both orders. */
2656 eq1 = tor_memeq(examples[i].a, examples[i].b, len);
2657 eq2 = tor_memeq(examples[i].b, examples[i].a, len);
2658 neq1 = tor_memneq(examples[i].a, examples[i].b, len);
2659 neq2 = tor_memneq(examples[i].b, examples[i].a, len);
2660 cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
2661 cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
2663 /* Check for correctness of cmp1 */
2664 if (cmp1 < 0 && examples[i].want_sign != LT)
2665 test_fail();
2666 else if (cmp1 > 0 && examples[i].want_sign != GT)
2667 test_fail();
2668 else if (cmp1 == 0 && examples[i].want_sign != EQ)
2669 test_fail();
2671 /* Check for consistency of everything else with cmp1 */
2672 test_eq(eq1, eq2);
2673 test_eq(neq1, neq2);
2674 test_eq(cmp1, -cmp2);
2675 test_eq(eq1, cmp1 == 0);
2676 test_eq(neq1, !eq1);
2679 done:
2684 * Test counting high bits
2686 static void
2687 test_util_n_bits_set(void *ptr)
2689 (void)ptr;
2690 test_eq(0, n_bits_set_u8(0));
2691 test_eq(1, n_bits_set_u8(1));
2692 test_eq(3, n_bits_set_u8(7));
2693 test_eq(1, n_bits_set_u8(8));
2694 test_eq(2, n_bits_set_u8(129));
2695 test_eq(8, n_bits_set_u8(255));
2696 done:
2701 * Test LHS whitespace (and comment) eater
2703 static void
2704 test_util_eat_whitespace(void *ptr)
2706 const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
2707 char str[80];
2708 size_t i;
2710 (void)ptr;
2712 /* Try one leading ws */
2713 strcpy(str, "fuubaar");
2714 for (i = 0; i < sizeof(ws); ++i) {
2715 str[0] = ws[i];
2716 test_eq_ptr(str + 1, eat_whitespace(str));
2717 test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str)));
2718 test_eq_ptr(str + 1, eat_whitespace_no_nl(str));
2719 test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str)));
2721 str[0] = '\n';
2722 test_eq_ptr(str + 1, eat_whitespace(str));
2723 test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str)));
2724 test_eq_ptr(str, eat_whitespace_no_nl(str));
2725 test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
2727 /* Empty string */
2728 strcpy(str, "");
2729 test_eq_ptr(str, eat_whitespace(str));
2730 test_eq_ptr(str, eat_whitespace_eos(str, str));
2731 test_eq_ptr(str, eat_whitespace_no_nl(str));
2732 test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str));
2734 /* Only ws */
2735 strcpy(str, " \t\r\n");
2736 test_eq_ptr(str + strlen(str), eat_whitespace(str));
2737 test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
2738 test_eq_ptr(str + strlen(str) - 1,
2739 eat_whitespace_no_nl(str));
2740 test_eq_ptr(str + strlen(str) - 1,
2741 eat_whitespace_eos_no_nl(str, str + strlen(str)));
2743 strcpy(str, " \t\r ");
2744 test_eq_ptr(str + strlen(str), eat_whitespace(str));
2745 test_eq_ptr(str + strlen(str),
2746 eat_whitespace_eos(str, str + strlen(str)));
2747 test_eq_ptr(str + strlen(str), eat_whitespace_no_nl(str));
2748 test_eq_ptr(str + strlen(str),
2749 eat_whitespace_eos_no_nl(str, str + strlen(str)));
2751 /* Multiple ws */
2752 strcpy(str, "fuubaar");
2753 for (i = 0; i < sizeof(ws); ++i)
2754 str[i] = ws[i];
2755 test_eq_ptr(str + sizeof(ws), eat_whitespace(str));
2756 test_eq_ptr(str + sizeof(ws), eat_whitespace_eos(str, str + strlen(str)));
2757 test_eq_ptr(str + sizeof(ws), eat_whitespace_no_nl(str));
2758 test_eq_ptr(str + sizeof(ws),
2759 eat_whitespace_eos_no_nl(str, str + strlen(str)));
2761 /* Eat comment */
2762 strcpy(str, "# Comment \n No Comment");
2763 test_streq("No Comment", eat_whitespace(str));
2764 test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str)));
2765 test_eq_ptr(str, eat_whitespace_no_nl(str));
2766 test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
2768 /* Eat comment & ws mix */
2769 strcpy(str, " # \t Comment \n\t\nNo Comment");
2770 test_streq("No Comment", eat_whitespace(str));
2771 test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str)));
2772 test_eq_ptr(str + 1, eat_whitespace_no_nl(str));
2773 test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str)));
2775 /* Eat entire comment */
2776 strcpy(str, "#Comment");
2777 test_eq_ptr(str + strlen(str), eat_whitespace(str));
2778 test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
2779 test_eq_ptr(str, eat_whitespace_no_nl(str));
2780 test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
2782 /* Blank line, then comment */
2783 strcpy(str, " \t\n # Comment");
2784 test_eq_ptr(str + strlen(str), eat_whitespace(str));
2785 test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
2786 test_eq_ptr(str + 2, eat_whitespace_no_nl(str));
2787 test_eq_ptr(str + 2, eat_whitespace_eos_no_nl(str, str + strlen(str)));
2789 done:
2793 /** Return a newly allocated smartlist containing the lines of text in
2794 * <b>lines</b>. The returned strings are heap-allocated, and must be
2795 * freed by the caller.
2797 * XXXX? Move to container.[hc] ? */
2798 static smartlist_t *
2799 smartlist_new_from_text_lines(const char *lines)
2801 smartlist_t *sl = smartlist_new();
2802 char *last_line;
2804 smartlist_split_string(sl, lines, "\n", 0, 0);
2806 last_line = smartlist_pop_last(sl);
2807 if (last_line != NULL && *last_line != '\0') {
2808 smartlist_add(sl, last_line);
2811 return sl;
2814 /** Test smartlist_new_from_text_lines */
2815 static void
2816 test_util_sl_new_from_text_lines(void *ptr)
2818 (void)ptr;
2820 { /* Normal usage */
2821 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
2822 int sl_len = smartlist_len(sl);
2824 tt_want_int_op(sl_len, ==, 3);
2826 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), ==, "foo");
2827 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), ==, "bar");
2828 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), ==, "baz");
2830 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
2831 smartlist_free(sl);
2834 { /* No final newline */
2835 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
2836 int sl_len = smartlist_len(sl);
2838 tt_want_int_op(sl_len, ==, 3);
2840 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), ==, "foo");
2841 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), ==, "bar");
2842 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), ==, "baz");
2844 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
2845 smartlist_free(sl);
2848 { /* No newlines */
2849 smartlist_t *sl = smartlist_new_from_text_lines("foo");
2850 int sl_len = smartlist_len(sl);
2852 tt_want_int_op(sl_len, ==, 1);
2854 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), ==, "foo");
2856 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
2857 smartlist_free(sl);
2860 { /* No text at all */
2861 smartlist_t *sl = smartlist_new_from_text_lines("");
2862 int sl_len = smartlist_len(sl);
2864 tt_want_int_op(sl_len, ==, 0);
2866 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
2867 smartlist_free(sl);
2871 static void
2872 test_util_envnames(void *ptr)
2874 (void) ptr;
2876 tt_assert(environment_variable_names_equal("abc", "abc"));
2877 tt_assert(environment_variable_names_equal("abc", "abc="));
2878 tt_assert(environment_variable_names_equal("abc", "abc=def"));
2879 tt_assert(environment_variable_names_equal("abc=def", "abc"));
2880 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
2882 tt_assert(environment_variable_names_equal("abc", "abc"));
2883 tt_assert(environment_variable_names_equal("abc", "abc="));
2884 tt_assert(environment_variable_names_equal("abc", "abc=def"));
2885 tt_assert(environment_variable_names_equal("abc=def", "abc"));
2886 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
2888 tt_assert(!environment_variable_names_equal("abc", "abcd"));
2889 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
2890 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
2891 tt_assert(!environment_variable_names_equal("abc=", "def"));
2892 tt_assert(!environment_variable_names_equal("abc=", "def="));
2893 tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
2895 tt_assert(!environment_variable_names_equal("", "a=def"));
2896 /* A bit surprising. */
2897 tt_assert(environment_variable_names_equal("", "=def"));
2898 tt_assert(environment_variable_names_equal("=y", "=x"));
2900 done:
2904 /** Test process_environment_make */
2905 static void
2906 test_util_make_environment(void *ptr)
2908 const char *env_vars_string =
2909 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
2910 "HOME=/home/foozer\n";
2911 const char expected_windows_env_block[] =
2912 "HOME=/home/foozer\000"
2913 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
2914 "\000";
2915 size_t expected_windows_env_block_len =
2916 sizeof(expected_windows_env_block) - 1;
2918 smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
2919 smartlist_t *env_vars_sorted = smartlist_new();
2920 smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
2922 process_environment_t *env;
2924 (void)ptr;
2926 env = process_environment_make(env_vars);
2928 /* Check that the Windows environment block is correct. */
2929 tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
2930 expected_windows_env_block_len));
2932 /* Now for the Unixoid environment block. We don't care which order
2933 * these environment variables are in, so we sort both lists first. */
2935 smartlist_add_all(env_vars_sorted, env_vars);
2938 char **v;
2939 for (v = env->unixoid_environment_block; *v; ++v) {
2940 smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
2944 smartlist_sort_strings(env_vars_sorted);
2945 smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
2947 tt_want_int_op(smartlist_len(env_vars_sorted), ==,
2948 smartlist_len(env_vars_in_unixoid_env_block_sorted));
2950 int len = smartlist_len(env_vars_sorted);
2951 int i;
2953 if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
2954 len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
2957 for (i = 0; i < len; ++i) {
2958 tt_want_str_op(smartlist_get(env_vars_sorted, i), ==,
2959 smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
2963 /* Clean up. */
2964 smartlist_free(env_vars_in_unixoid_env_block_sorted);
2965 smartlist_free(env_vars_sorted);
2967 SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
2968 smartlist_free(env_vars);
2970 process_environment_free(env);
2973 /** Test set_environment_variable_in_smartlist */
2974 static void
2975 test_util_set_env_var_in_sl(void *ptr)
2977 /* The environment variables in these strings are in arbitrary
2978 * order; we sort the resulting lists before comparing them.
2980 * (They *will not* end up in the order shown in
2981 * expected_resulting_env_vars_string.) */
2983 const char *base_env_vars_string =
2984 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
2985 "HOME=/home/foozer\n"
2986 "TERM=xterm\n"
2987 "SHELL=/bin/ksh\n"
2988 "USER=foozer\n"
2989 "LOGNAME=foozer\n"
2990 "USERNAME=foozer\n"
2991 "LANG=en_US.utf8\n"
2994 const char *new_env_vars_string =
2995 "TERM=putty\n"
2996 "DISPLAY=:18.0\n"
2999 const char *expected_resulting_env_vars_string =
3000 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
3001 "HOME=/home/foozer\n"
3002 "TERM=putty\n"
3003 "SHELL=/bin/ksh\n"
3004 "USER=foozer\n"
3005 "LOGNAME=foozer\n"
3006 "USERNAME=foozer\n"
3007 "LANG=en_US.utf8\n"
3008 "DISPLAY=:18.0\n"
3011 smartlist_t *merged_env_vars =
3012 smartlist_new_from_text_lines(base_env_vars_string);
3013 smartlist_t *new_env_vars =
3014 smartlist_new_from_text_lines(new_env_vars_string);
3015 smartlist_t *expected_resulting_env_vars =
3016 smartlist_new_from_text_lines(expected_resulting_env_vars_string);
3018 /* Elements of merged_env_vars are heap-allocated, and must be
3019 * freed. Some of them are (or should) be freed by
3020 * set_environment_variable_in_smartlist.
3022 * Elements of new_env_vars are heap-allocated, but are copied into
3023 * merged_env_vars, so they are not freed separately at the end of
3024 * the function.
3026 * Elements of expected_resulting_env_vars are heap-allocated, and
3027 * must be freed. */
3029 (void)ptr;
3031 SMARTLIST_FOREACH(new_env_vars, char *, env_var,
3032 set_environment_variable_in_smartlist(merged_env_vars,
3033 env_var,
3034 _tor_free,
3035 1));
3037 smartlist_sort_strings(merged_env_vars);
3038 smartlist_sort_strings(expected_resulting_env_vars);
3040 tt_want_int_op(smartlist_len(merged_env_vars), ==,
3041 smartlist_len(expected_resulting_env_vars));
3043 int len = smartlist_len(merged_env_vars);
3044 int i;
3046 if (smartlist_len(expected_resulting_env_vars) < len) {
3047 len = smartlist_len(expected_resulting_env_vars);
3050 for (i = 0; i < len; ++i) {
3051 tt_want_str_op(smartlist_get(merged_env_vars, i), ==,
3052 smartlist_get(expected_resulting_env_vars, i));
3056 /* Clean up. */
3057 SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
3058 smartlist_free(merged_env_vars);
3060 smartlist_free(new_env_vars);
3062 SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
3063 smartlist_free(expected_resulting_env_vars);
3066 #define UTIL_LEGACY(name) \
3067 { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
3069 #define UTIL_TEST(name, flags) \
3070 { #name, test_util_ ## name, flags, NULL, NULL }
3072 struct testcase_t util_tests[] = {
3073 UTIL_LEGACY(time),
3074 UTIL_TEST(parse_http_time, 0),
3075 UTIL_LEGACY(config_line),
3076 UTIL_LEGACY(config_line_quotes),
3077 UTIL_LEGACY(config_line_comment_character),
3078 UTIL_LEGACY(config_line_escaped_content),
3079 #ifndef _WIN32
3080 UTIL_LEGACY(expand_filename),
3081 #endif
3082 UTIL_LEGACY(strmisc),
3083 UTIL_LEGACY(pow2),
3084 UTIL_LEGACY(gzip),
3085 UTIL_LEGACY(datadir),
3086 UTIL_LEGACY(mempool),
3087 UTIL_LEGACY(memarea),
3088 UTIL_LEGACY(control_formats),
3089 UTIL_LEGACY(mmap),
3090 UTIL_LEGACY(threads),
3091 UTIL_LEGACY(sscanf),
3092 UTIL_LEGACY(path_is_relative),
3093 UTIL_LEGACY(strtok),
3094 UTIL_LEGACY(di_ops),
3095 UTIL_TEST(find_str_at_start_of_line, 0),
3096 UTIL_TEST(string_is_C_identifier, 0),
3097 UTIL_TEST(asprintf, 0),
3098 UTIL_TEST(listdir, 0),
3099 UTIL_TEST(parent_dir, 0),
3100 #ifdef _WIN32
3101 UTIL_TEST(load_win_lib, 0),
3102 #endif
3103 UTIL_TEST(exit_status, 0),
3104 #ifndef _WIN32
3105 UTIL_TEST(fgets_eagain, TT_SKIP),
3106 #endif
3107 UTIL_TEST(spawn_background_ok, 0),
3108 UTIL_TEST(spawn_background_fail, 0),
3109 UTIL_TEST(spawn_background_partial_read, 0),
3110 UTIL_TEST(format_hex_number, 0),
3111 UTIL_TEST(join_win_cmdline, 0),
3112 UTIL_TEST(split_lines, 0),
3113 UTIL_TEST(n_bits_set, 0),
3114 UTIL_TEST(eat_whitespace, 0),
3115 UTIL_TEST(sl_new_from_text_lines, 0),
3116 UTIL_TEST(envnames, 0),
3117 UTIL_TEST(make_environment, 0),
3118 UTIL_TEST(set_env_var_in_sl, 0),
3119 END_OF_TESTCASES