Back to index

tor  0.2.3.18-rc
test_util.c
Go to the documentation of this file.
00001 /* Copyright (c) 2001-2004, Roger Dingledine.
00002  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00003  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00004 /* See LICENSE for licensing information */
00005 
00006 #include "orconfig.h"
00007 #define CONTROL_PRIVATE
00008 #define MEMPOOL_PRIVATE
00009 #define UTIL_PRIVATE
00010 #include "or.h"
00011 #include "config.h"
00012 #include "control.h"
00013 #include "test.h"
00014 #include "mempool.h"
00015 #include "memarea.h"
00016 
00017 #ifdef _WIN32
00018 #include <tchar.h>
00019 #endif
00020 
00021 static void
00022 test_util_time(void)
00023 {
00024   struct timeval start, end;
00025   struct tm a_time;
00026   char timestr[128];
00027   time_t t_res;
00028   int i;
00029   struct timeval tv;
00030 
00031   /* Test tv_udiff */
00032 
00033   start.tv_sec = 5;
00034   start.tv_usec = 5000;
00035 
00036   end.tv_sec = 5;
00037   end.tv_usec = 5000;
00038 
00039   test_eq(0L, tv_udiff(&start, &end));
00040 
00041   end.tv_usec = 7000;
00042 
00043   test_eq(2000L, tv_udiff(&start, &end));
00044 
00045   end.tv_sec = 6;
00046 
00047   test_eq(1002000L, tv_udiff(&start, &end));
00048 
00049   end.tv_usec = 0;
00050 
00051   test_eq(995000L, tv_udiff(&start, &end));
00052 
00053   end.tv_sec = 4;
00054 
00055   test_eq(-1005000L, tv_udiff(&start, &end));
00056 
00057   /* Test tor_timegm */
00058 
00059   /* The test values here are confirmed to be correct on a platform
00060    * with a working timegm. */
00061   a_time.tm_year = 2003-1900;
00062   a_time.tm_mon = 7;
00063   a_time.tm_mday = 30;
00064   a_time.tm_hour = 6;
00065   a_time.tm_min = 14;
00066   a_time.tm_sec = 55;
00067   test_eq((time_t) 1062224095UL, tor_timegm(&a_time));
00068   a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
00069   test_eq((time_t) 1093846495UL, tor_timegm(&a_time));
00070   a_time.tm_mon = 1;          /* Try a leap year, in feb. */
00071   a_time.tm_mday = 10;
00072   test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
00073   a_time.tm_mon = 0;
00074   a_time.tm_mday = 10;
00075   test_eq((time_t) 1073715295UL, tor_timegm(&a_time));
00076   a_time.tm_mon = 12;          /* Wrong month, it's 0-based */
00077   a_time.tm_mday = 10;
00078   test_eq((time_t) -1, tor_timegm(&a_time));
00079   a_time.tm_mon = -1;          /* Wrong month */
00080   a_time.tm_mday = 10;
00081   test_eq((time_t) -1, tor_timegm(&a_time));
00082 
00083   /* Test {format,parse}_rfc1123_time */
00084 
00085   format_rfc1123_time(timestr, 0);
00086   test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr);
00087   format_rfc1123_time(timestr, (time_t)1091580502UL);
00088   test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr);
00089 
00090   t_res = 0;
00091   i = parse_rfc1123_time(timestr, &t_res);
00092   test_eq(0,i);
00093   test_eq(t_res, (time_t)1091580502UL);
00094   /* The timezone doesn't matter */
00095   t_res = 0;
00096   test_eq(0, parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
00097   test_eq(t_res, (time_t)1091580502UL);
00098   test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
00099   test_eq(-1, parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
00100   test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
00101   test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
00102   test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
00103   test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
00104   test_eq(-1, parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
00105   test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
00106 
00107 #if 0
00108   /* This fails, I imagine it's important and should be fixed? */
00109   test_eq(-1, parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
00110   /* Why is this string valid (ie. the test fails because it doesn't
00111      return -1)? */
00112   test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
00113 #endif
00114 
00115   /* Test parse_iso_time */
00116 
00117   t_res = 0;
00118   i = parse_iso_time("", &t_res);
00119   test_eq(-1, i);
00120   t_res = 0;
00121   i = parse_iso_time("2004-08-32 00:48:22", &t_res);
00122   test_eq(-1, i);
00123   t_res = 0;
00124   i = parse_iso_time("1969-08-03 00:48:22", &t_res);
00125   test_eq(-1, i);
00126 
00127   t_res = 0;
00128   i = parse_iso_time("2004-08-04 00:48:22", &t_res);
00129   test_eq(0,i);
00130   test_eq(t_res, (time_t)1091580502UL);
00131   t_res = 0;
00132   i = parse_iso_time("2004-8-4 0:48:22", &t_res);
00133   test_eq(0, i);
00134   test_eq(t_res, (time_t)1091580502UL);
00135   test_eq(-1, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res));
00136   test_eq(-1, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res));
00137   test_eq(-1, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res));
00138   test_eq(-1, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res));
00139   test_eq(-1, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res));
00140   test_eq(-1, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res));
00141   test_eq(-1, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res));
00142   test_eq(-1, parse_iso_time("2011-03-30 23:59", &t_res));
00143 
00144   /* Test tor_gettimeofday */
00145 
00146   end.tv_sec = 4;
00147   end.tv_usec = 999990;
00148   start.tv_sec = 1;
00149   start.tv_usec = 500;
00150 
00151   tor_gettimeofday(&start);
00152   /* now make sure time works. */
00153   tor_gettimeofday(&end);
00154   /* We might've timewarped a little. */
00155   tt_int_op(tv_udiff(&start, &end), >=, -5000);
00156 
00157   /* Test format_iso_time */
00158 
00159   tv.tv_sec = (time_t)1326296338;
00160   tv.tv_usec = 3060;
00161   format_iso_time(timestr, tv.tv_sec);
00162   test_streq("2012-01-11 15:38:58", timestr);
00163   /* The output of format_local_iso_time will vary by timezone, and setting
00164      our timezone for testing purposes would be a nontrivial flaky pain.
00165      Skip this test for now.
00166   format_local_iso_time(timestr, tv.tv_sec);
00167   test_streq("2012-01-11 10:38:58", timestr);
00168   */
00169   format_iso_time_nospace(timestr, tv.tv_sec);
00170   test_streq("2012-01-11T15:38:58", timestr);
00171   test_eq(strlen(timestr), ISO_TIME_LEN);
00172   format_iso_time_nospace_usec(timestr, &tv);
00173   test_streq("2012-01-11T15:38:58.003060", timestr);
00174   test_eq(strlen(timestr), ISO_TIME_USEC_LEN);
00175 
00176  done:
00177   ;
00178 }
00179 
00180 static void
00181 test_util_parse_http_time(void *arg)
00182 {
00183   struct tm a_time;
00184   char b[ISO_TIME_LEN+1];
00185   (void)arg;
00186 
00187 #define T(s) do {                               \
00188     format_iso_time(b, tor_timegm(&a_time));    \
00189     tt_str_op(b, ==, (s));                      \
00190     b[0]='\0';                                  \
00191   } while (0)
00192 
00193   /* Test parse_http_time */
00194 
00195   test_eq(-1, parse_http_time("", &a_time));
00196   test_eq(-1, parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
00197   test_eq(-1, parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
00198   test_eq(-1, parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
00199   test_eq(-1, parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
00200   test_eq(-1, parse_http_time("Sunday, August the third", &a_time));
00201   test_eq(-1, parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
00202 
00203   test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
00204   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00205   T("1994-08-04 00:48:22");
00206   test_eq(0, parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
00207   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00208   T("1994-08-04 00:48:22");
00209   test_eq(0, parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
00210   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00211   T("1994-08-04 00:48:22");
00212   test_eq(0, parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
00213   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00214   T("1994-08-04 00:48:22");
00215   test_eq(0, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
00216   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00217   T("1994-08-04 00:48:22");
00218   test_eq(0, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
00219   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00220   T("1994-08-04 00:48:22");
00221   test_eq(0, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
00222   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00223   T("1994-08-04 00:48:22");
00224   test_eq(0, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
00225   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00226   T("1994-08-04 00:48:22");
00227   test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
00228   test_eq((time_t)775961302UL, tor_timegm(&a_time));
00229   T("1994-08-04 00:48:22");
00230   test_eq(0, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
00231   test_eq((time_t)1325376000UL, tor_timegm(&a_time));
00232   T("2012-01-01 00:00:00");
00233   test_eq(0, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
00234   test_eq((time_t)1356912000UL, tor_timegm(&a_time));
00235   T("2012-12-31 00:00:00");
00236   test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
00237   test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
00238   test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
00239   test_eq(-1, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
00240   test_eq(-1, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
00241   test_eq(-1, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
00242   test_eq(-1, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
00243   test_eq(-1, parse_http_time("2011-03-30 23:59", &a_time));
00244 
00245 #undef T
00246  done:
00247   ;
00248 }
00249 
00250 static void
00251 test_util_config_line(void)
00252 {
00253   char buf[1024];
00254   char *k=NULL, *v=NULL;
00255   const char *str;
00256 
00257   /* Test parse_config_line_from_str */
00258   strlcpy(buf, "k v\n" " key    value with spaces   \n" "keykey val\n"
00259           "k2\n"
00260           "k3 \n" "\n" "   \n" "#comment\n"
00261           "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
00262           "kseven   \"a quoted 'string\"\n"
00263           "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
00264           "k9 a line that\\\n spans two lines.\n\n"
00265           "k10 more than\\\n one contin\\\nuation\n"
00266           "k11  \\\ncontinuation at the start\n"
00267           "k12 line with a\\\n#comment\n embedded\n"
00268           "k13\\\ncontinuation at the very start\n"
00269           "k14 a line that has a comment and # ends with a slash \\\n"
00270           "k15 this should be the next new line\n"
00271           "k16 a line that has a comment and # ends without a slash \n"
00272           "k17 this should be the next new line\n"
00273           , sizeof(buf));
00274   str = buf;
00275 
00276   str = parse_config_line_from_str(str, &k, &v);
00277   test_streq(k, "k");
00278   test_streq(v, "v");
00279   tor_free(k); tor_free(v);
00280   test_assert(!strcmpstart(str, "key    value with"));
00281 
00282   str = parse_config_line_from_str(str, &k, &v);
00283   test_streq(k, "key");
00284   test_streq(v, "value with spaces");
00285   tor_free(k); tor_free(v);
00286   test_assert(!strcmpstart(str, "keykey"));
00287 
00288   str = parse_config_line_from_str(str, &k, &v);
00289   test_streq(k, "keykey");
00290   test_streq(v, "val");
00291   tor_free(k); tor_free(v);
00292   test_assert(!strcmpstart(str, "k2\n"));
00293 
00294   str = parse_config_line_from_str(str, &k, &v);
00295   test_streq(k, "k2");
00296   test_streq(v, "");
00297   tor_free(k); tor_free(v);
00298   test_assert(!strcmpstart(str, "k3 \n"));
00299 
00300   str = parse_config_line_from_str(str, &k, &v);
00301   test_streq(k, "k3");
00302   test_streq(v, "");
00303   tor_free(k); tor_free(v);
00304   test_assert(!strcmpstart(str, "#comment"));
00305 
00306   str = parse_config_line_from_str(str, &k, &v);
00307   test_streq(k, "k4");
00308   test_streq(v, "");
00309   tor_free(k); tor_free(v);
00310   test_assert(!strcmpstart(str, "k5#abc"));
00311 
00312   str = parse_config_line_from_str(str, &k, &v);
00313   test_streq(k, "k5");
00314   test_streq(v, "");
00315   tor_free(k); tor_free(v);
00316   test_assert(!strcmpstart(str, "k6"));
00317 
00318   str = parse_config_line_from_str(str, &k, &v);
00319   test_streq(k, "k6");
00320   test_streq(v, "val");
00321   tor_free(k); tor_free(v);
00322   test_assert(!strcmpstart(str, "kseven"));
00323 
00324   str = parse_config_line_from_str(str, &k, &v);
00325   test_streq(k, "kseven");
00326   test_streq(v, "a quoted \'string");
00327   tor_free(k); tor_free(v);
00328   test_assert(!strcmpstart(str, "k8 "));
00329 
00330   str = parse_config_line_from_str(str, &k, &v);
00331   test_streq(k, "k8");
00332   test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
00333   tor_free(k); tor_free(v);
00334 
00335   str = parse_config_line_from_str(str, &k, &v);
00336   test_streq(k, "k9");
00337   test_streq(v, "a line that spans two lines.");
00338   tor_free(k); tor_free(v);
00339 
00340   str = parse_config_line_from_str(str, &k, &v);
00341   test_streq(k, "k10");
00342   test_streq(v, "more than one continuation");
00343   tor_free(k); tor_free(v);
00344 
00345   str = parse_config_line_from_str(str, &k, &v);
00346   test_streq(k, "k11");
00347   test_streq(v, "continuation at the start");
00348   tor_free(k); tor_free(v);
00349 
00350   str = parse_config_line_from_str(str, &k, &v);
00351   test_streq(k, "k12");
00352   test_streq(v, "line with a embedded");
00353   tor_free(k); tor_free(v);
00354 
00355   str = parse_config_line_from_str(str, &k, &v);
00356   test_streq(k, "k13");
00357   test_streq(v, "continuation at the very start");
00358   tor_free(k); tor_free(v);
00359 
00360   str = parse_config_line_from_str(str, &k, &v);
00361   test_streq(k, "k14");
00362   test_streq(v, "a line that has a comment and" );
00363   tor_free(k); tor_free(v);
00364 
00365   str = parse_config_line_from_str(str, &k, &v);
00366   test_streq(k, "k15");
00367   test_streq(v, "this should be the next new line");
00368   tor_free(k); tor_free(v);
00369 
00370   str = parse_config_line_from_str(str, &k, &v);
00371   test_streq(k, "k16");
00372   test_streq(v, "a line that has a comment and" );
00373   tor_free(k); tor_free(v);
00374 
00375   str = parse_config_line_from_str(str, &k, &v);
00376   test_streq(k, "k17");
00377   test_streq(v, "this should be the next new line");
00378   tor_free(k); tor_free(v);
00379 
00380   test_streq(str, "");
00381 
00382  done:
00383   tor_free(k);
00384   tor_free(v);
00385 }
00386 
00387 static void
00388 test_util_config_line_quotes(void)
00389 {
00390   char buf1[1024];
00391   char buf2[128];
00392   char buf3[128];
00393   char buf4[128];
00394   char *k=NULL, *v=NULL;
00395   const char *str;
00396 
00397   /* Test parse_config_line_from_str */
00398   strlcpy(buf1, "kTrailingSpace \"quoted value\"   \n"
00399           "kTrailingGarbage \"quoted value\"trailing garbage\n"
00400           , sizeof(buf1));
00401   strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
00402           , sizeof(buf2));
00403   strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
00404           , sizeof(buf3));
00405   strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
00406           , sizeof(buf4));
00407   str = buf1;
00408 
00409   str = parse_config_line_from_str(str, &k, &v);
00410   test_streq(k, "kTrailingSpace");
00411   test_streq(v, "quoted value");
00412   tor_free(k); tor_free(v);
00413 
00414   str = parse_config_line_from_str(str, &k, &v);
00415   test_eq_ptr(str, NULL);
00416   tor_free(k); tor_free(v);
00417 
00418   str = buf2;
00419 
00420   str = parse_config_line_from_str(str, &k, &v);
00421   test_eq_ptr(str, NULL);
00422   tor_free(k); tor_free(v);
00423 
00424   str = buf3;
00425 
00426   str = parse_config_line_from_str(str, &k, &v);
00427   test_eq_ptr(str, NULL);
00428   tor_free(k); tor_free(v);
00429 
00430   str = buf4;
00431 
00432   str = parse_config_line_from_str(str, &k, &v);
00433   test_eq_ptr(str, NULL);
00434   tor_free(k); tor_free(v);
00435 
00436  done:
00437   tor_free(k);
00438   tor_free(v);
00439 }
00440 
00441 static void
00442 test_util_config_line_comment_character(void)
00443 {
00444   char buf[1024];
00445   char *k=NULL, *v=NULL;
00446   const char *str;
00447 
00448   /* Test parse_config_line_from_str */
00449   strlcpy(buf, "k1 \"# in quotes\"\n"
00450           "k2 some value    # some comment\n"
00451           "k3 /home/user/myTorNetwork#2\n"    /* Testcase for #1323 */
00452           , sizeof(buf));
00453   str = buf;
00454 
00455   str = parse_config_line_from_str(str, &k, &v);
00456   test_streq(k, "k1");
00457   test_streq(v, "# in quotes");
00458   tor_free(k); tor_free(v);
00459 
00460   str = parse_config_line_from_str(str, &k, &v);
00461   test_streq(k, "k2");
00462   test_streq(v, "some value");
00463   tor_free(k); tor_free(v);
00464 
00465   test_streq(str, "k3 /home/user/myTorNetwork#2\n");
00466 
00467 #if 0
00468   str = parse_config_line_from_str(str, &k, &v);
00469   test_streq(k, "k3");
00470   test_streq(v, "/home/user/myTorNetwork#2");
00471   tor_free(k); tor_free(v);
00472 
00473   test_streq(str, "");
00474 #endif
00475 
00476  done:
00477   tor_free(k);
00478   tor_free(v);
00479 }
00480 
00481 static void
00482 test_util_config_line_escaped_content(void)
00483 {
00484   char buf1[1024];
00485   char buf2[128];
00486   char buf3[128];
00487   char buf4[128];
00488   char buf5[128];
00489   char buf6[128];
00490   char *k=NULL, *v=NULL;
00491   const char *str;
00492 
00493   /* Test parse_config_line_from_str */
00494   strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
00495           "HexadecimalUpper \"\\x2A\"\n"
00496           "HexadecimalUpperX \"\\X2A\"\n"
00497           "Octal \"\\52\"\n"
00498           "Newline \"\\n\"\n"
00499           "Tab \"\\t\"\n"
00500           "CarriageReturn \"\\r\"\n"
00501           "DoubleQuote \"\\\"\"\n"
00502           "SimpleQuote \"\\'\"\n"
00503           "Backslash \"\\\\\"\n"
00504           "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
00505           , sizeof(buf1));
00506 
00507   strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
00508           , sizeof(buf2));
00509 
00510   strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
00511           , sizeof(buf3));
00512 
00513   strlcpy(buf4, "BrokenOctal \"\\8\"\n"
00514           , sizeof(buf4));
00515 
00516   strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
00517           , sizeof(buf5));
00518 
00519   strlcpy(buf6, "BrokenEscape \"\\"
00520           , sizeof(buf6));
00521 
00522   str = buf1;
00523 
00524   str = parse_config_line_from_str(str, &k, &v);
00525   test_streq(k, "HexadecimalLower");
00526   test_streq(v, "*");
00527   tor_free(k); tor_free(v);
00528 
00529   str = parse_config_line_from_str(str, &k, &v);
00530   test_streq(k, "HexadecimalUpper");
00531   test_streq(v, "*");
00532   tor_free(k); tor_free(v);
00533 
00534   str = parse_config_line_from_str(str, &k, &v);
00535   test_streq(k, "HexadecimalUpperX");
00536   test_streq(v, "*");
00537   tor_free(k); tor_free(v);
00538 
00539   str = parse_config_line_from_str(str, &k, &v);
00540   test_streq(k, "Octal");
00541   test_streq(v, "*");
00542   tor_free(k); tor_free(v);
00543 
00544   str = parse_config_line_from_str(str, &k, &v);
00545   test_streq(k, "Newline");
00546   test_streq(v, "\n");
00547   tor_free(k); tor_free(v);
00548 
00549   str = parse_config_line_from_str(str, &k, &v);
00550   test_streq(k, "Tab");
00551   test_streq(v, "\t");
00552   tor_free(k); tor_free(v);
00553 
00554   str = parse_config_line_from_str(str, &k, &v);
00555   test_streq(k, "CarriageReturn");
00556   test_streq(v, "\r");
00557   tor_free(k); tor_free(v);
00558 
00559   str = parse_config_line_from_str(str, &k, &v);
00560   test_streq(k, "DoubleQuote");
00561   test_streq(v, "\"");
00562   tor_free(k); tor_free(v);
00563 
00564   str = parse_config_line_from_str(str, &k, &v);
00565   test_streq(k, "SimpleQuote");
00566   test_streq(v, "'");
00567   tor_free(k); tor_free(v);
00568 
00569   str = parse_config_line_from_str(str, &k, &v);
00570   test_streq(k, "Backslash");
00571   test_streq(v, "\\");
00572   tor_free(k); tor_free(v);
00573 
00574   str = parse_config_line_from_str(str, &k, &v);
00575   test_streq(k, "Mix");
00576   test_streq(v, "This is a \"star\":\t'*'\nAnd second line");
00577   tor_free(k); tor_free(v);
00578   test_streq(str, "");
00579 
00580   str = buf2;
00581 
00582   str = parse_config_line_from_str(str, &k, &v);
00583   test_eq_ptr(str, NULL);
00584   tor_free(k); tor_free(v);
00585 
00586   str = buf3;
00587 
00588   str = parse_config_line_from_str(str, &k, &v);
00589   test_eq_ptr(str, NULL);
00590   tor_free(k); tor_free(v);
00591 
00592   str = buf4;
00593 
00594   str = parse_config_line_from_str(str, &k, &v);
00595   test_eq_ptr(str, NULL);
00596   tor_free(k); tor_free(v);
00597 
00598 #if 0
00599   str = buf5;
00600 
00601   str = parse_config_line_from_str(str, &k, &v);
00602   test_eq_ptr(str, NULL);
00603   tor_free(k); tor_free(v);
00604 #endif
00605 
00606   str = buf6;
00607 
00608   str = parse_config_line_from_str(str, &k, &v);
00609   test_eq_ptr(str, NULL);
00610   tor_free(k); tor_free(v);
00611 
00612  done:
00613   tor_free(k);
00614   tor_free(v);
00615 }
00616 
00617 #ifndef _WIN32
00618 static void
00619 test_util_expand_filename(void)
00620 {
00621   char *str;
00622 
00623   setenv("HOME", "/home/itv", 1); /* For "internal test value" */
00624 
00625   str = expand_filename("");
00626   test_streq("", str);
00627   tor_free(str);
00628 
00629   str = expand_filename("/normal/path");
00630   test_streq("/normal/path", str);
00631   tor_free(str);
00632 
00633   str = expand_filename("/normal/trailing/path/");
00634   test_streq("/normal/trailing/path/", str);
00635   tor_free(str);
00636 
00637   str = expand_filename("~");
00638   test_streq("/home/itv/", str);
00639   tor_free(str);
00640 
00641   str = expand_filename("$HOME/nodice");
00642   test_streq("$HOME/nodice", str);
00643   tor_free(str);
00644 
00645   str = expand_filename("~/");
00646   test_streq("/home/itv/", str);
00647   tor_free(str);
00648 
00649   str = expand_filename("~/foobarqux");
00650   test_streq("/home/itv/foobarqux", str);
00651   tor_free(str);
00652 
00653   str = expand_filename("~/../../etc/passwd");
00654   test_streq("/home/itv/../../etc/passwd", str);
00655   tor_free(str);
00656 
00657   str = expand_filename("~/trailing/");
00658   test_streq("/home/itv/trailing/", str);
00659   tor_free(str);
00660   /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
00661      have to somehow inject/fake the get_user_homedir call) */
00662 
00663   /* $HOME ending in a trailing slash */
00664   setenv("HOME", "/home/itv/", 1);
00665 
00666   str = expand_filename("~");
00667   test_streq("/home/itv/", str);
00668   tor_free(str);
00669 
00670   str = expand_filename("~/");
00671   test_streq("/home/itv/", str);
00672   tor_free(str);
00673 
00674   str = expand_filename("~/foo");
00675   test_streq("/home/itv/foo", str);
00676   tor_free(str);
00677 
00678   /* Try with empty $HOME */
00679 
00680   setenv("HOME", "", 1);
00681 
00682   str = expand_filename("~");
00683   test_streq("/", str);
00684   tor_free(str);
00685 
00686   str = expand_filename("~/");
00687   test_streq("/", str);
00688   tor_free(str);
00689 
00690   str = expand_filename("~/foobar");
00691   test_streq("/foobar", str);
00692   tor_free(str);
00693 
00694   /* Try with $HOME unset */
00695 
00696   unsetenv("HOME");
00697 
00698   str = expand_filename("~");
00699   test_streq("/", str);
00700   tor_free(str);
00701 
00702   str = expand_filename("~/");
00703   test_streq("/", str);
00704   tor_free(str);
00705 
00706   str = expand_filename("~/foobar");
00707   test_streq("/foobar", str);
00708   tor_free(str);
00709 
00710  done:
00711   tor_free(str);
00712 }
00713 #endif
00714 
00716 static void
00717 test_util_strmisc(void)
00718 {
00719   char buf[1024];
00720   int i;
00721   char *cp;
00722 
00723   /* Test strl operations */
00724   test_eq(5, strlcpy(buf, "Hello", 0));
00725   test_eq(5, strlcpy(buf, "Hello", 10));
00726   test_streq(buf, "Hello");
00727   test_eq(5, strlcpy(buf, "Hello", 6));
00728   test_streq(buf, "Hello");
00729   test_eq(5, strlcpy(buf, "Hello", 5));
00730   test_streq(buf, "Hell");
00731   strlcpy(buf, "Hello", sizeof(buf));
00732   test_eq(10, strlcat(buf, "Hello", 5));
00733 
00734   /* Test strstrip() */
00735   strlcpy(buf, "Testing 1 2 3", sizeof(buf));
00736   tor_strstrip(buf, ",!");
00737   test_streq(buf, "Testing 1 2 3");
00738   strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
00739   tor_strstrip(buf, "!? ");
00740   test_streq(buf, "Testing123");
00741   strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
00742   tor_strstrip(buf, "!? ");
00743   test_streq(buf, "Testing123");
00744 
00745   /* Test parse_long */
00746   /* Empty/zero input */
00747   test_eq(0L, tor_parse_long("",10,0,100,&i,NULL));
00748   test_eq(0, i);
00749   test_eq(0L, tor_parse_long("0",10,0,100,&i,NULL));
00750   test_eq(1, i);
00751   /* Normal cases */
00752   test_eq(10L, tor_parse_long("10",10,0,100,&i,NULL));
00753   test_eq(1, i);
00754   test_eq(10L, tor_parse_long("10",10,0,10,&i,NULL));
00755   test_eq(1, i);
00756   test_eq(10L, tor_parse_long("10",10,10,100,&i,NULL));
00757   test_eq(1, i);
00758   test_eq(-50L, tor_parse_long("-50",10,-100,100,&i,NULL));
00759   test_eq(1, i);
00760   test_eq(-50L, tor_parse_long("-50",10,-100,0,&i,NULL));
00761   test_eq(1, i);
00762   test_eq(-50L, tor_parse_long("-50",10,-50,0,&i,NULL));
00763   test_eq(1, i);
00764   /* Extra garbage */
00765   test_eq(0L, tor_parse_long("10m",10,0,100,&i,NULL));
00766   test_eq(0, i);
00767   test_eq(0L, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
00768   test_eq(0, i);
00769   test_eq(10L, tor_parse_long("10m",10,0,100,&i,&cp));
00770   test_eq(1, i);
00771   test_streq(cp, "m");
00772   test_eq(-50L, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
00773   test_eq(1, i);
00774   test_streq(cp, " plus garbage");
00775   /* Out of bounds */
00776   test_eq(0L,  tor_parse_long("10",10,50,100,&i,NULL));
00777   test_eq(0, i);
00778   test_eq(0L,   tor_parse_long("-50",10,0,100,&i,NULL));
00779   test_eq(0, i);
00780   /* Base different than 10 */
00781   test_eq(2L,   tor_parse_long("10",2,0,100,NULL,NULL));
00782   test_eq(0L,   tor_parse_long("2",2,0,100,NULL,NULL));
00783   test_eq(0L,   tor_parse_long("10",-2,0,100,NULL,NULL));
00784   test_eq(68284L, tor_parse_long("10abc",16,0,70000,NULL,NULL));
00785   test_eq(68284L, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
00786 
00787   /* Test parse_ulong */
00788   test_eq(0UL, tor_parse_ulong("",10,0,100,NULL,NULL));
00789   test_eq(0UL, tor_parse_ulong("0",10,0,100,NULL,NULL));
00790   test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL));
00791   test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL));
00792   test_eq(10UL, tor_parse_ulong("10",10,0,10,NULL,NULL));
00793   test_eq(10UL, tor_parse_ulong("10",10,10,100,NULL,NULL));
00794   test_eq(0UL, tor_parse_ulong("8",8,0,100,NULL,NULL));
00795   test_eq(50UL, tor_parse_ulong("50",10,50,100,NULL,NULL));
00796   test_eq(0UL, tor_parse_ulong("-50",10,-100,100,NULL,NULL));
00797 
00798   /* Test parse_uint64 */
00799   test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
00800   test_eq(1, i);
00801   test_streq(cp, " x");
00802   test_assert(U64_LITERAL(12345678901) ==
00803               tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
00804   test_eq(1, i);
00805   test_streq(cp, "");
00806   test_assert(U64_LITERAL(0) ==
00807               tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
00808   test_eq(0, i);
00809 
00810   {
00811   /* Test parse_double */
00812   double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL);
00813   test_eq(1, i);
00814   test_assert(DBL_TO_U64(d) == 10);
00815   d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL);
00816   test_eq(1, i);
00817   test_assert(DBL_TO_U64(d) == 0);
00818   d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL);
00819   test_eq(0, i);
00820   d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL);
00821   test_eq(0, i);
00822   d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp);
00823   test_eq(1, i);
00824   d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL);
00825   test_eq(1, i);
00826   test_assert(DBL_TO_U64(d) == 0);
00827   d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
00828   test_eq(1, i);
00829   test_eq(-10.0, d);
00830   }
00831 
00832   {
00833     /* Test tor_parse_* where we overflow/underflow the underlying type. */
00834     /* This string should overflow 64-bit ints. */
00835 #define TOOBIG "100000000000000000000000000"
00836     test_eq(0L, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
00837     test_eq(i, 0);
00838     test_eq(0L, tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
00839     test_eq(i, 0);
00840     test_eq(0UL, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
00841     test_eq(i, 0);
00842     test_eq(U64_LITERAL(0), tor_parse_uint64(TOOBIG, 10,
00843                                              0, UINT64_MAX, &i, NULL));
00844     test_eq(i, 0);
00845   }
00846 
00847   /* Test snprintf */
00848   /* Returning -1 when there's not enough room in the output buffer */
00849   test_eq(-1, tor_snprintf(buf, 0, "Foo"));
00850   test_eq(-1, tor_snprintf(buf, 2, "Foo"));
00851   test_eq(-1, tor_snprintf(buf, 3, "Foo"));
00852   test_neq(-1, tor_snprintf(buf, 4, "Foo"));
00853   /* Always NUL-terminate the output */
00854   tor_snprintf(buf, 5, "abcdef");
00855   test_eq(0, buf[4]);
00856   tor_snprintf(buf, 10, "abcdef");
00857   test_eq(0, buf[6]);
00858   /* uint64 */
00859   tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
00860                U64_PRINTF_ARG(U64_LITERAL(12345678901)));
00861   test_streq("x!12345678901!x", buf);
00862 
00863   /* Test str{,case}cmpstart */
00864   test_assert(strcmpstart("abcdef", "abcdef")==0);
00865   test_assert(strcmpstart("abcdef", "abc")==0);
00866   test_assert(strcmpstart("abcdef", "abd")<0);
00867   test_assert(strcmpstart("abcdef", "abb")>0);
00868   test_assert(strcmpstart("ab", "abb")<0);
00869   test_assert(strcmpstart("ab", "")==0);
00870   test_assert(strcmpstart("ab", "ab ")<0);
00871   test_assert(strcasecmpstart("abcdef", "abCdEF")==0);
00872   test_assert(strcasecmpstart("abcDeF", "abc")==0);
00873   test_assert(strcasecmpstart("abcdef", "Abd")<0);
00874   test_assert(strcasecmpstart("Abcdef", "abb")>0);
00875   test_assert(strcasecmpstart("ab", "Abb")<0);
00876   test_assert(strcasecmpstart("ab", "")==0);
00877   test_assert(strcasecmpstart("ab", "ab ")<0);
00878 
00879   /* Test str{,case}cmpend */
00880   test_assert(strcmpend("abcdef", "abcdef")==0);
00881   test_assert(strcmpend("abcdef", "def")==0);
00882   test_assert(strcmpend("abcdef", "deg")<0);
00883   test_assert(strcmpend("abcdef", "dee")>0);
00884   test_assert(strcmpend("ab", "aab")>0);
00885   test_assert(strcasecmpend("AbcDEF", "abcdef")==0);
00886   test_assert(strcasecmpend("abcdef", "dEF")==0);
00887   test_assert(strcasecmpend("abcdef", "Deg")<0);
00888   test_assert(strcasecmpend("abcDef", "dee")>0);
00889   test_assert(strcasecmpend("AB", "abb")<0);
00890 
00891   /* Test digest_is_zero */
00892   memset(buf,0,20);
00893   buf[20] = 'x';
00894   test_assert(tor_digest_is_zero(buf));
00895   buf[19] = 'x';
00896   test_assert(!tor_digest_is_zero(buf));
00897 
00898   /* Test mem_is_zero */
00899   memset(buf,0,128);
00900   buf[128] = 'x';
00901   test_assert(tor_mem_is_zero(buf, 10));
00902   test_assert(tor_mem_is_zero(buf, 20));
00903   test_assert(tor_mem_is_zero(buf, 128));
00904   test_assert(!tor_mem_is_zero(buf, 129));
00905   buf[60] = (char)255;
00906   test_assert(!tor_mem_is_zero(buf, 128));
00907   buf[0] = (char)1;
00908   test_assert(!tor_mem_is_zero(buf, 10));
00909 
00910   /* Test 'escaped' */
00911   test_assert(NULL == escaped(NULL));
00912   test_streq("\"\"", escaped(""));
00913   test_streq("\"abcd\"", escaped("abcd"));
00914   test_streq("\"\\\\ \\n\\r\\t\\\"\\'\"", escaped("\\ \n\r\t\"'"));
00915   test_streq("\"unnecessary \\'backslashes\\'\"",
00916              escaped("unnecessary \'backslashes\'"));
00917   /* Non-printable characters appear as octal */
00918   test_streq("\"z\\001abc\\277d\"",  escaped("z\001abc\277d"));
00919   test_streq("\"z\\336\\255 ;foo\"", escaped("z\xde\xad\x20;foo"));
00920 
00921   /* Test strndup and memdup */
00922   {
00923     const char *s = "abcdefghijklmnopqrstuvwxyz";
00924     cp = tor_strndup(s, 30);
00925     test_streq(cp, s); /* same string, */
00926     test_neq(cp, s); /* but different pointers. */
00927     tor_free(cp);
00928 
00929     cp = tor_strndup(s, 5);
00930     test_streq(cp, "abcde");
00931     tor_free(cp);
00932 
00933     s = "a\0b\0c\0d\0e\0";
00934     cp = tor_memdup(s,10);
00935     test_memeq(cp, s, 10); /* same ram, */
00936     test_neq(cp, s); /* but different pointers. */
00937     tor_free(cp);
00938   }
00939 
00940   /* Test str-foo functions */
00941   cp = tor_strdup("abcdef");
00942   test_assert(tor_strisnonupper(cp));
00943   cp[3] = 'D';
00944   test_assert(!tor_strisnonupper(cp));
00945   tor_strupper(cp);
00946   test_streq(cp, "ABCDEF");
00947   tor_strlower(cp);
00948   test_streq(cp, "abcdef");
00949   test_assert(tor_strisnonupper(cp));
00950   test_assert(tor_strisprint(cp));
00951   cp[3] = 3;
00952   test_assert(!tor_strisprint(cp));
00953   tor_free(cp);
00954 
00955   /* Test memmem and memstr */
00956   {
00957     const char *haystack = "abcde";
00958     test_assert(!tor_memmem(haystack, 5, "ef", 2));
00959     test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
00960     test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
00961     test_assert(!tor_memmem(haystack, 4, "cde", 3));
00962     haystack = "ababcad";
00963     test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2);
00964     /* memstr */
00965     test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2);
00966     test_eq_ptr(tor_memstr(haystack, 7, "cad"), haystack + 4);
00967     test_assert(!tor_memstr(haystack, 6, "cad"));
00968     test_assert(!tor_memstr(haystack, 7, "cadd"));
00969     test_assert(!tor_memstr(haystack, 7, "fe"));
00970     test_assert(!tor_memstr(haystack, 7, "ababcade"));
00971   }
00972 
00973   /* Test wrap_string */
00974   {
00975     smartlist_t *sl = smartlist_new();
00976     wrap_string(sl,
00977                 "This is a test of string wrapping functionality: woot. "
00978                     "a functionality? w00t w00t...!",
00979                 10, "", "");
00980     cp = smartlist_join_strings(sl, "", 0, NULL);
00981     test_streq(cp,
00982             "This is a\ntest of\nstring\nwrapping\nfunctional\nity: woot.\n"
00983                "a\nfunctional\nity? w00t\nw00t...!\n");
00984     tor_free(cp);
00985     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
00986     smartlist_clear(sl);
00987 
00988     wrap_string(sl, "This is a test of string wrapping functionality: woot.",
00989                 16, "### ", "# ");
00990     cp = smartlist_join_strings(sl, "", 0, NULL);
00991     test_streq(cp,
00992              "### This is a\n# test of string\n# wrapping\n# functionality:\n"
00993              "# woot.\n");
00994     tor_free(cp);
00995     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
00996     smartlist_clear(sl);
00997 
00998     wrap_string(sl, "A test of string wrapping...", 6, "### ", "# ");
00999     cp = smartlist_join_strings(sl, "", 0, NULL);
01000     test_streq(cp,
01001                "### A\n# test\n# of\n# stri\n# ng\n# wrap\n# ping\n# ...\n");
01002     tor_free(cp);
01003     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
01004     smartlist_clear(sl);
01005 
01006     wrap_string(sl, "Wrapping test", 6, "#### ", "# ");
01007     cp = smartlist_join_strings(sl, "", 0, NULL);
01008     test_streq(cp, "#### W\n# rapp\n# ing\n# test\n");
01009     tor_free(cp);
01010     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
01011     smartlist_clear(sl);
01012 
01013     wrap_string(sl, "Small test", 6, "### ", "#### ");
01014     cp = smartlist_join_strings(sl, "", 0, NULL);
01015     test_streq(cp, "### Sm\n#### a\n#### l\n#### l\n#### t\n#### e"
01016                    "\n#### s\n#### t\n");
01017     tor_free(cp);
01018     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
01019     smartlist_clear(sl);
01020 
01021     wrap_string(sl, "First null", 6, NULL, "> ");
01022     cp = smartlist_join_strings(sl, "", 0, NULL);
01023     test_streq(cp, "First\n> null\n");
01024     tor_free(cp);
01025     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
01026     smartlist_clear(sl);
01027 
01028     wrap_string(sl, "Second null", 6, "> ", NULL);
01029     cp = smartlist_join_strings(sl, "", 0, NULL);
01030     test_streq(cp, "> Seco\nnd\nnull\n");
01031     tor_free(cp);
01032     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
01033     smartlist_clear(sl);
01034 
01035     wrap_string(sl, "Both null", 6, NULL, NULL);
01036     cp = smartlist_join_strings(sl, "", 0, NULL);
01037     test_streq(cp, "Both\nnull\n");
01038     tor_free(cp);
01039     SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
01040     smartlist_free(sl);
01041 
01042     /* Can't test prefixes that have the same length as the line width, because
01043        the function has an assert */
01044   }
01045 
01046   /* Test hex_str */
01047   {
01048     char binary_data[68];
01049     size_t i;
01050     for (i = 0; i < sizeof(binary_data); ++i)
01051       binary_data[i] = i;
01052     test_streq(hex_str(binary_data, 0), "");
01053     test_streq(hex_str(binary_data, 1), "00");
01054     test_streq(hex_str(binary_data, 17), "000102030405060708090A0B0C0D0E0F10");
01055     test_streq(hex_str(binary_data, 32),
01056                "000102030405060708090A0B0C0D0E0F"
01057                "101112131415161718191A1B1C1D1E1F");
01058     test_streq(hex_str(binary_data, 34),
01059                "000102030405060708090A0B0C0D0E0F"
01060                "101112131415161718191A1B1C1D1E1F");
01061     /* Repeat these tests for shorter strings after longer strings
01062        have been tried, to make sure we're correctly terminating strings */
01063     test_streq(hex_str(binary_data, 1), "00");
01064     test_streq(hex_str(binary_data, 0), "");
01065   }
01066 
01067   /* Test strcmp_opt */
01068   tt_int_op(strcmp_opt("",   "foo"), <, 0);
01069   tt_int_op(strcmp_opt("",    ""),  ==, 0);
01070   tt_int_op(strcmp_opt("foo", ""),   >, 0);
01071 
01072   tt_int_op(strcmp_opt(NULL,  ""),    <, 0);
01073   tt_int_op(strcmp_opt(NULL,  NULL), ==, 0);
01074   tt_int_op(strcmp_opt("",    NULL),  >, 0);
01075 
01076   tt_int_op(strcmp_opt(NULL,  "foo"), <, 0);
01077   tt_int_op(strcmp_opt("foo", NULL),  >, 0);
01078 
01079   /* Test strcmp_len */
01080   tt_int_op(strcmp_len("foo", "bar", 3),   >, 0);
01081   tt_int_op(strcmp_len("foo", "bar", 2),   <, 0); /* First len, then lexical */
01082   tt_int_op(strcmp_len("foo2", "foo1", 4), >, 0);
01083   tt_int_op(strcmp_len("foo2", "foo1", 3), <, 0); /* Really stop at len */
01084   tt_int_op(strcmp_len("foo2", "foo", 3), ==, 0);   /* Really stop at len */
01085   tt_int_op(strcmp_len("blah", "", 4),     >, 0);
01086   tt_int_op(strcmp_len("blah", "", 0),    ==, 0);
01087 
01088  done:
01089   ;
01090 }
01091 
01092 static void
01093 test_util_pow2(void)
01094 {
01095   /* Test tor_log2(). */
01096   test_eq(tor_log2(64), 6);
01097   test_eq(tor_log2(65), 6);
01098   test_eq(tor_log2(63), 5);
01099   test_eq(tor_log2(1), 0);
01100   test_eq(tor_log2(2), 1);
01101   test_eq(tor_log2(3), 1);
01102   test_eq(tor_log2(4), 2);
01103   test_eq(tor_log2(5), 2);
01104   test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55);
01105   test_eq(tor_log2(UINT64_MAX), 63);
01106 
01107   /* Test round_to_power_of_2 */
01108   test_eq(round_to_power_of_2(120), 128);
01109   test_eq(round_to_power_of_2(128), 128);
01110   test_eq(round_to_power_of_2(130), 128);
01111   test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)),
01112           U64_LITERAL(1)<<55);
01113   test_eq(round_to_power_of_2(0), 2);
01114 
01115  done:
01116   ;
01117 }
01118 
01120 static tor_mutex_t *_thread_test_mutex = NULL;
01123 static tor_mutex_t *_thread_test_start1 = NULL,
01124                    *_thread_test_start2 = NULL;
01126 static strmap_t *_thread_test_strmap = NULL;
01128 static char *_thread1_name = NULL;
01130 static char *_thread2_name = NULL;
01131 
01132 static void _thread_test_func(void* _s) ATTR_NORETURN;
01133 
01135 static int t1_count = 0, t2_count = 0;
01136 
01141 static void
01142 _thread_test_func(void* _s)
01143 {
01144   char *s = _s;
01145   int i, *count;
01146   tor_mutex_t *m;
01147   char buf[64];
01148   char **cp;
01149   if (!strcmp(s, "thread 1")) {
01150     m = _thread_test_start1;
01151     cp = &_thread1_name;
01152     count = &t1_count;
01153   } else {
01154     m = _thread_test_start2;
01155     cp = &_thread2_name;
01156     count = &t2_count;
01157   }
01158 
01159   tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id());
01160   *cp = tor_strdup(buf);
01161 
01162   tor_mutex_acquire(m);
01163 
01164   for (i=0; i<10000; ++i) {
01165     tor_mutex_acquire(_thread_test_mutex);
01166     strmap_set(_thread_test_strmap, "last to run", *cp);
01167     ++*count;
01168     tor_mutex_release(_thread_test_mutex);
01169   }
01170   tor_mutex_acquire(_thread_test_mutex);
01171   strmap_set(_thread_test_strmap, s, *cp);
01172   tor_mutex_release(_thread_test_mutex);
01173 
01174   tor_mutex_release(m);
01175 
01176   spawn_exit();
01177 }
01178 
01180 static void
01181 test_util_threads(void)
01182 {
01183   char *s1 = NULL, *s2 = NULL;
01184   int done = 0, timedout = 0;
01185   time_t started;
01186 #ifndef _WIN32
01187   struct timeval tv;
01188   tv.tv_sec=0;
01189   tv.tv_usec=100*1000;
01190 #endif
01191 #ifndef TOR_IS_MULTITHREADED
01192   /* Skip this test if we aren't threading. We should be threading most
01193    * everywhere by now. */
01194   if (1)
01195     return;
01196 #endif
01197   _thread_test_mutex = tor_mutex_new();
01198   _thread_test_start1 = tor_mutex_new();
01199   _thread_test_start2 = tor_mutex_new();
01200   _thread_test_strmap = strmap_new();
01201   s1 = tor_strdup("thread 1");
01202   s2 = tor_strdup("thread 2");
01203   tor_mutex_acquire(_thread_test_start1);
01204   tor_mutex_acquire(_thread_test_start2);
01205   spawn_func(_thread_test_func, s1);
01206   spawn_func(_thread_test_func, s2);
01207   tor_mutex_release(_thread_test_start2);
01208   tor_mutex_release(_thread_test_start1);
01209   started = time(NULL);
01210   while (!done) {
01211     tor_mutex_acquire(_thread_test_mutex);
01212     strmap_assert_ok(_thread_test_strmap);
01213     if (strmap_get(_thread_test_strmap, "thread 1") &&
01214         strmap_get(_thread_test_strmap, "thread 2")) {
01215       done = 1;
01216     } else if (time(NULL) > started + 150) {
01217       timedout = done = 1;
01218     }
01219     tor_mutex_release(_thread_test_mutex);
01220 #ifndef _WIN32
01221     /* Prevent the main thread from starving the worker threads. */
01222     select(0, NULL, NULL, NULL, &tv);
01223 #endif
01224   }
01225   tor_mutex_acquire(_thread_test_start1);
01226   tor_mutex_release(_thread_test_start1);
01227   tor_mutex_acquire(_thread_test_start2);
01228   tor_mutex_release(_thread_test_start2);
01229 
01230   tor_mutex_free(_thread_test_mutex);
01231 
01232   if (timedout) {
01233     printf("\nTimed out: %d %d", t1_count, t2_count);
01234     test_assert(strmap_get(_thread_test_strmap, "thread 1"));
01235     test_assert(strmap_get(_thread_test_strmap, "thread 2"));
01236     test_assert(!timedout);
01237   }
01238 
01239   /* different thread IDs. */
01240   test_assert(strcmp(strmap_get(_thread_test_strmap, "thread 1"),
01241                      strmap_get(_thread_test_strmap, "thread 2")));
01242   test_assert(!strcmp(strmap_get(_thread_test_strmap, "thread 1"),
01243                       strmap_get(_thread_test_strmap, "last to run")) ||
01244               !strcmp(strmap_get(_thread_test_strmap, "thread 2"),
01245                       strmap_get(_thread_test_strmap, "last to run")));
01246 
01247  done:
01248   tor_free(s1);
01249   tor_free(s2);
01250   tor_free(_thread1_name);
01251   tor_free(_thread2_name);
01252   if (_thread_test_strmap)
01253     strmap_free(_thread_test_strmap, NULL);
01254   if (_thread_test_start1)
01255     tor_mutex_free(_thread_test_start1);
01256   if (_thread_test_start2)
01257     tor_mutex_free(_thread_test_start2);
01258 }
01259 
01261 static void
01262 test_util_gzip(void)
01263 {
01264   char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
01265   const char *ccp2;
01266   size_t len1, len2;
01267   tor_zlib_state_t *state = NULL;
01268 
01269   buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
01270   test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
01271   if (is_gzip_supported()) {
01272     test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
01273                                    GZIP_METHOD));
01274     test_assert(buf2);
01275     test_assert(len1 < strlen(buf1));
01276     test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
01277 
01278     test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
01279                                      GZIP_METHOD, 1, LOG_INFO));
01280     test_assert(buf3);
01281     test_eq(strlen(buf1) + 1, len2);
01282     test_streq(buf1, buf3);
01283 
01284     tor_free(buf2);
01285     tor_free(buf3);
01286   }
01287 
01288   test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
01289                                  ZLIB_METHOD));
01290   test_assert(buf2);
01291   test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
01292 
01293   test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
01294                                    ZLIB_METHOD, 1, LOG_INFO));
01295   test_assert(buf3);
01296   test_eq(strlen(buf1) + 1, len2);
01297   test_streq(buf1, buf3);
01298 
01299   /* Check whether we can uncompress concatenated, compressed strings. */
01300   tor_free(buf3);
01301   buf2 = tor_realloc(buf2, len1*2);
01302   memcpy(buf2+len1, buf2, len1);
01303   test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
01304                                    ZLIB_METHOD, 1, LOG_INFO));
01305   test_eq((strlen(buf1)+1)*2, len2);
01306   test_memeq(buf3,
01307              "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
01308              "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
01309              (strlen(buf1)+1)*2);
01310 
01311   tor_free(buf1);
01312   tor_free(buf2);
01313   tor_free(buf3);
01314 
01315   /* Check whether we can uncompress partial strings. */
01316   buf1 =
01317     tor_strdup("String with low redundancy that won't be compressed much.");
01318   test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
01319                                  ZLIB_METHOD));
01320   tt_assert(len1>16);
01321   /* when we allow an incomplete string, we should succeed.*/
01322   tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
01323                                   ZLIB_METHOD, 0, LOG_INFO));
01324   tt_assert(len2 > 5);
01325   buf3[len2]='\0';
01326   tt_assert(!strcmpstart(buf1, buf3));
01327 
01328   /* when we demand a complete string, this must fail. */
01329   tor_free(buf3);
01330   tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
01331                                  ZLIB_METHOD, 1, LOG_INFO));
01332   tt_assert(!buf3);
01333 
01334   /* Now, try streaming compression. */
01335   tor_free(buf1);
01336   tor_free(buf2);
01337   tor_free(buf3);
01338   state = tor_zlib_new(1, ZLIB_METHOD);
01339   tt_assert(state);
01340   cp1 = buf1 = tor_malloc(1024);
01341   len1 = 1024;
01342   ccp2 = "ABCDEFGHIJABCDEFGHIJ";
01343   len2 = 21;
01344   test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
01345               == TOR_ZLIB_OK);
01346   test_eq(0, len2); /* Make sure we compressed it all. */
01347   test_assert(cp1 > buf1);
01348 
01349   len2 = 0;
01350   cp2 = cp1;
01351   test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
01352               == TOR_ZLIB_DONE);
01353   test_eq(0, len2);
01354   test_assert(cp1 > cp2); /* Make sure we really added something. */
01355 
01356   tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
01357                                   ZLIB_METHOD, 1, LOG_WARN));
01358   test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
01359   test_eq(21, len2);
01360 
01361  done:
01362   if (state)
01363     tor_zlib_free(state);
01364   tor_free(buf2);
01365   tor_free(buf3);
01366   tor_free(buf1);
01367 }
01368 
01370 static void
01371 test_util_mmap(void)
01372 {
01373   char *fname1 = tor_strdup(get_fname("mapped_1"));
01374   char *fname2 = tor_strdup(get_fname("mapped_2"));
01375   char *fname3 = tor_strdup(get_fname("mapped_3"));
01376   const size_t buflen = 17000;
01377   char *buf = tor_malloc(17000);
01378   tor_mmap_t *mapping = NULL;
01379 
01380   crypto_rand(buf, buflen);
01381 
01382   mapping = tor_mmap_file(fname1);
01383   test_assert(! mapping);
01384 
01385   write_str_to_file(fname1, "Short file.", 1);
01386 
01387   mapping = tor_mmap_file(fname1);
01388   test_assert(mapping);
01389   test_eq(mapping->size, strlen("Short file."));
01390   test_streq(mapping->data, "Short file.");
01391 #ifdef _WIN32
01392   tor_munmap_file(mapping);
01393   mapping = NULL;
01394   test_assert(unlink(fname1) == 0);
01395 #else
01396   /* make sure we can unlink. */
01397   test_assert(unlink(fname1) == 0);
01398   test_streq(mapping->data, "Short file.");
01399   tor_munmap_file(mapping);
01400   mapping = NULL;
01401 #endif
01402 
01403   /* Now a zero-length file. */
01404   write_str_to_file(fname1, "", 1);
01405   mapping = tor_mmap_file(fname1);
01406   test_eq(mapping, NULL);
01407   test_eq(ERANGE, errno);
01408   unlink(fname1);
01409 
01410   /* Make sure that we fail to map a no-longer-existent file. */
01411   mapping = tor_mmap_file(fname1);
01412   test_assert(! mapping);
01413 
01414   /* Now try a big file that stretches across a few pages and isn't aligned */
01415   write_bytes_to_file(fname2, buf, buflen, 1);
01416   mapping = tor_mmap_file(fname2);
01417   test_assert(mapping);
01418   test_eq(mapping->size, buflen);
01419   test_memeq(mapping->data, buf, buflen);
01420   tor_munmap_file(mapping);
01421   mapping = NULL;
01422 
01423   /* Now try a big aligned file. */
01424   write_bytes_to_file(fname3, buf, 16384, 1);
01425   mapping = tor_mmap_file(fname3);
01426   test_assert(mapping);
01427   test_eq(mapping->size, 16384);
01428   test_memeq(mapping->data, buf, 16384);
01429   tor_munmap_file(mapping);
01430   mapping = NULL;
01431 
01432  done:
01433   unlink(fname1);
01434   unlink(fname2);
01435   unlink(fname3);
01436 
01437   tor_free(fname1);
01438   tor_free(fname2);
01439   tor_free(fname3);
01440   tor_free(buf);
01441 
01442   if (mapping)
01443     tor_munmap_file(mapping);
01444 }
01445 
01447 static void
01448 test_util_control_formats(void)
01449 {
01450   char *out = NULL;
01451   const char *inp =
01452     "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
01453   size_t sz;
01454 
01455   sz = read_escaped_data(inp, strlen(inp), &out);
01456   test_streq(out,
01457              ".This is a test\nof the emergency \n.system.\n\rZ.\n");
01458   test_eq(sz, strlen(out));
01459 
01460  done:
01461   tor_free(out);
01462 }
01463 
01464 static void
01465 test_util_sscanf(void)
01466 {
01467   unsigned u1, u2, u3;
01468   char s1[20], s2[10], s3[10], ch;
01469   int r;
01470 
01471   /* Simple tests (malformed patterns, literal matching, ...) */
01472   test_eq(-1, tor_sscanf("123", "%i", &r)); /* %i is not supported */
01473   test_eq(-1, tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
01474   test_eq(-1, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
01475   test_eq(-1, tor_sscanf("prettylongstring", "%999999s", s1));
01476 #if 0
01477   /* GCC thinks these two are illegal. */
01478   test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
01479   test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
01480 #endif
01481   /* No '%'-strings: always "success" */
01482   test_eq(0, tor_sscanf("hello world", "hello world"));
01483   test_eq(0, tor_sscanf("hello world", "good bye"));
01484   /* Excess data */
01485   test_eq(0, tor_sscanf("hello 3", "%u", &u1));  /* have to match the start */
01486   test_eq(0, tor_sscanf(" 3 hello", "%u", &u1));
01487   test_eq(0, tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
01488   test_eq(1, tor_sscanf("3 hello", "%u", &u1));  /* but trailing is alright */
01489 
01490   /* Numbers (ie. %u) */
01491   test_eq(0, tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
01492   test_eq(1, tor_sscanf("12345", "%u", &u1));
01493   test_eq(12345u, u1);
01494   test_eq(1, tor_sscanf("12346 ", "%u", &u1));
01495   test_eq(12346u, u1);
01496   test_eq(0, tor_sscanf(" 12347", "%u", &u1));
01497   test_eq(1, tor_sscanf(" 12348", " %u", &u1));
01498   test_eq(12348u, u1);
01499   test_eq(1, tor_sscanf("0", "%u", &u1));
01500   test_eq(0u, u1);
01501   test_eq(1, tor_sscanf("0000", "%u", &u2));
01502   test_eq(0u, u2);
01503   test_eq(0, tor_sscanf("", "%u", &u1)); /* absent number */
01504   test_eq(0, tor_sscanf("A", "%u", &u1)); /* bogus number */
01505   test_eq(0, tor_sscanf("-1", "%u", &u1)); /* negative number */
01506   test_eq(1, tor_sscanf("4294967295", "%u", &u1)); /* UINT32_MAX should work */
01507   test_eq(4294967295u, u1);
01508   test_eq(0, tor_sscanf("4294967296", "%u", &u1)); /* But not at 32 bits */
01509   test_eq(1, tor_sscanf("4294967296", "%9u", &u1)); /* but parsing only 9... */
01510   test_eq(429496729u, u1);
01511 
01512   /* Numbers with size (eg. %2u) */
01513   test_eq(0, tor_sscanf("-1", "%2u", &u1));
01514   test_eq(2, tor_sscanf("123456", "%2u%u", &u1, &u2));
01515   test_eq(12u, u1);
01516   test_eq(3456u, u2);
01517   test_eq(1, tor_sscanf("123456", "%8u", &u1));
01518   test_eq(123456u, u1);
01519   test_eq(1, tor_sscanf("123457  ", "%8u", &u1));
01520   test_eq(123457u, u1);
01521   test_eq(0, tor_sscanf("  123456", "%8u", &u1));
01522   test_eq(3, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
01523   test_eq(12u, u1);
01524   test_eq(3u, u2);
01525   test_eq(456u, u3);
01526   test_eq(3, tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
01527   test_eq(67u, u1);
01528   test_eq(8u, u2);
01529   test_eq(99u, u3);
01530   /* %u does not match space.*/
01531   test_eq(2, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
01532   test_eq(12u, u1);
01533   test_eq(3u, u2);
01534   /* %u does not match negative numbers. */
01535   test_eq(2, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
01536   test_eq(67u, u1);
01537   test_eq(8u, u2);
01538   /* Arbitrary amounts of 0-padding are okay */
01539   test_eq(3, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
01540                         &u1, &u2, &u3));
01541   test_eq(12u, u1);
01542   test_eq(3u, u2);
01543   test_eq(99u, u3);
01544 
01545   /* Hex (ie. %x) */
01546   test_eq(3, tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
01547   test_eq(0x1234, u1);
01548   test_eq(0x2ABCDEF, u2);
01549   test_eq(0xFF, u3);
01550   /* Width works on %x */
01551   test_eq(3, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
01552   test_eq(0xf00d, u1);
01553   test_eq(0xcafe, u2);
01554   test_eq(444, u3);
01555 
01556   /* Literal '%' (ie. '%%') */
01557   test_eq(1, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
01558   test_eq(99, u1);
01559   test_eq(0, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
01560   test_eq(1, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
01561   test_eq(2, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
01562   test_eq(99, u1);
01563   test_streq(s1, "fresh");
01564   test_eq(1, tor_sscanf("% boo", "%% %3s", s1));
01565   test_streq("boo", s1);
01566 
01567   /* Strings (ie. %s) */
01568   test_eq(2, tor_sscanf("hello", "%3s%7s", s1, s2));
01569   test_streq(s1, "hel");
01570   test_streq(s2, "lo");
01571   test_eq(2, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
01572   test_streq(s3, "WD");
01573   test_eq(40, u1);
01574   test_eq(2, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
01575   test_streq(s3, "WD4");
01576   test_eq(0, u1);
01577   test_eq(2, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
01578   test_eq(76, u1);
01579   test_streq(s1, "trombones");
01580   test_eq(1, tor_sscanf("prettylongstring", "%999s", s1));
01581   test_streq(s1, "prettylongstring");
01582   /* %s doesn't eat spaces */
01583   test_eq(2, tor_sscanf("hello world", "%9s %9s", s1, s2));
01584   test_streq(s1, "hello");
01585   test_streq(s2, "world");
01586   test_eq(2, tor_sscanf("bye   world?", "%9s %9s", s1, s2));
01587   test_streq(s1, "bye");
01588   test_streq(s2, "");
01589   test_eq(3, tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
01590   test_streq(s1, "hi");
01591   test_streq(s2, "");
01592   test_streq(s3, "");
01593 
01594   test_eq(3, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
01595   test_eq(4, tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
01596   test_eq(' ', ch);
01597 
01598  done:
01599   ;
01600 }
01601 
01602 static void
01603 test_util_path_is_relative(void)
01604 {
01605   /* OS-independent tests */
01606   test_eq(1, path_is_relative(""));
01607   test_eq(1, path_is_relative("dir"));
01608   test_eq(1, path_is_relative("dir/"));
01609   test_eq(1, path_is_relative("./dir"));
01610   test_eq(1, path_is_relative("../dir"));
01611 
01612   test_eq(0, path_is_relative("/"));
01613   test_eq(0, path_is_relative("/dir"));
01614   test_eq(0, path_is_relative("/dir/"));
01615 
01616   /* Windows */
01617 #ifdef _WIN32
01618   /* I don't have Windows so I can't test this, hence the "#ifdef
01619      0". These are tests that look useful, so please try to get them
01620      running and uncomment if it all works as it should */
01621   test_eq(1, path_is_relative("dir"));
01622   test_eq(1, path_is_relative("dir\\"));
01623   test_eq(1, path_is_relative("dir\\a:"));
01624   test_eq(1, path_is_relative("dir\\a:\\"));
01625   test_eq(1, path_is_relative("http:\\dir"));
01626 
01627   test_eq(0, path_is_relative("\\dir"));
01628   test_eq(0, path_is_relative("a:\\dir"));
01629   test_eq(0, path_is_relative("z:\\dir"));
01630 #endif
01631 
01632  done:
01633   ;
01634 }
01635 
01637 static void
01638 test_util_mempool(void)
01639 {
01640   mp_pool_t *pool = NULL;
01641   smartlist_t *allocated = NULL;
01642   int i;
01643 
01644   pool = mp_pool_new(1, 100);
01645   test_assert(pool);
01646   test_assert(pool->new_chunk_capacity >= 100);
01647   test_assert(pool->item_alloc_size >= sizeof(void*)+1);
01648   mp_pool_destroy(pool);
01649   pool = NULL;
01650 
01651   pool = mp_pool_new(241, 2500);
01652   test_assert(pool);
01653   test_assert(pool->new_chunk_capacity >= 10);
01654   test_assert(pool->item_alloc_size >= sizeof(void*)+241);
01655   test_eq(pool->item_alloc_size & 0x03, 0);
01656   test_assert(pool->new_chunk_capacity < 60);
01657 
01658   allocated = smartlist_new();
01659   for (i = 0; i < 20000; ++i) {
01660     if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) {
01661       void *m = mp_pool_get(pool);
01662       memset(m, 0x09, 241);
01663       smartlist_add(allocated, m);
01664       //printf("%d: %p\n", i, m);
01665       //mp_pool_assert_ok(pool);
01666     } else {
01667       int idx = crypto_rand_int(smartlist_len(allocated));
01668       void *m = smartlist_get(allocated, idx);
01669       //printf("%d: free %p\n", i, m);
01670       smartlist_del(allocated, idx);
01671       mp_pool_release(m);
01672       //mp_pool_assert_ok(pool);
01673     }
01674     if (crypto_rand_int(777)==0)
01675       mp_pool_clean(pool, 1, 1);
01676 
01677     if (i % 777)
01678       mp_pool_assert_ok(pool);
01679   }
01680 
01681  done:
01682   if (allocated) {
01683     SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m));
01684     mp_pool_assert_ok(pool);
01685     mp_pool_clean(pool, 0, 0);
01686     mp_pool_assert_ok(pool);
01687     smartlist_free(allocated);
01688   }
01689 
01690   if (pool)
01691     mp_pool_destroy(pool);
01692 }
01693 
01695 static void
01696 test_util_memarea(void)
01697 {
01698   memarea_t *area = memarea_new();
01699   char *p1, *p2, *p3, *p1_orig;
01700   void *malloced_ptr = NULL;
01701   int i;
01702 
01703   test_assert(area);
01704 
01705   p1_orig = p1 = memarea_alloc(area,64);
01706   p2 = memarea_alloc_zero(area,52);
01707   p3 = memarea_alloc(area,11);
01708 
01709   test_assert(memarea_owns_ptr(area, p1));
01710   test_assert(memarea_owns_ptr(area, p2));
01711   test_assert(memarea_owns_ptr(area, p3));
01712   /* Make sure we left enough space. */
01713   test_assert(p1+64 <= p2);
01714   test_assert(p2+52 <= p3);
01715   /* Make sure we aligned. */
01716   test_eq(((uintptr_t)p1) % sizeof(void*), 0);
01717   test_eq(((uintptr_t)p2) % sizeof(void*), 0);
01718   test_eq(((uintptr_t)p3) % sizeof(void*), 0);
01719   test_assert(!memarea_owns_ptr(area, p3+8192));
01720   test_assert(!memarea_owns_ptr(area, p3+30));
01721   test_assert(tor_mem_is_zero(p2, 52));
01722   /* Make sure we don't overalign. */
01723   p1 = memarea_alloc(area, 1);
01724   p2 = memarea_alloc(area, 1);
01725   test_eq(p1+sizeof(void*), p2);
01726   {
01727     malloced_ptr = tor_malloc(64);
01728     test_assert(!memarea_owns_ptr(area, malloced_ptr));
01729     tor_free(malloced_ptr);
01730   }
01731 
01732   /* memarea_memdup */
01733   {
01734     malloced_ptr = tor_malloc(64);
01735     crypto_rand((char*)malloced_ptr, 64);
01736     p1 = memarea_memdup(area, malloced_ptr, 64);
01737     test_assert(p1 != malloced_ptr);
01738     test_memeq(p1, malloced_ptr, 64);
01739     tor_free(malloced_ptr);
01740   }
01741 
01742   /* memarea_strdup. */
01743   p1 = memarea_strdup(area,"");
01744   p2 = memarea_strdup(area, "abcd");
01745   test_assert(p1);
01746   test_assert(p2);
01747   test_streq(p1, "");
01748   test_streq(p2, "abcd");
01749 
01750   /* memarea_strndup. */
01751   {
01752     const char *s = "Ad ogni porta batte la morte e grida: il nome!";
01753     /* (From Turandot, act 3.) */
01754     size_t len = strlen(s);
01755     p1 = memarea_strndup(area, s, 1000);
01756     p2 = memarea_strndup(area, s, 10);
01757     test_streq(p1, s);
01758     test_assert(p2 >= p1 + len + 1);
01759     test_memeq(s, p2, 10);
01760     test_eq(p2[10], '\0');
01761     p3 = memarea_strndup(area, s, len);
01762     test_streq(p3, s);
01763     p3 = memarea_strndup(area, s, len-1);
01764     test_memeq(s, p3, len-1);
01765     test_eq(p3[len-1], '\0');
01766   }
01767 
01768   memarea_clear(area);
01769   p1 = memarea_alloc(area, 1);
01770   test_eq(p1, p1_orig);
01771   memarea_clear(area);
01772 
01773   /* Check for running over an area's size. */
01774   for (i = 0; i < 512; ++i) {
01775     p1 = memarea_alloc(area, crypto_rand_int(5)+1);
01776     test_assert(memarea_owns_ptr(area, p1));
01777   }
01778   memarea_assert_ok(area);
01779   /* Make sure we can allocate a too-big object. */
01780   p1 = memarea_alloc_zero(area, 9000);
01781   p2 = memarea_alloc_zero(area, 16);
01782   test_assert(memarea_owns_ptr(area, p1));
01783   test_assert(memarea_owns_ptr(area, p2));
01784 
01785  done:
01786   memarea_drop_all(area);
01787   tor_free(malloced_ptr);
01788 }
01789 
01792 static void
01793 test_util_datadir(void)
01794 {
01795   char buf[1024];
01796   char *f = NULL;
01797   char *temp_dir = NULL;
01798 
01799   temp_dir = get_datadir_fname(NULL);
01800   f = get_datadir_fname("state");
01801   tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
01802   test_streq(f, buf);
01803   tor_free(f);
01804   f = get_datadir_fname2("cache", "thingy");
01805   tor_snprintf(buf, sizeof(buf),
01806                "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
01807   test_streq(f, buf);
01808   tor_free(f);
01809   f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
01810   tor_snprintf(buf, sizeof(buf),
01811                "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
01812   test_streq(f, buf);
01813   tor_free(f);
01814   f = get_datadir_fname_suffix("cache", ".foo");
01815   tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
01816                temp_dir);
01817   test_streq(f, buf);
01818 
01819  done:
01820   tor_free(f);
01821   tor_free(temp_dir);
01822 }
01823 
01824 static void
01825 test_util_strtok(void)
01826 {
01827   char buf[128];
01828   char buf2[128];
01829   int i;
01830   char *cp1, *cp2;
01831 
01832   for (i = 0; i < 3; i++) {
01833     const char *pad1="", *pad2="";
01834     switch (i) {
01835     case 0:
01836       break;
01837     case 1:
01838       pad1 = " ";
01839       pad2 = "!";
01840       break;
01841     case 2:
01842       pad1 = "  ";
01843       pad2 = ";!";
01844       break;
01845     }
01846     tor_snprintf(buf, sizeof(buf), "%s", pad1);
01847     tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
01848     test_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1));
01849     test_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2));
01850 
01851     tor_snprintf(buf, sizeof(buf),
01852                  "%sGraved on the dark  in gestures of descent%s", pad1, pad1);
01853     tor_snprintf(buf2, sizeof(buf2),
01854                 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
01855     /*  -- "Year's End", Richard Wilbur */
01856 
01857     test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1));
01858     test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2));
01859 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
01860 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
01861     test_streq("on", S1());
01862     test_streq("the", S1());
01863     test_streq("dark", S1());
01864     test_streq("seemed", S2());
01865     test_streq("their", S2());
01866     test_streq("own", S2());
01867     test_streq("in", S1());
01868     test_streq("gestures", S1());
01869     test_streq("of", S1());
01870     test_streq("most", S2());
01871     test_streq("perfect", S2());
01872     test_streq("descent", S1());
01873     test_streq("monument", S2());
01874     test_eq_ptr(NULL, S1());
01875     test_eq_ptr(NULL, S2());
01876   }
01877 
01878   buf[0] = 0;
01879   test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
01880   test_eq_ptr(NULL, tor_strtok_r_impl(buf, "!", &cp1));
01881 
01882   strlcpy(buf, "Howdy!", sizeof(buf));
01883   test_streq("Howdy", tor_strtok_r_impl(buf, "!", &cp1));
01884   test_eq_ptr(NULL, tor_strtok_r_impl(NULL, "!", &cp1));
01885 
01886   strlcpy(buf, " ", sizeof(buf));
01887   test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
01888   strlcpy(buf, "  ", sizeof(buf));
01889   test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
01890 
01891   strlcpy(buf, "something  ", sizeof(buf));
01892   test_streq("something", tor_strtok_r_impl(buf, " ", &cp1));
01893   test_eq_ptr(NULL, tor_strtok_r_impl(NULL, ";", &cp1));
01894  done:
01895   ;
01896 }
01897 
01898 static void
01899 test_util_find_str_at_start_of_line(void *ptr)
01900 {
01901   const char *long_string =
01902     "howdy world. how are you? i hope it's fine.\n"
01903     "hello kitty\n"
01904     "third line";
01905   char *line2 = strchr(long_string,'\n')+1;
01906   char *line3 = strchr(line2,'\n')+1;
01907   const char *short_string = "hello kitty\n"
01908     "second line\n";
01909   char *short_line2 = strchr(short_string,'\n')+1;
01910 
01911   (void)ptr;
01912 
01913   test_eq_ptr(long_string, find_str_at_start_of_line(long_string, ""));
01914   test_eq_ptr(NULL, find_str_at_start_of_line(short_string, "nonsense"));
01915   test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "nonsense"));
01916   test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "\n"));
01917   test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "how "));
01918   test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "kitty"));
01919   test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "h"));
01920   test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "how"));
01921   test_eq_ptr(line2, find_str_at_start_of_line(long_string, "he"));
01922   test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hell"));
01923   test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello k"));
01924   test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\n"));
01925   test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\nt"));
01926   test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third"));
01927   test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third line"));
01928   test_eq_ptr(NULL,  find_str_at_start_of_line(long_string, "third line\n"));
01929   test_eq_ptr(short_line2, find_str_at_start_of_line(short_string,
01930                                                      "second line\n"));
01931  done:
01932   ;
01933 }
01934 
01935 static void
01936 test_util_string_is_C_identifier(void *ptr)
01937 {
01938   (void)ptr;
01939 
01940   test_eq(1, string_is_C_identifier("string_is_C_identifier"));
01941   test_eq(1, string_is_C_identifier("_string_is_C_identifier"));
01942   test_eq(1, string_is_C_identifier("_"));
01943   test_eq(1, string_is_C_identifier("i"));
01944   test_eq(1, string_is_C_identifier("_____"));
01945   test_eq(1, string_is_C_identifier("__00__"));
01946   test_eq(1, string_is_C_identifier("__init__"));
01947   test_eq(1, string_is_C_identifier("_0"));
01948   test_eq(1, string_is_C_identifier("_0string_is_C_identifier"));
01949   test_eq(1, string_is_C_identifier("_0"));
01950 
01951   test_eq(0, string_is_C_identifier("0_string_is_C_identifier"));
01952   test_eq(0, string_is_C_identifier("0"));
01953   test_eq(0, string_is_C_identifier(""));
01954   test_eq(0, string_is_C_identifier(";"));
01955   test_eq(0, string_is_C_identifier("i;"));
01956   test_eq(0, string_is_C_identifier("_;"));
01957   test_eq(0, string_is_C_identifier("í"));
01958   test_eq(0, string_is_C_identifier("ñ"));
01959 
01960  done:
01961   ;
01962 }
01963 
01964 static void
01965 test_util_asprintf(void *ptr)
01966 {
01967 #define LOREMIPSUM                                              \
01968   "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
01969   char *cp=NULL, *cp2=NULL;
01970   int r;
01971   (void)ptr;
01972 
01973   /* simple string */
01974   r = tor_asprintf(&cp, "simple string 100%% safe");
01975   test_assert(cp);
01976   test_streq("simple string 100% safe", cp);
01977   test_eq(strlen(cp), r);
01978 
01979   /* empty string */
01980   r = tor_asprintf(&cp, "%s", "");
01981   test_assert(cp);
01982   test_streq("", cp);
01983   test_eq(strlen(cp), r);
01984 
01985   /* numbers (%i) */
01986   r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
01987   test_assert(cp);
01988   test_streq("I like numbers--1, 2, etc.", cp);
01989   test_eq(strlen(cp), r);
01990 
01991   /* numbers (%d) */
01992   r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
01993   test_assert(cp2);
01994   test_eq(strlen(cp2), r);
01995   test_streq("First=101, Second=202", cp2);
01996   test_assert(cp != cp2);
01997   tor_free(cp);
01998   tor_free(cp2);
01999 
02000   /* Glass-box test: a string exactly 128 characters long. */
02001   r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
02002   test_assert(cp);
02003   test_eq(128, r);
02004   test_assert(cp[128] == '\0');
02005   test_streq("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM, cp);
02006   tor_free(cp);
02007 
02008   /* String longer than 128 characters */
02009   r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
02010                    LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
02011   test_assert(cp);
02012   test_eq(strlen(cp), r);
02013   test_streq("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM, cp);
02014 
02015  done:
02016   tor_free(cp);
02017   tor_free(cp2);
02018 }
02019 
02020 static void
02021 test_util_listdir(void *ptr)
02022 {
02023   smartlist_t *dir_contents = NULL;
02024   char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
02025   int r;
02026   (void)ptr;
02027 
02028   fname1 = tor_strdup(get_fname("hopscotch"));
02029   fname2 = tor_strdup(get_fname("mumblety-peg"));
02030   fname3 = tor_strdup(get_fname(".hidden-file"));
02031   dir1   = tor_strdup(get_fname("some-directory"));
02032   dirname = tor_strdup(get_fname(NULL));
02033 
02034   test_eq(0, write_str_to_file(fname1, "X\n", 0));
02035   test_eq(0, write_str_to_file(fname2, "Y\n", 0));
02036   test_eq(0, write_str_to_file(fname3, "Z\n", 0));
02037 #ifdef _WIN32
02038   r = mkdir(dir1);
02039 #else
02040   r = mkdir(dir1, 0700);
02041 #endif
02042   if (r) {
02043     fprintf(stderr, "Can't create directory %s:", dir1);
02044     perror("");
02045     exit(1);
02046   }
02047 
02048   dir_contents = tor_listdir(dirname);
02049   test_assert(dir_contents);
02050   /* make sure that each filename is listed. */
02051   test_assert(smartlist_string_isin_case(dir_contents, "hopscotch"));
02052   test_assert(smartlist_string_isin_case(dir_contents, "mumblety-peg"));
02053   test_assert(smartlist_string_isin_case(dir_contents, ".hidden-file"));
02054   test_assert(smartlist_string_isin_case(dir_contents, "some-directory"));
02055 
02056   test_assert(!smartlist_string_isin(dir_contents, "."));
02057   test_assert(!smartlist_string_isin(dir_contents, ".."));
02058 
02059  done:
02060   tor_free(fname1);
02061   tor_free(fname2);
02062   tor_free(dirname);
02063   if (dir_contents) {
02064     SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
02065     smartlist_free(dir_contents);
02066   }
02067 }
02068 
02069 static void
02070 test_util_parent_dir(void *ptr)
02071 {
02072   char *cp;
02073   (void)ptr;
02074 
02075 #define T(output,expect_ok,input)               \
02076   do {                                          \
02077     int ok;                                     \
02078     cp = tor_strdup(input);                     \
02079     ok = get_parent_directory(cp);              \
02080     tt_int_op(expect_ok, ==, ok);               \
02081     if (ok==0)                                  \
02082       tt_str_op(output, ==, cp);                \
02083     tor_free(cp);                               \
02084   } while (0);
02085 
02086   T("/home/wombat", 0, "/home/wombat/knish");
02087   T("/home/wombat", 0, "/home/wombat/knish/");
02088   T("/home/wombat", 0, "/home/wombat/knish///");
02089   T("./home/wombat", 0, "./home/wombat/knish/");
02090   T("/", 0, "/home");
02091   T("/", 0, "/home//");
02092   T(".", 0, "./wombat");
02093   T(".", 0, "./wombat/");
02094   T(".", 0, "./wombat//");
02095   T("wombat", 0, "wombat/foo");
02096   T("wombat/..", 0, "wombat/../foo");
02097   T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
02098   T("wombat/.", 0, "wombat/./foo");
02099   T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
02100   T("wombat", 0, "wombat/..//");
02101   T("wombat", 0, "wombat/foo/");
02102   T("wombat", 0, "wombat/.foo");
02103   T("wombat", 0, "wombat/.foo/");
02104 
02105   T("wombat", -1, "");
02106   T("w", -1, "");
02107   T("wombat", 0, "wombat/knish");
02108 
02109   T("/", 0, "/");
02110   T("/", 0, "////");
02111 
02112  done:
02113   tor_free(cp);
02114 }
02115 
02116 #ifdef _WIN32
02117 static void
02118 test_util_load_win_lib(void *ptr)
02119 {
02120   HANDLE h = load_windows_system_library(_T("advapi32.dll"));
02121   (void) ptr;
02122 
02123   tt_assert(h);
02124  done:
02125   if (h)
02126     CloseHandle(h);
02127 }
02128 #endif
02129 
02130 static void
02131 clear_hex_errno(char *hex_errno)
02132 {
02133   memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
02134 }
02135 
02136 static void
02137 test_util_exit_status(void *ptr)
02138 {
02139   /* Leave an extra byte for a \0 so we can do string comparison */
02140   char hex_errno[HEX_ERRNO_SIZE + 1];
02141   int n;
02142 
02143   (void)ptr;
02144 
02145   clear_hex_errno(hex_errno);
02146   n = format_helper_exit_status(0, 0, hex_errno);
02147   test_streq("0/0\n", hex_errno);
02148   test_eq(n, strlen(hex_errno));
02149 
02150   clear_hex_errno(hex_errno);
02151   n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
02152   test_streq("0/7FFFFFFF\n", hex_errno);
02153   test_eq(n, strlen(hex_errno));
02154 
02155   clear_hex_errno(hex_errno);
02156   n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
02157   test_streq("FF/-80000000\n", hex_errno);
02158   test_eq(n, strlen(hex_errno));
02159 
02160   clear_hex_errno(hex_errno);
02161   n = format_helper_exit_status(0x7F, 0, hex_errno);
02162   test_streq("7F/0\n", hex_errno);
02163   test_eq(n, strlen(hex_errno));
02164 
02165   clear_hex_errno(hex_errno);
02166   n = format_helper_exit_status(0x08, -0x242, hex_errno);
02167   test_streq("8/-242\n", hex_errno);
02168   test_eq(n, strlen(hex_errno));
02169 
02170  done:
02171   ;
02172 }
02173 
02174 #ifndef _WIN32
02175 
02177 static void
02178 test_util_fgets_eagain(void *ptr)
02179 {
02180   int test_pipe[2] = {-1, -1};
02181   int retval;
02182   ssize_t retlen;
02183   char *retptr;
02184   FILE *test_stream = NULL;
02185   char buf[10];
02186 
02187   (void)ptr;
02188 
02189   /* Set up a pipe to test on */
02190   retval = pipe(test_pipe);
02191   tt_int_op(retval, >=, 0);
02192 
02193   /* Set up the read-end to be non-blocking */
02194   retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
02195   tt_int_op(retval, >=, 0);
02196 
02197   /* Open it as a stdio stream */
02198   test_stream = fdopen(test_pipe[0], "r");
02199   tt_ptr_op(test_stream, !=, NULL);
02200 
02201   /* Send in a partial line */
02202   retlen = write(test_pipe[1], "A", 1);
02203   tt_int_op(retlen, ==, 1);
02204   retptr = fgets(buf, sizeof(buf), test_stream);
02205   tt_want(retptr == NULL);
02206   tt_int_op(errno, ==, EAGAIN);
02207 
02208   /* Send in the rest */
02209   retlen = write(test_pipe[1], "B\n", 2);
02210   tt_int_op(retlen, ==, 2);
02211   retptr = fgets(buf, sizeof(buf), test_stream);
02212   tt_ptr_op(retptr, ==, buf);
02213   tt_str_op(buf, ==, "AB\n");
02214 
02215   /* Send in a full line */
02216   retlen = write(test_pipe[1], "CD\n", 3);
02217   tt_int_op(retlen, ==, 3);
02218   retptr = fgets(buf, sizeof(buf), test_stream);
02219   tt_ptr_op(retptr, ==, buf);
02220   tt_str_op(buf, ==, "CD\n");
02221 
02222   /* Send in a partial line */
02223   retlen = write(test_pipe[1], "E", 1);
02224   tt_int_op(retlen, ==, 1);
02225   retptr = fgets(buf, sizeof(buf), test_stream);
02226   tt_ptr_op(retptr, ==, NULL);
02227   tt_int_op(errno, ==, EAGAIN);
02228 
02229   /* Send in the rest */
02230   retlen = write(test_pipe[1], "F\n", 2);
02231   tt_int_op(retlen, ==, 2);
02232   retptr = fgets(buf, sizeof(buf), test_stream);
02233   tt_ptr_op(retptr, ==, buf);
02234   tt_str_op(buf, ==, "EF\n");
02235 
02236   /* Send in a full line and close */
02237   retlen = write(test_pipe[1], "GH", 2);
02238   tt_int_op(retlen, ==, 2);
02239   retval = close(test_pipe[1]);
02240   test_pipe[1] = -1;
02241   tt_int_op(retval, ==, 0);
02242   retptr = fgets(buf, sizeof(buf), test_stream);
02243   tt_ptr_op(retptr, ==, buf);
02244   tt_str_op(buf, ==, "GH");
02245 
02246   /* Check for EOF */
02247   retptr = fgets(buf, sizeof(buf), test_stream);
02248   tt_ptr_op(retptr, ==, NULL);
02249   tt_int_op(feof(test_stream), >, 0);
02250 
02251  done:
02252   if (test_stream != NULL)
02253     fclose(test_stream);
02254   if (test_pipe[0] != -1)
02255     close(test_pipe[0]);
02256   if (test_pipe[1] != -1)
02257     close(test_pipe[1]);
02258 }
02259 #endif
02260 
02262 static void
02263 run_util_spawn_background(const char *argv[], const char *expected_out,
02264                           const char *expected_err, int expected_exit,
02265                           int expected_status)
02266 {
02267   int retval, exit_code;
02268   ssize_t pos;
02269   process_handle_t *process_handle=NULL;
02270   char stdout_buf[100], stderr_buf[100];
02271   int status;
02272 
02273   /* Start the program */
02274 #ifdef _WIN32
02275   status = tor_spawn_background(NULL, argv, NULL, &process_handle);
02276 #else
02277   status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
02278 #endif
02279 
02280   test_eq(expected_status, status);
02281   if (status == PROCESS_STATUS_ERROR)
02282     return;
02283 
02284   test_assert(process_handle != NULL);
02285   test_eq(expected_status, process_handle->status);
02286 
02287 #ifdef _WIN32
02288   test_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE);
02289   test_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE);
02290 #else
02291   test_assert(process_handle->stdout_pipe > 0);
02292   test_assert(process_handle->stderr_pipe > 0);
02293 #endif
02294 
02295   /* Check stdout */
02296   pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
02297                                          sizeof(stdout_buf) - 1);
02298   tt_assert(pos >= 0);
02299   stdout_buf[pos] = '\0';
02300   test_eq(strlen(expected_out), pos);
02301   test_streq(expected_out, stdout_buf);
02302 
02303   /* Check it terminated correctly */
02304   retval = tor_get_exit_code(process_handle, 1, &exit_code);
02305   test_eq(PROCESS_EXIT_EXITED, retval);
02306   test_eq(expected_exit, exit_code);
02307   // TODO: Make test-child exit with something other than 0
02308 
02309   /* Check stderr */
02310   pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
02311                                          sizeof(stderr_buf) - 1);
02312   test_assert(pos >= 0);
02313   stderr_buf[pos] = '\0';
02314   test_streq(expected_err, stderr_buf);
02315   test_eq(strlen(expected_err), pos);
02316 
02317  done:
02318   if (process_handle)
02319     tor_process_handle_destroy(process_handle, 1);
02320 }
02321 
02323 static void
02324 test_util_spawn_background_ok(void *ptr)
02325 {
02326 #ifdef _WIN32
02327   const char *argv[] = {"test-child.exe", "--test", NULL};
02328   const char *expected_out = "OUT\r\n--test\r\nSLEEPING\r\nDONE\r\n";
02329   const char *expected_err = "ERR\r\n";
02330 #else
02331   const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
02332   const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
02333   const char *expected_err = "ERR\n";
02334 #endif
02335 
02336   (void)ptr;
02337 
02338   run_util_spawn_background(argv, expected_out, expected_err, 0,
02339                             PROCESS_STATUS_RUNNING);
02340 }
02341 
02343 static void
02344 test_util_spawn_background_fail(void *ptr)
02345 {
02346 #ifndef BUILDDIR
02347 #define BUILDDIR "."
02348 #endif
02349   const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
02350   const char *expected_err = "";
02351   char expected_out[1024];
02352   char code[32];
02353 #ifdef _WIN32
02354   const int expected_status = PROCESS_STATUS_ERROR;
02355 #else
02356   /* TODO: Once we can signal failure to exec, set this to be
02357    * PROCESS_STATUS_ERROR */
02358   const int expected_status = PROCESS_STATUS_RUNNING;
02359 #endif
02360 
02361   (void)ptr;
02362 
02363   tor_snprintf(code, sizeof(code), "%x/%x",
02364     9 /* CHILD_STATE_FAILEXEC */ , ENOENT);
02365   tor_snprintf(expected_out, sizeof(expected_out),
02366     "ERR: Failed to spawn background process - code %s\n", code);
02367 
02368   run_util_spawn_background(argv, expected_out, expected_err, 255,
02369                             expected_status);
02370 }
02371 
02374 static void
02375 test_util_spawn_background_partial_read(void *ptr)
02376 {
02377   const int expected_exit = 0;
02378   const int expected_status = PROCESS_STATUS_RUNNING;
02379 
02380   int retval, exit_code;
02381   ssize_t pos = -1;
02382   process_handle_t *process_handle=NULL;
02383   int status;
02384   char stdout_buf[100], stderr_buf[100];
02385 #ifdef _WIN32
02386   const char *argv[] = {"test-child.exe", "--test", NULL};
02387   const char *expected_out[] = { "OUT\r\n--test\r\nSLEEPING\r\n",
02388                                  "DONE\r\n",
02389                                  NULL };
02390   const char *expected_err = "ERR\r\n";
02391 #else
02392   const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
02393   const char *expected_out[] = { "OUT\n--test\nSLEEPING\n",
02394                                  "DONE\n",
02395                                  NULL };
02396   const char *expected_err = "ERR\n";
02397   int eof = 0;
02398 #endif
02399   int expected_out_ctr;
02400   (void)ptr;
02401 
02402   /* Start the program */
02403 #ifdef _WIN32
02404   status = tor_spawn_background(NULL, argv, NULL, &process_handle);
02405 #else
02406   status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
02407 #endif
02408   test_eq(expected_status, status);
02409   test_assert(process_handle);
02410   test_eq(expected_status, process_handle->status);
02411 
02412   /* Check stdout */
02413   for (expected_out_ctr = 0; expected_out[expected_out_ctr] != NULL;) {
02414 #ifdef _WIN32
02415     pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
02416                               sizeof(stdout_buf) - 1, NULL);
02417 #else
02418     /* Check that we didn't read the end of file last time */
02419     test_assert(!eof);
02420     pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
02421                               sizeof(stdout_buf) - 1, NULL, &eof);
02422 #endif
02423     log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
02424 
02425     /* We would have blocked, keep on trying */
02426     if (0 == pos)
02427       continue;
02428 
02429     test_assert(pos > 0);
02430     stdout_buf[pos] = '\0';
02431     test_streq(expected_out[expected_out_ctr], stdout_buf);
02432     test_eq(strlen(expected_out[expected_out_ctr]), pos);
02433     expected_out_ctr++;
02434   }
02435 
02436   /* The process should have exited without writing more */
02437 #ifdef _WIN32
02438   pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
02439                             sizeof(stdout_buf) - 1,
02440                             process_handle);
02441   test_eq(0, pos);
02442 #else
02443   if (!eof) {
02444     /* We should have got all the data, but maybe not the EOF flag */
02445     pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
02446                               sizeof(stdout_buf) - 1,
02447                               process_handle, &eof);
02448     test_eq(0, pos);
02449     test_assert(eof);
02450   }
02451   /* Otherwise, we got the EOF on the last read */
02452 #endif
02453 
02454   /* Check it terminated correctly */
02455   retval = tor_get_exit_code(process_handle, 1, &exit_code);
02456   test_eq(PROCESS_EXIT_EXITED, retval);
02457   test_eq(expected_exit, exit_code);
02458 
02459   // TODO: Make test-child exit with something other than 0
02460 
02461   /* Check stderr */
02462   pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
02463                                          sizeof(stderr_buf) - 1);
02464   test_assert(pos >= 0);
02465   stderr_buf[pos] = '\0';
02466   test_streq(expected_err, stderr_buf);
02467   test_eq(strlen(expected_err), pos);
02468 
02469  done:
02470   tor_process_handle_destroy(process_handle, 1);
02471 }
02472 
02477 static void
02478 test_util_format_hex_number(void *ptr)
02479 {
02480   int i, len;
02481   char buf[HEX_ERRNO_SIZE + 1];
02482   const struct {
02483     const char *str;
02484     unsigned int x;
02485   } test_data[] = {
02486     {"0", 0},
02487     {"1", 1},
02488     {"273A", 0x273a},
02489     {"FFFF", 0xffff},
02490 #if UINT_MAX >= 0xffffffff
02491     {"31BC421D", 0x31bc421d},
02492     {"FFFFFFFF", 0xffffffff},
02493 #endif
02494     {NULL, 0}
02495   };
02496 
02497   (void)ptr;
02498 
02499   for (i = 0; test_data[i].str != NULL; ++i) {
02500     len = format_hex_number_for_helper_exit_status(test_data[i].x,
02501         buf, HEX_ERRNO_SIZE);
02502     test_neq(len, 0);
02503     buf[len] = '\0';
02504     test_streq(buf, test_data[i].str);
02505   }
02506 
02507  done:
02508   return;
02509 }
02510 
02514 static void
02515 test_util_join_win_cmdline(void *ptr)
02516 {
02517   /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
02518    * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
02519    * will try to only generate simple cases for the child process to parse;
02520    * i.e. we never embed quoted strings in arguments. */
02521 
02522   const char *argvs[][4] = {
02523     {"a", "bb", "CCC", NULL}, // Normal
02524     {NULL, NULL, NULL, NULL}, // Empty argument list
02525     {"", NULL, NULL, NULL}, // Empty argument
02526     {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
02527     {"a\tbc", "dd  dd", "E", NULL}, // Whitespace
02528     {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
02529     {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
02530     {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
02531     { NULL } // Terminator
02532   };
02533 
02534   const char *cmdlines[] = {
02535     "a bb CCC",
02536     "",
02537     "\"\"",
02538     "\\\"a b\\\"b CCC\\\"",
02539     "\"a\tbc\" \"dd  dd\" E",
02540     "a\\\\\\b \"de fg\" H",
02541     "a\\\\\\\"b \\c D\\",
02542     "\"a\\\\b c\" d E",
02543     NULL // Terminator
02544   };
02545 
02546   int i;
02547   char *joined_argv;
02548 
02549   (void)ptr;
02550 
02551   for (i=0; cmdlines[i]!=NULL; i++) {
02552     log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
02553     joined_argv = tor_join_win_cmdline(argvs[i]);
02554     test_streq(cmdlines[i], joined_argv);
02555     tor_free(joined_argv);
02556   }
02557 
02558  done:
02559   ;
02560 }
02561 
02562 #define MAX_SPLIT_LINE_COUNT 4
02563 struct split_lines_test_t {
02564   const char *orig_line; // Line to be split (may contain \0's)
02565   int orig_length; // Length of orig_line
02566   const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
02567 };
02568 
02572 static void
02573 test_util_split_lines(void *ptr)
02574 {
02575   /* Test cases. orig_line of last test case must be NULL.
02576    * The last element of split_line[i] must be NULL. */
02577   struct split_lines_test_t tests[] = {
02578     {"", 0, {NULL}},
02579     {"foo", 3, {"foo", NULL}},
02580     {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
02581     {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
02582     {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
02583     {"line 1\r\nline 2", 14, {"line 1", "line 2", NULL}},
02584     {"line 1\r\n\r\nline 2", 16, {"line 1", "line 2", NULL}},
02585     {"line 1\r\n\r\r\r\nline 2", 18, {"line 1", "line 2", NULL}},
02586     {"line 1\r\n\n\n\n\rline 2", 18, {"line 1", "line 2", NULL}},
02587     {"line 1\r\n\r\t\r\nline 3", 18, {"line 1", ".", "line 3", NULL}},
02588     {"\n\t\r\t\nline 3", 11, {".", ".", "line 3", NULL}},
02589     {NULL, 0, { NULL }}
02590   };
02591 
02592   int i, j;
02593   char *orig_line=NULL;
02594   smartlist_t *sl=NULL;
02595 
02596   (void)ptr;
02597 
02598   for (i=0; tests[i].orig_line; i++) {
02599     sl = smartlist_new();
02600     /* Allocate space for string and trailing NULL */
02601     orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
02602     tor_split_lines(sl, orig_line, tests[i].orig_length);
02603 
02604     j = 0;
02605     log_info(LD_GENERAL, "Splitting test %d of length %d",
02606              i, tests[i].orig_length);
02607     SMARTLIST_FOREACH(sl, const char *, line,
02608     {
02609       /* Check we have not got too many lines */
02610       test_assert(j < MAX_SPLIT_LINE_COUNT);
02611       /* Check that there actually should be a line here */
02612       test_assert(tests[i].split_line[j] != NULL);
02613       log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
02614                j, i, tests[i].split_line[j]);
02615       /* Check that the line is as expected */
02616       test_streq(line, tests[i].split_line[j]);
02617       j++;
02618     });
02619     /* Check that we didn't miss some lines */
02620     test_eq_ptr(NULL, tests[i].split_line[j]);
02621     tor_free(orig_line);
02622     smartlist_free(sl);
02623     sl = NULL;
02624   }
02625 
02626  done:
02627   tor_free(orig_line);
02628   smartlist_free(sl);
02629 }
02630 
02631 static void
02632 test_util_di_ops(void)
02633 {
02634 #define LT -1
02635 #define GT 1
02636 #define EQ 0
02637   const struct {
02638     const char *a; int want_sign; const char *b;
02639   } examples[] = {
02640     { "Foo", EQ, "Foo" },
02641     { "foo", GT, "bar", },
02642     { "foobar", EQ ,"foobar" },
02643     { "foobar", LT, "foobaw" },
02644     { "foobar", GT, "f00bar" },
02645     { "foobar", GT, "boobar" },
02646     { "", EQ, "" },
02647     { NULL, 0, NULL },
02648   };
02649 
02650   int i;
02651 
02652   for (i = 0; examples[i].a; ++i) {
02653     size_t len = strlen(examples[i].a);
02654     int eq1, eq2, neq1, neq2, cmp1, cmp2;
02655     test_eq(len, strlen(examples[i].b));
02656     /* We do all of the operations, with operands in both orders. */
02657     eq1 = tor_memeq(examples[i].a, examples[i].b, len);
02658     eq2 = tor_memeq(examples[i].b, examples[i].a, len);
02659     neq1 = tor_memneq(examples[i].a, examples[i].b, len);
02660     neq2 = tor_memneq(examples[i].b, examples[i].a, len);
02661     cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
02662     cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
02663 
02664     /* Check for correctness of cmp1 */
02665     if (cmp1 < 0 && examples[i].want_sign != LT)
02666       test_fail();
02667     else if (cmp1 > 0 && examples[i].want_sign != GT)
02668       test_fail();
02669     else if (cmp1 == 0 && examples[i].want_sign != EQ)
02670       test_fail();
02671 
02672     /* Check for consistency of everything else with cmp1 */
02673     test_eq(eq1, eq2);
02674     test_eq(neq1, neq2);
02675     test_eq(cmp1, -cmp2);
02676     test_eq(eq1, cmp1 == 0);
02677     test_eq(neq1, !eq1);
02678   }
02679 
02680  done:
02681   ;
02682 }
02683 
02687 static void
02688 test_util_n_bits_set(void *ptr)
02689 {
02690   (void)ptr;
02691   test_eq(0, n_bits_set_u8(0));
02692   test_eq(1, n_bits_set_u8(1));
02693   test_eq(3, n_bits_set_u8(7));
02694   test_eq(1, n_bits_set_u8(8));
02695   test_eq(2, n_bits_set_u8(129));
02696   test_eq(8, n_bits_set_u8(255));
02697  done:
02698   ;
02699 }
02700 
02704 static void
02705 test_util_eat_whitespace(void *ptr)
02706 {
02707   const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
02708   char str[80];
02709   size_t i;
02710 
02711   (void)ptr;
02712 
02713   /* Try one leading ws */
02714   strcpy(str, "fuubaar");
02715   for (i = 0; i < sizeof(ws); ++i) {
02716     str[0] = ws[i];
02717     test_eq_ptr(str + 1, eat_whitespace(str));
02718     test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str)));
02719     test_eq_ptr(str + 1, eat_whitespace_no_nl(str));
02720     test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str)));
02721   }
02722   str[0] = '\n';
02723   test_eq_ptr(str + 1, eat_whitespace(str));
02724   test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str)));
02725   test_eq_ptr(str,     eat_whitespace_no_nl(str));
02726   test_eq_ptr(str,     eat_whitespace_eos_no_nl(str, str + strlen(str)));
02727 
02728   /* Empty string */
02729   strcpy(str, "");
02730   test_eq_ptr(str, eat_whitespace(str));
02731   test_eq_ptr(str, eat_whitespace_eos(str, str));
02732   test_eq_ptr(str, eat_whitespace_no_nl(str));
02733   test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str));
02734 
02735   /* Only ws */
02736   strcpy(str, " \t\r\n");
02737   test_eq_ptr(str + strlen(str), eat_whitespace(str));
02738   test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
02739   test_eq_ptr(str + strlen(str) - 1,
02740               eat_whitespace_no_nl(str));
02741   test_eq_ptr(str + strlen(str) - 1,
02742               eat_whitespace_eos_no_nl(str, str + strlen(str)));
02743 
02744   strcpy(str, " \t\r ");
02745   test_eq_ptr(str + strlen(str), eat_whitespace(str));
02746   test_eq_ptr(str + strlen(str),
02747               eat_whitespace_eos(str, str + strlen(str)));
02748   test_eq_ptr(str + strlen(str), eat_whitespace_no_nl(str));
02749   test_eq_ptr(str + strlen(str),
02750               eat_whitespace_eos_no_nl(str, str + strlen(str)));
02751 
02752   /* Multiple ws */
02753   strcpy(str, "fuubaar");
02754   for (i = 0; i < sizeof(ws); ++i)
02755     str[i] = ws[i];
02756   test_eq_ptr(str + sizeof(ws), eat_whitespace(str));
02757   test_eq_ptr(str + sizeof(ws), eat_whitespace_eos(str, str + strlen(str)));
02758   test_eq_ptr(str + sizeof(ws), eat_whitespace_no_nl(str));
02759   test_eq_ptr(str + sizeof(ws),
02760               eat_whitespace_eos_no_nl(str, str + strlen(str)));
02761 
02762   /* Eat comment */
02763   strcpy(str, "# Comment \n No Comment");
02764   test_streq("No Comment", eat_whitespace(str));
02765   test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str)));
02766   test_eq_ptr(str, eat_whitespace_no_nl(str));
02767   test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
02768 
02769   /* Eat comment & ws mix */
02770   strcpy(str, " # \t Comment \n\t\nNo Comment");
02771   test_streq("No Comment", eat_whitespace(str));
02772   test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str)));
02773   test_eq_ptr(str + 1, eat_whitespace_no_nl(str));
02774   test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str)));
02775 
02776   /* Eat entire comment */
02777   strcpy(str, "#Comment");
02778   test_eq_ptr(str + strlen(str), eat_whitespace(str));
02779   test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
02780   test_eq_ptr(str, eat_whitespace_no_nl(str));
02781   test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
02782 
02783   /* Blank line, then comment */
02784   strcpy(str, " \t\n # Comment");
02785   test_eq_ptr(str + strlen(str), eat_whitespace(str));
02786   test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
02787   test_eq_ptr(str + 2, eat_whitespace_no_nl(str));
02788   test_eq_ptr(str + 2, eat_whitespace_eos_no_nl(str, str + strlen(str)));
02789 
02790  done:
02791   ;
02792 }
02793 
02799 static smartlist_t *
02800 smartlist_new_from_text_lines(const char *lines)
02801 {
02802   smartlist_t *sl = smartlist_new();
02803   char *last_line;
02804 
02805   smartlist_split_string(sl, lines, "\n", 0, 0);
02806 
02807   last_line = smartlist_pop_last(sl);
02808   if (last_line != NULL && *last_line != '\0') {
02809     smartlist_add(sl, last_line);
02810   }
02811 
02812   return sl;
02813 }
02814 
02816 static void
02817 test_util_sl_new_from_text_lines(void *ptr)
02818 {
02819   (void)ptr;
02820 
02821   { /* Normal usage */
02822     smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
02823     int sl_len = smartlist_len(sl);
02824 
02825     tt_want_int_op(sl_len, ==, 3);
02826 
02827     if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), ==, "foo");
02828     if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), ==, "bar");
02829     if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), ==, "baz");
02830 
02831     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
02832     smartlist_free(sl);
02833   }
02834 
02835   { /* No final newline */
02836     smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
02837     int sl_len = smartlist_len(sl);
02838 
02839     tt_want_int_op(sl_len, ==, 3);
02840 
02841     if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), ==, "foo");
02842     if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), ==, "bar");
02843     if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), ==, "baz");
02844 
02845     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
02846     smartlist_free(sl);
02847   }
02848 
02849   { /* No newlines */
02850     smartlist_t *sl = smartlist_new_from_text_lines("foo");
02851     int sl_len = smartlist_len(sl);
02852 
02853     tt_want_int_op(sl_len, ==, 1);
02854 
02855     if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), ==, "foo");
02856 
02857     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
02858     smartlist_free(sl);
02859   }
02860 
02861   { /* No text at all */
02862     smartlist_t *sl = smartlist_new_from_text_lines("");
02863     int sl_len = smartlist_len(sl);
02864 
02865     tt_want_int_op(sl_len, ==, 0);
02866 
02867     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
02868     smartlist_free(sl);
02869   }
02870 }
02871 
02872 static void
02873 test_util_envnames(void *ptr)
02874 {
02875   (void) ptr;
02876 
02877   tt_assert(environment_variable_names_equal("abc", "abc"));
02878   tt_assert(environment_variable_names_equal("abc", "abc="));
02879   tt_assert(environment_variable_names_equal("abc", "abc=def"));
02880   tt_assert(environment_variable_names_equal("abc=def", "abc"));
02881   tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
02882 
02883   tt_assert(environment_variable_names_equal("abc", "abc"));
02884   tt_assert(environment_variable_names_equal("abc", "abc="));
02885   tt_assert(environment_variable_names_equal("abc", "abc=def"));
02886   tt_assert(environment_variable_names_equal("abc=def", "abc"));
02887   tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
02888 
02889   tt_assert(!environment_variable_names_equal("abc", "abcd"));
02890   tt_assert(!environment_variable_names_equal("abc=", "abcd"));
02891   tt_assert(!environment_variable_names_equal("abc=", "abcd"));
02892   tt_assert(!environment_variable_names_equal("abc=", "def"));
02893   tt_assert(!environment_variable_names_equal("abc=", "def="));
02894   tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
02895 
02896   tt_assert(!environment_variable_names_equal("", "a=def"));
02897   /* A bit surprising. */
02898   tt_assert(environment_variable_names_equal("", "=def"));
02899   tt_assert(environment_variable_names_equal("=y", "=x"));
02900 
02901  done:
02902   ;
02903 }
02904 
02906 static void
02907 test_util_make_environment(void *ptr)
02908 {
02909   const char *env_vars_string =
02910     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
02911     "HOME=/home/foozer\n";
02912   const char expected_windows_env_block[] =
02913     "HOME=/home/foozer\000"
02914     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
02915     "\000";
02916   size_t expected_windows_env_block_len =
02917     sizeof(expected_windows_env_block) - 1;
02918 
02919   smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
02920   smartlist_t *env_vars_sorted = smartlist_new();
02921   smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
02922 
02923   process_environment_t *env;
02924 
02925   (void)ptr;
02926 
02927   env = process_environment_make(env_vars);
02928 
02929   /* Check that the Windows environment block is correct. */
02930   tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
02931                     expected_windows_env_block_len));
02932 
02933   /* Now for the Unixoid environment block.  We don't care which order
02934    * these environment variables are in, so we sort both lists first. */
02935 
02936   smartlist_add_all(env_vars_sorted, env_vars);
02937 
02938   {
02939     char **v;
02940     for (v = env->unixoid_environment_block; *v; ++v) {
02941       smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
02942     }
02943   }
02944 
02945   smartlist_sort_strings(env_vars_sorted);
02946   smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
02947 
02948   tt_want_int_op(smartlist_len(env_vars_sorted), ==,
02949                  smartlist_len(env_vars_in_unixoid_env_block_sorted));
02950   {
02951     int len = smartlist_len(env_vars_sorted);
02952     int i;
02953 
02954     if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
02955       len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
02956     }
02957 
02958     for (i = 0; i < len; ++i) {
02959       tt_want_str_op(smartlist_get(env_vars_sorted, i), ==,
02960                      smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
02961     }
02962   }
02963 
02964   /* Clean up. */
02965   smartlist_free(env_vars_in_unixoid_env_block_sorted);
02966   smartlist_free(env_vars_sorted);
02967 
02968   SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
02969   smartlist_free(env_vars);
02970 
02971   process_environment_free(env);
02972 }
02973 
02975 static void
02976 test_util_set_env_var_in_sl(void *ptr)
02977 {
02978   /* The environment variables in these strings are in arbitrary
02979    * order; we sort the resulting lists before comparing them.
02980    *
02981    * (They *will not* end up in the order shown in
02982    * expected_resulting_env_vars_string.) */
02983 
02984   const char *base_env_vars_string =
02985     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
02986     "HOME=/home/foozer\n"
02987     "TERM=xterm\n"
02988     "SHELL=/bin/ksh\n"
02989     "USER=foozer\n"
02990     "LOGNAME=foozer\n"
02991     "USERNAME=foozer\n"
02992     "LANG=en_US.utf8\n"
02993     ;
02994 
02995   const char *new_env_vars_string =
02996     "TERM=putty\n"
02997     "DISPLAY=:18.0\n"
02998     ;
02999 
03000   const char *expected_resulting_env_vars_string =
03001     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
03002     "HOME=/home/foozer\n"
03003     "TERM=putty\n"
03004     "SHELL=/bin/ksh\n"
03005     "USER=foozer\n"
03006     "LOGNAME=foozer\n"
03007     "USERNAME=foozer\n"
03008     "LANG=en_US.utf8\n"
03009     "DISPLAY=:18.0\n"
03010     ;
03011 
03012   smartlist_t *merged_env_vars =
03013     smartlist_new_from_text_lines(base_env_vars_string);
03014   smartlist_t *new_env_vars =
03015     smartlist_new_from_text_lines(new_env_vars_string);
03016   smartlist_t *expected_resulting_env_vars =
03017     smartlist_new_from_text_lines(expected_resulting_env_vars_string);
03018 
03019   /* Elements of merged_env_vars are heap-allocated, and must be
03020    * freed.  Some of them are (or should) be freed by
03021    * set_environment_variable_in_smartlist.
03022    *
03023    * Elements of new_env_vars are heap-allocated, but are copied into
03024    * merged_env_vars, so they are not freed separately at the end of
03025    * the function.
03026    *
03027    * Elements of expected_resulting_env_vars are heap-allocated, and
03028    * must be freed. */
03029 
03030   (void)ptr;
03031 
03032   SMARTLIST_FOREACH(new_env_vars, char *, env_var,
03033                     set_environment_variable_in_smartlist(merged_env_vars,
03034                                                           env_var,
03035                                                           _tor_free,
03036                                                           1));
03037 
03038   smartlist_sort_strings(merged_env_vars);
03039   smartlist_sort_strings(expected_resulting_env_vars);
03040 
03041   tt_want_int_op(smartlist_len(merged_env_vars), ==,
03042                  smartlist_len(expected_resulting_env_vars));
03043   {
03044     int len = smartlist_len(merged_env_vars);
03045     int i;
03046 
03047     if (smartlist_len(expected_resulting_env_vars) < len) {
03048       len = smartlist_len(expected_resulting_env_vars);
03049     }
03050 
03051     for (i = 0; i < len; ++i) {
03052       tt_want_str_op(smartlist_get(merged_env_vars, i), ==,
03053                      smartlist_get(expected_resulting_env_vars, i));
03054     }
03055   }
03056 
03057   /* Clean up. */
03058   SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
03059   smartlist_free(merged_env_vars);
03060 
03061   smartlist_free(new_env_vars);
03062 
03063   SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
03064   smartlist_free(expected_resulting_env_vars);
03065 }
03066 
03067 #define UTIL_LEGACY(name)                                               \
03068   { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
03069 
03070 #define UTIL_TEST(name, flags)                          \
03071   { #name, test_util_ ## name, flags, NULL, NULL }
03072 
03073 struct testcase_t util_tests[] = {
03074   UTIL_LEGACY(time),
03075   UTIL_TEST(parse_http_time, 0),
03076   UTIL_LEGACY(config_line),
03077   UTIL_LEGACY(config_line_quotes),
03078   UTIL_LEGACY(config_line_comment_character),
03079   UTIL_LEGACY(config_line_escaped_content),
03080 #ifndef _WIN32
03081   UTIL_LEGACY(expand_filename),
03082 #endif
03083   UTIL_LEGACY(strmisc),
03084   UTIL_LEGACY(pow2),
03085   UTIL_LEGACY(gzip),
03086   UTIL_LEGACY(datadir),
03087   UTIL_LEGACY(mempool),
03088   UTIL_LEGACY(memarea),
03089   UTIL_LEGACY(control_formats),
03090   UTIL_LEGACY(mmap),
03091   UTIL_LEGACY(threads),
03092   UTIL_LEGACY(sscanf),
03093   UTIL_LEGACY(path_is_relative),
03094   UTIL_LEGACY(strtok),
03095   UTIL_LEGACY(di_ops),
03096   UTIL_TEST(find_str_at_start_of_line, 0),
03097   UTIL_TEST(string_is_C_identifier, 0),
03098   UTIL_TEST(asprintf, 0),
03099   UTIL_TEST(listdir, 0),
03100   UTIL_TEST(parent_dir, 0),
03101 #ifdef _WIN32
03102   UTIL_TEST(load_win_lib, 0),
03103 #endif
03104   UTIL_TEST(exit_status, 0),
03105 #ifndef _WIN32
03106   UTIL_TEST(fgets_eagain, TT_SKIP),
03107 #endif
03108   UTIL_TEST(spawn_background_ok, 0),
03109   UTIL_TEST(spawn_background_fail, 0),
03110   UTIL_TEST(spawn_background_partial_read, 0),
03111   UTIL_TEST(format_hex_number, 0),
03112   UTIL_TEST(join_win_cmdline, 0),
03113   UTIL_TEST(split_lines, 0),
03114   UTIL_TEST(n_bits_set, 0),
03115   UTIL_TEST(eat_whitespace, 0),
03116   UTIL_TEST(sl_new_from_text_lines, 0),
03117   UTIL_TEST(envnames, 0),
03118   UTIL_TEST(make_environment, 0),
03119   UTIL_TEST(set_env_var_in_sl, 0),
03120   END_OF_TESTCASES
03121 };
03122