LCOV - code coverage report
Current view: top level - test - test_util.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 3875 3921 98.8 %
Date: 2021-11-24 03:28:48 Functions: 100 100 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2001-2004, Roger Dingledine.
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : #include "orconfig.h"
       7             : #define COMPAT_TIME_PRIVATE
       8             : #define UTIL_MALLOC_PRIVATE
       9             : #define PROCESS_WIN32_PRIVATE
      10             : #include "lib/testsupport/testsupport.h"
      11             : #include "core/or/or.h"
      12             : #include "lib/buf/buffers.h"
      13             : #include "app/config/config.h"
      14             : #include "feature/control/control.h"
      15             : #include "feature/control/control_proto.h"
      16             : #include "feature/client/transports.h"
      17             : #include "lib/crypt_ops/crypto_format.h"
      18             : #include "lib/crypt_ops/crypto_rand.h"
      19             : #include "lib/defs/time.h"
      20             : #include "test/test.h"
      21             : #include "test/test_helpers.h"
      22             : #include "lib/memarea/memarea.h"
      23             : #include "lib/process/waitpid.h"
      24             : #include "lib/process/process_win32.h"
      25             : #include "test/log_test_helpers.h"
      26             : #include "lib/compress/compress.h"
      27             : #include "lib/compress/compress_zstd.h"
      28             : #include "lib/encoding/keyval.h"
      29             : #include "lib/fdio/fdio.h"
      30             : #include "lib/fs/winlib.h"
      31             : #include "lib/process/env.h"
      32             : #include "lib/process/pidfile.h"
      33             : #include "lib/intmath/weakrng.h"
      34             : #include "lib/intmath/muldiv.h"
      35             : #include "lib/thread/numcpus.h"
      36             : #include "lib/math/fp.h"
      37             : #include "lib/math/laplace.h"
      38             : #include "lib/meminfo/meminfo.h"
      39             : #include "lib/time/tvdiff.h"
      40             : #include "lib/encoding/confline.h"
      41             : #include "lib/net/socketpair.h"
      42             : #include "lib/malloc/map_anon.h"
      43             : 
      44             : #ifdef HAVE_PWD_H
      45             : #include <pwd.h>
      46             : #endif
      47             : #ifdef HAVE_SYS_UTIME_H
      48             : #include <sys/utime.h>
      49             : #endif
      50             : #ifdef HAVE_UTIME_H
      51             : #include <utime.h>
      52             : #endif
      53             : #ifdef HAVE_SYS_STAT_H
      54             : #include <sys/stat.h>
      55             : #endif
      56             : #ifdef HAVE_FCNTL_H
      57             : #include <fcntl.h>
      58             : #endif
      59             : #ifdef HAVE_UNISTD_H
      60             : #include <unistd.h>
      61             : #endif
      62             : #ifdef HAVE_SYS_MMAN_H
      63             : #include <sys/mman.h>
      64             : #endif
      65             : #ifdef HAVE_SYS_WAIT_H
      66             : #include <sys/wait.h>
      67             : #endif
      68             : 
      69             : #ifdef _WIN32
      70             : #include <tchar.h>
      71             : #endif
      72             : #include <math.h>
      73             : #include <ctype.h>
      74             : #include <float.h>
      75             : 
      76             : /* These platforms don't have meaningful pwdb or homedirs. */
      77             : #if defined(_WIN32) || defined(__ANDROID__)
      78             : #define DISABLE_PWDB_TESTS
      79             : #endif
      80             : 
      81             : static void set_file_mtime(const char *fname, time_t when);
      82             : 
      83             : #define INFINITY_DBL ((double)INFINITY)
      84             : #define NAN_DBL ((double)NAN)
      85             : 
      86             : /** Test the tor_isinf() wrapper */
      87             : static void
      88           1 : test_tor_isinf(void *arg)
      89             : {
      90           1 :   (void) arg;
      91             : 
      92           1 :   tt_assert(tor_isinf(INFINITY_DBL));
      93             : 
      94           1 :   tt_assert(!tor_isinf(NAN_DBL));
      95           1 :   tt_assert(!tor_isinf(DBL_EPSILON));
      96           1 :   tt_assert(!tor_isinf(DBL_MAX));
      97           1 :   tt_assert(!tor_isinf(DBL_MIN));
      98             : 
      99           1 :   tt_assert(!tor_isinf(0.0));
     100           1 :   tt_assert(!tor_isinf(0.1));
     101           1 :   tt_assert(!tor_isinf(3));
     102           1 :   tt_assert(!tor_isinf(3.14));
     103             : 
     104           1 :  done:
     105           1 :   ;
     106           1 : }
     107             : 
     108             : /* XXXX this is a minimal wrapper to make the unit tests compile with the
     109             :  * changed tor_timegm interface. */
     110             : static time_t
     111          52 : tor_timegm_wrapper(const struct tm *tm)
     112             : {
     113          52 :   time_t t;
     114          52 :   if (tor_timegm(tm, &t) < 0)
     115             :     return -1;
     116          32 :   return t;
     117             : }
     118             : 
     119             : #define tor_timegm tor_timegm_wrapper
     120             : 
     121             : static void
     122           6 : test_util_read_until_eof_impl(const char *fname, size_t file_len,
     123             :                               size_t read_limit)
     124             : {
     125           6 :   char *fifo_name = NULL;
     126           6 :   char *test_str = NULL;
     127           6 :   char *str = NULL;
     128           6 :   size_t sz = 9999999;
     129           6 :   int fd = -1;
     130           6 :   int r;
     131             : 
     132           6 :   fifo_name = tor_strdup(get_fname(fname));
     133           6 :   test_str = tor_malloc(file_len);
     134           6 :   crypto_rand(test_str, file_len);
     135             : 
     136           6 :   r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
     137           6 :   tt_int_op(r, OP_EQ, 0);
     138             : 
     139           6 :   fd = open(fifo_name, O_RDONLY|O_BINARY);
     140           6 :   tt_int_op(fd, OP_GE, 0);
     141           6 :   str = read_file_to_str_until_eof(fd, read_limit, &sz);
     142           6 :   tt_ptr_op(str, OP_NE, NULL);
     143             : 
     144           6 :   if (read_limit < file_len)
     145           2 :     tt_int_op(sz, OP_EQ, read_limit);
     146             :   else
     147           4 :     tt_int_op(sz, OP_EQ, file_len);
     148             : 
     149           6 :   tt_mem_op(test_str, OP_EQ, str, sz);
     150           6 :   tt_int_op(str[sz], OP_EQ, '\0');
     151             : 
     152           6 :  done:
     153           6 :   unlink(fifo_name);
     154           6 :   tor_free(fifo_name);
     155           6 :   tor_free(test_str);
     156           6 :   tor_free(str);
     157           6 :   if (fd >= 0)
     158           6 :     close(fd);
     159           6 : }
     160             : 
     161             : static void
     162           1 : test_util_read_file_eof_tiny_limit(void *arg)
     163             : {
     164           1 :   (void)arg;
     165             :   // purposely set limit shorter than what we wrote to the FIFO to
     166             :   // test the maximum, and that it puts the NUL in the right spot
     167             : 
     168           1 :   test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
     169           1 : }
     170             : 
     171             : static void
     172           1 : test_util_read_file_eof_one_loop_a(void *arg)
     173             : {
     174           1 :   (void)arg;
     175           1 :   test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
     176           1 : }
     177             : 
     178             : static void
     179           1 : test_util_read_file_eof_one_loop_b(void *arg)
     180             : {
     181           1 :   (void)arg;
     182           1 :   test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
     183           1 : }
     184             : 
     185             : static void
     186           1 : test_util_read_file_eof_two_loops(void *arg)
     187             : {
     188           1 :   (void)arg;
     189             :   // write more than 1024 bytes to the FIFO to test two passes through
     190             :   // the loop in the method; if the re-alloc size is changed this
     191             :   // should be updated as well.
     192             : 
     193           1 :   test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
     194           1 : }
     195             : 
     196             : static void
     197           1 : test_util_read_file_eof_two_loops_b(void *arg)
     198             : {
     199           1 :   (void)arg;
     200             : 
     201           1 :   test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
     202           1 : }
     203             : 
     204             : static void
     205           1 : test_util_read_file_eof_zero_bytes(void *arg)
     206             : {
     207           1 :   (void)arg;
     208             :   // zero-byte fifo
     209           1 :   test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
     210           1 : }
     211             : 
     212             : static void
     213           1 : test_util_read_file_endlines(void *arg)
     214             : {
     215           1 :   (void)arg;
     216             : 
     217           1 :   char *fname = NULL;
     218           1 :   char *read_content = NULL;
     219           1 :   int r = -1;
     220             : 
     221             :   /* Write a file that contains both \n and \r\n as line ending. */
     222           1 :   const char *file_content = "foo bar\n"
     223             :                              "foo bar baz\r\n"
     224             :                              "foo bar\r\n";
     225             : 
     226           1 :   const char *expected_file_content = "foo bar\n"
     227             :                                       "foo bar baz\n"
     228             :                                       "foo bar\n";
     229             : 
     230           1 :   fname = tor_strdup(get_fname("file_with_crlf_ending"));
     231             : 
     232           1 :   r = write_bytes_to_file(fname, file_content, strlen(file_content), 1);
     233           1 :   tt_int_op(r, OP_EQ, 0);
     234             : 
     235             :   /* Read the file in text mode: we strip \r's from the files on both Windows
     236             :    * and UNIX. */
     237           1 :   read_content = read_file_to_str(fname, 0, NULL);
     238             : 
     239           1 :   tt_ptr_op(read_content, OP_NE, NULL);
     240           1 :   tt_int_op(strlen(read_content), OP_EQ, strlen(expected_file_content));
     241           1 :   tt_str_op(read_content, OP_EQ, expected_file_content);
     242             : 
     243           1 :   tor_free(read_content);
     244             : 
     245             :   /* Read the file in binary mode: we should preserve the \r here. */
     246           1 :   read_content = read_file_to_str(fname, RFTS_BIN, NULL);
     247             : 
     248           1 :   tt_ptr_op(read_content, OP_NE, NULL);
     249           1 :   tt_int_op(strlen(read_content), OP_EQ, strlen(file_content));
     250           1 :   tt_str_op(read_content, OP_EQ, file_content);
     251             : 
     252           1 :   tor_free(read_content);
     253             : 
     254           1 :  done:
     255           1 :   unlink(fname);
     256           1 :   tor_free(fname);
     257           1 :   tor_free(read_content);
     258           1 : }
     259             : 
     260             : /* Test the basic expected behaviour for write_chunks_to_file.
     261             :  * NOTE: This will need to be updated if we ever change the tempfile location
     262             :  * or extension */
     263             : static void
     264           1 : test_util_write_chunks_to_file(void *arg)
     265             : {
     266           1 :   char *fname = NULL;
     267           1 :   char *tempname = NULL;
     268           1 :   char *str = NULL;
     269           1 :   int r;
     270           1 :   struct stat st;
     271             : 
     272             :   /* These should be two different sizes to ensure the data is different
     273             :    * between the data file and the temp file's 'known string' */
     274           1 :   int temp_str_len = 1024;
     275           1 :   int data_str_len = 512;
     276           1 :   char *data_str = tor_malloc(data_str_len);
     277           1 :   char *temp_str = tor_malloc(temp_str_len);
     278             : 
     279           1 :   smartlist_t *chunks = smartlist_new();
     280           1 :   sized_chunk_t c = {data_str, data_str_len/2};
     281           1 :   sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
     282           1 :   (void)arg;
     283             : 
     284           1 :   crypto_rand(temp_str, temp_str_len);
     285           1 :   crypto_rand(data_str, data_str_len);
     286             : 
     287             :   // Ensure it can write multiple chunks
     288             : 
     289           1 :   smartlist_add(chunks, &c);
     290           1 :   smartlist_add(chunks, &c2);
     291             : 
     292             :   /*
     293             :   * Check if it writes using a tempfile
     294             :   */
     295           1 :   fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
     296           1 :   tor_asprintf(&tempname, "%s.tmp", fname);
     297             : 
     298             :   // write a known string to a file where the tempfile will be
     299           1 :   r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
     300           1 :   tt_int_op(r, OP_EQ, 0);
     301             : 
     302             :   // call write_chunks_to_file
     303           1 :   r = write_chunks_to_file(fname, chunks, 1, 0);
     304           1 :   tt_int_op(r, OP_EQ, 0);
     305             : 
     306             :   // assert the file has been written (expected size)
     307           1 :   str = read_file_to_str(fname, RFTS_BIN, &st);
     308           1 :   tt_assert(str != NULL);
     309           1 :   tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
     310           1 :   tt_mem_op(data_str, OP_EQ, str, data_str_len);
     311           1 :   tor_free(str);
     312             : 
     313             :   // assert that the tempfile is removed (should not leave artifacts)
     314           1 :   str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
     315           1 :   tt_assert(str == NULL);
     316             : 
     317             :   // Remove old testfile for second test
     318           1 :   r = unlink(fname);
     319           1 :   tt_int_op(r, OP_EQ, 0);
     320           1 :   tor_free(fname);
     321           1 :   tor_free(tempname);
     322             : 
     323             :   /*
     324             :   *  Check if it skips using a tempfile with flags
     325             :   */
     326           1 :   fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
     327           1 :   tor_asprintf(&tempname, "%s.tmp", fname);
     328             : 
     329             :   // write a known string to a file where the tempfile will be
     330           1 :   r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
     331           1 :   tt_int_op(r, OP_EQ, 0);
     332             : 
     333             :   // call write_chunks_to_file with no_tempfile = true
     334           1 :   r = write_chunks_to_file(fname, chunks, 1, 1);
     335           1 :   tt_int_op(r, OP_EQ, 0);
     336             : 
     337             :   // assert the file has been written (expected size)
     338           1 :   str = read_file_to_str(fname, RFTS_BIN, &st);
     339           1 :   tt_assert(str != NULL);
     340           1 :   tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
     341           1 :   tt_mem_op(data_str, OP_EQ, str, data_str_len);
     342           1 :   tor_free(str);
     343             : 
     344             :   // assert the tempfile still contains the known string
     345           1 :   str = read_file_to_str(tempname, RFTS_BIN, &st);
     346           1 :   tt_assert(str != NULL);
     347           1 :   tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
     348           1 :   tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
     349             : 
     350           1 :  done:
     351           1 :   unlink(fname);
     352           1 :   unlink(tempname);
     353           1 :   smartlist_free(chunks);
     354           1 :   tor_free(fname);
     355           1 :   tor_free(tempname);
     356           1 :   tor_free(str);
     357           1 :   tor_free(data_str);
     358           1 :   tor_free(temp_str);
     359           1 : }
     360             : 
     361             : /* Test write_str_to_file_if_not_equal(). */
     362             : static void
     363           1 : test_util_write_str_if_changed(void *arg)
     364             : {
     365           1 :   (void)arg;
     366           1 :   char *fname = tor_strdup(get_fname("write_if_changed"));
     367           1 :   char *s = NULL;
     368           1 :   int rv;
     369           1 :   const char str1[] = "The wombat lives across the seas";
     370           1 :   const char str2[] = "Among the far Antipodes"; /* -- Ogden Nash */
     371             : 
     372             :   /* We can create files. */
     373           1 :   rv = write_str_to_file_if_not_equal(fname, str1);
     374           1 :   tt_int_op(rv, OP_EQ, 0);
     375           1 :   s = read_file_to_str(fname, 0, NULL);
     376           1 :   tt_str_op(s, OP_EQ, str1);
     377           1 :   tor_free(s);
     378             : 
     379             :   /* We can replace files. */
     380           1 :   rv = write_str_to_file_if_not_equal(fname, str2);
     381           1 :   tt_int_op(rv, OP_EQ, 0);
     382           1 :   s = read_file_to_str(fname, 0, NULL);
     383           1 :   tt_str_op(s, OP_EQ, str2);
     384           1 :   tor_free(s);
     385             : 
     386             :   /* Make sure we don't replace files when they're equal. (That's the whole
     387             :    * point of the function we're testing. */
     388             :   /* First, change the mtime of the file so that we can tell whether we
     389             :    * replaced it. */
     390           1 :   const time_t now = time(NULL);
     391           1 :   const time_t five_sec_ago = now - 5;
     392           1 :   set_file_mtime(fname, five_sec_ago);
     393           1 :   rv = write_str_to_file_if_not_equal(fname, str2);
     394           1 :   tt_int_op(rv, OP_EQ, 0);
     395             :   /* Make sure that the file's mtime is unchanged... */
     396           1 :   struct stat st;
     397           1 :   rv = stat(fname, &st);
     398           1 :   tt_int_op(rv, OP_EQ, 0);
     399           1 :   tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
     400             :   /* And make sure its contents are unchanged. */
     401           1 :   s = read_file_to_str(fname, 0, NULL);
     402           1 :   tt_str_op(s, OP_EQ, str2);
     403           1 :   tor_free(s);
     404             : 
     405           1 :  done:
     406           1 :   tor_free(fname);
     407           1 :   tor_free(s);
     408           1 : }
     409             : 
     410             : #ifndef COCCI
     411             : #define _TFE(a, b, f)  tt_int_op((a).f, OP_EQ, (b).f)
     412             : /** test the minimum set of struct tm fields needed for a unique epoch value
     413             :  * this is also the set we use to test tor_timegm */
     414             : #define TM_EQUAL(a, b)           \
     415             :           TT_STMT_BEGIN          \
     416             :             _TFE(a, b, tm_year); \
     417             :             _TFE(a, b, tm_mon ); \
     418             :             _TFE(a, b, tm_mday); \
     419             :             _TFE(a, b, tm_hour); \
     420             :             _TFE(a, b, tm_min ); \
     421             :             _TFE(a, b, tm_sec ); \
     422             :           TT_STMT_END
     423             : #endif /* !defined(COCCI) */
     424             : 
     425             : static void
     426           1 : test_util_time(void *arg)
     427             : {
     428           1 :   struct timeval start, end;
     429           1 :   struct tm a_time, b_time;
     430           1 :   char timestr[128];
     431           1 :   time_t t_res;
     432           1 :   int i;
     433           1 :   struct timeval tv;
     434             : 
     435             :   /* Test tv_udiff and tv_mdiff */
     436             : 
     437           1 :   (void)arg;
     438           1 :   start.tv_sec = 5;
     439           1 :   start.tv_usec = 5000;
     440             : 
     441           1 :   end.tv_sec = 5;
     442           1 :   end.tv_usec = 5000;
     443             : 
     444           1 :   tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
     445           1 :   tt_int_op(0L,OP_EQ, tv_mdiff(&start, &end));
     446           1 :   tt_int_op(0L,OP_EQ, tv_udiff(&end, &start));
     447           1 :   tt_int_op(0L,OP_EQ, tv_mdiff(&end, &start));
     448             : 
     449           1 :   end.tv_usec = 7000;
     450             : 
     451           1 :   tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
     452           1 :   tt_int_op(2L,OP_EQ, tv_mdiff(&start, &end));
     453           1 :   tt_int_op(-2000L,OP_EQ, tv_udiff(&end, &start));
     454           1 :   tt_int_op(-2L,OP_EQ, tv_mdiff(&end, &start));
     455             : 
     456           1 :   end.tv_sec = 6;
     457             : 
     458           1 :   tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
     459           1 :   tt_int_op(1002L,OP_EQ, tv_mdiff(&start, &end));
     460           1 :   tt_int_op(-1002000L,OP_EQ, tv_udiff(&end, &start));
     461           1 :   tt_int_op(-1002L,OP_EQ, tv_mdiff(&end, &start));
     462             : 
     463           1 :   end.tv_usec = 0;
     464             : 
     465           1 :   tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
     466           1 :   tt_int_op(995L,OP_EQ, tv_mdiff(&start, &end));
     467           1 :   tt_int_op(-995000L,OP_EQ, tv_udiff(&end, &start));
     468           1 :   tt_int_op(-995L,OP_EQ, tv_mdiff(&end, &start));
     469             : 
     470           1 :   end.tv_sec = 4;
     471             : 
     472           1 :   tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
     473           1 :   tt_int_op(-1005L,OP_EQ, tv_mdiff(&start, &end));
     474           1 :   tt_int_op(1005000L,OP_EQ, tv_udiff(&end, &start));
     475           1 :   tt_int_op(1005L,OP_EQ, tv_mdiff(&end, &start));
     476             : 
     477             :   /* Negative tv_sec values, these will break on platforms where tv_sec is
     478             :    * unsigned */
     479             : 
     480           1 :   end.tv_sec = -10;
     481             : 
     482           1 :   tt_int_op(-15005000L,OP_EQ, tv_udiff(&start, &end));
     483           1 :   tt_int_op(-15005L,OP_EQ, tv_mdiff(&start, &end));
     484           1 :   tt_int_op(15005000L,OP_EQ, tv_udiff(&end, &start));
     485           1 :   tt_int_op(15005L,OP_EQ, tv_mdiff(&end, &start));
     486             : 
     487           1 :   start.tv_sec = -100;
     488             : 
     489           1 :   tt_int_op(89995000L,OP_EQ, tv_udiff(&start, &end));
     490           1 :   tt_int_op(89995L,OP_EQ, tv_mdiff(&start, &end));
     491           1 :   tt_int_op(-89995000L,OP_EQ, tv_udiff(&end, &start));
     492           1 :   tt_int_op(-89995L,OP_EQ, tv_mdiff(&end, &start));
     493             : 
     494             :   /* Test that tv_usec values round away from zero when converted to msec */
     495           1 :   start.tv_sec = 0;
     496           1 :   start.tv_usec = 0;
     497           1 :   end.tv_sec = 10;
     498           1 :   end.tv_usec = 499;
     499             : 
     500           1 :   tt_int_op(10000499L, OP_EQ, tv_udiff(&start, &end));
     501           1 :   tt_int_op(10000L, OP_EQ, tv_mdiff(&start, &end));
     502           1 :   tt_int_op(-10000499L, OP_EQ, tv_udiff(&end, &start));
     503           1 :   tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
     504             : 
     505           1 :   start.tv_sec = 0;
     506           1 :   start.tv_usec = 0;
     507           1 :   end.tv_sec = 10;
     508           1 :   end.tv_usec = 500;
     509             : 
     510           1 :   tt_int_op(10000500L, OP_EQ, tv_udiff(&start, &end));
     511           1 :   tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
     512           1 :   tt_int_op(-10000500L, OP_EQ, tv_udiff(&end, &start));
     513           1 :   tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
     514             : 
     515           1 :   start.tv_sec = 0;
     516           1 :   start.tv_usec = 0;
     517           1 :   end.tv_sec = 10;
     518           1 :   end.tv_usec = 501;
     519             : 
     520           1 :   tt_int_op(10000501L, OP_EQ, tv_udiff(&start, &end));
     521           1 :   tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
     522           1 :   tt_int_op(-10000501L, OP_EQ, tv_udiff(&end, &start));
     523           1 :   tt_int_op(-10001L, OP_EQ, tv_mdiff(&end, &start));
     524             : 
     525             :   /* Overflow conditions */
     526             : 
     527             : #ifdef _WIN32
     528             :   /* Would you believe that tv_sec is a long on windows? Of course you would.*/
     529             : #define TV_SEC_MAX LONG_MAX
     530             : #define TV_SEC_MIN LONG_MIN
     531             : #else
     532             :   /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
     533             :    * Which means TIME_MAX is not actually the maximum value of tv_sec.
     534             :    * But that's ok for the moment, because the code correctly performs 64-bit
     535             :    * calculations internally, then catches the overflow. */
     536             : #define TV_SEC_MAX TIME_MAX
     537             : #define TV_SEC_MIN TIME_MIN
     538             : #endif /* defined(_WIN32) */
     539             : 
     540             : /* Assume tv_usec is an unsigned integer until proven otherwise */
     541             : #define TV_USEC_MAX UINT_MAX
     542             : 
     543             :   /* Overflows in the result type */
     544             : 
     545             :   /* All comparisons work */
     546           1 :   start.tv_sec = 0;
     547           1 :   start.tv_usec = 0;
     548           1 :   end.tv_sec = LONG_MAX/1000 - 2;
     549           1 :   end.tv_usec = 0;
     550             : 
     551           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     552           1 :   tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
     553           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     554           1 :   tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
     555             : 
     556           1 :   start.tv_sec = 0;
     557           1 :   start.tv_usec = 0;
     558           1 :   end.tv_sec = LONG_MAX/1000000 - 1;
     559           1 :   end.tv_usec = 0;
     560             : 
     561           1 :   tt_int_op(end.tv_sec*1000000L, OP_EQ, tv_udiff(&start, &end));
     562           1 :   tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
     563           1 :   tt_int_op(-end.tv_sec*1000000L, OP_EQ, tv_udiff(&end, &start));
     564           1 :   tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
     565             : 
     566             :   /* No comparisons work */
     567           1 :   start.tv_sec = 0;
     568           1 :   start.tv_usec = 0;
     569           1 :   end.tv_sec = LONG_MAX/1000 + 1;
     570           1 :   end.tv_usec = 0;
     571             : 
     572           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     573           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     574           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     575           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     576             : 
     577           1 :   start.tv_sec = 0;
     578           1 :   start.tv_usec = 0;
     579           1 :   end.tv_sec = LONG_MAX/1000000 + 1;
     580           1 :   end.tv_usec = 0;
     581             : 
     582           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     583           1 :   tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
     584           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     585           1 :   tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
     586             : 
     587           1 :   start.tv_sec = 0;
     588           1 :   start.tv_usec = 0;
     589           1 :   end.tv_sec = LONG_MAX/1000;
     590           1 :   end.tv_usec = TOR_USEC_PER_SEC;
     591             : 
     592           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     593           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     594           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     595           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     596             : 
     597           1 :   start.tv_sec = 0;
     598           1 :   start.tv_usec = 0;
     599           1 :   end.tv_sec = LONG_MAX/1000000;
     600           1 :   end.tv_usec = TOR_USEC_PER_SEC;
     601             : 
     602           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     603           1 :   tt_int_op((end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&start, &end));
     604           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     605           1 :   tt_int_op(-(end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&end, &start));
     606             : 
     607             :   /* Overflows on comparison to zero */
     608             : 
     609           1 :   start.tv_sec = 0;
     610           1 :   start.tv_usec = 0;
     611             : 
     612           1 :   end.tv_sec = TV_SEC_MAX;
     613           1 :   end.tv_usec = 0;
     614             : 
     615           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     616           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     617           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     618           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     619             : 
     620           1 :   end.tv_sec = TV_SEC_MAX;
     621           1 :   end.tv_usec = TOR_USEC_PER_SEC;
     622             : 
     623           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     624           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     625           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     626           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     627             : 
     628           1 :   end.tv_sec = 0;
     629           1 :   end.tv_usec = TV_USEC_MAX;
     630             : 
     631           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     632           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     633           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     634           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     635             : 
     636           1 :   end.tv_sec = TV_SEC_MAX;
     637           1 :   end.tv_usec = TV_USEC_MAX;
     638             : 
     639           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     640           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     641           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     642           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     643             : 
     644           1 :   end.tv_sec = 0;
     645           1 :   end.tv_usec = 0;
     646             : 
     647           1 :   start.tv_sec = TV_SEC_MIN;
     648           1 :   start.tv_usec = 0;
     649             : 
     650           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     651           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     652           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     653           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     654             : 
     655           1 :   start.tv_sec = TV_SEC_MIN;
     656           1 :   start.tv_usec = TOR_USEC_PER_SEC;
     657             : 
     658           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     659           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     660           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     661           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     662             : 
     663           1 :   start.tv_sec = TV_SEC_MIN;
     664           1 :   start.tv_usec = TV_USEC_MAX;
     665             : 
     666           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     667           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     668           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     669           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     670             : 
     671             :   /* overflows on comparison to maxima / minima */
     672             : 
     673           1 :   start.tv_sec = TV_SEC_MIN;
     674           1 :   start.tv_usec = 0;
     675             : 
     676           1 :   end.tv_sec = TV_SEC_MAX;
     677           1 :   end.tv_usec = 0;
     678             : 
     679           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     680           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     681           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     682           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     683             : 
     684           1 :   end.tv_sec = TV_SEC_MAX;
     685           1 :   end.tv_usec = TOR_USEC_PER_SEC;
     686             : 
     687           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     688           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     689           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     690           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     691             : 
     692           1 :   end.tv_sec = TV_SEC_MAX;
     693           1 :   end.tv_usec = 0;
     694             : 
     695           1 :   start.tv_sec = TV_SEC_MIN;
     696           1 :   start.tv_usec = 0;
     697             : 
     698           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     699           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     700           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     701           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     702             : 
     703           1 :   start.tv_sec = TV_SEC_MIN;
     704           1 :   start.tv_usec = TOR_USEC_PER_SEC;
     705             : 
     706           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     707           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     708           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     709           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     710             : 
     711             :   /* overflows on comparison to maxima / minima with extra usec */
     712             : 
     713           1 :   start.tv_sec = TV_SEC_MIN;
     714           1 :   start.tv_usec = TOR_USEC_PER_SEC;
     715             : 
     716           1 :   end.tv_sec = TV_SEC_MAX;
     717           1 :   end.tv_usec = 0;
     718             : 
     719           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     720           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     721           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     722           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     723             : 
     724           1 :   end.tv_sec = TV_SEC_MAX;
     725           1 :   end.tv_usec = TOR_USEC_PER_SEC;
     726             : 
     727           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     728           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     729           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     730           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     731             : 
     732           1 :   end.tv_sec = TV_SEC_MAX;
     733           1 :   end.tv_usec = TOR_USEC_PER_SEC;
     734             : 
     735           1 :   start.tv_sec = TV_SEC_MIN;
     736           1 :   start.tv_usec = 0;
     737             : 
     738           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     739           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     740           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     741           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     742             : 
     743           1 :   start.tv_sec = TV_SEC_MIN;
     744           1 :   start.tv_usec = TOR_USEC_PER_SEC;
     745             : 
     746           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
     747           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
     748           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
     749           1 :   tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
     750             : 
     751             :   /* Test tor_timegm & tor_gmtime_r */
     752             : 
     753             :   /* The test values here are confirmed to be correct on a platform
     754             :    * with a working timegm & gmtime_r. */
     755             : 
     756             :   /* Start with known-zero a_time and b_time.
     757             :    * This avoids passing uninitialised values to TM_EQUAL in a_time.
     758             :    * Zeroing may not be needed for b_time, as long as tor_gmtime_r
     759             :    * never reads the existing values in the structure.
     760             :    * But we really don't want intermittently failing tests. */
     761           1 :   memset(&a_time, 0, sizeof(struct tm));
     762           1 :   memset(&b_time, 0, sizeof(struct tm));
     763             : 
     764           1 :   a_time.tm_year = 2003-1900;
     765           1 :   a_time.tm_mon = 7;
     766           1 :   a_time.tm_mday = 30;
     767           1 :   a_time.tm_hour = 6;
     768           1 :   a_time.tm_min = 14;
     769           1 :   a_time.tm_sec = 55;
     770           1 :   t_res = 1062224095UL;
     771           1 :   tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
     772           1 :   tor_gmtime_r(&t_res, &b_time);
     773           1 :   TM_EQUAL(a_time, b_time);
     774             : 
     775           1 :   a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
     776           1 :   t_res = 1093846495UL;
     777           1 :   tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
     778           1 :   tor_gmtime_r(&t_res, &b_time);
     779           1 :   TM_EQUAL(a_time, b_time);
     780             : 
     781           1 :   a_time.tm_mon = 1;          /* Try a leap year, in feb. */
     782           1 :   a_time.tm_mday = 10;
     783           1 :   t_res = 1076393695UL;
     784           1 :   tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
     785           1 :   tor_gmtime_r(&t_res, &b_time);
     786           1 :   TM_EQUAL(a_time, b_time);
     787             : 
     788           1 :   a_time.tm_mon = 0;
     789           1 :   t_res = 1073715295UL;
     790           1 :   tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
     791           1 :   tor_gmtime_r(&t_res, &b_time);
     792           1 :   TM_EQUAL(a_time, b_time);
     793             : 
     794             :   /* This value is in range with 32 bit and 64 bit time_t */
     795           1 :   a_time.tm_year = 2037-1900;
     796           1 :   t_res = 2115180895UL;
     797           1 :   tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
     798           1 :   tor_gmtime_r(&t_res, &b_time);
     799           1 :   TM_EQUAL(a_time, b_time);
     800             : 
     801             :   /* This value is out of range with 32 bit time_t, but in range for 64 bit
     802             :    * time_t */
     803           1 :   a_time.tm_year = 2039-1900;
     804             : #if SIZEOF_TIME_T == 4
     805             :   setup_full_capture_of_logs(LOG_WARN);
     806             :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     807             :   expect_single_log_msg_containing("Result does not fit in tor_timegm");
     808             :   teardown_capture_of_logs();
     809             : #elif SIZEOF_TIME_T == 8
     810           1 :   t_res = 2178252895UL;
     811           1 :   tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
     812           1 :   tor_gmtime_r(&t_res, &b_time);
     813           1 :   TM_EQUAL(a_time, b_time);
     814             : #endif /* SIZEOF_TIME_T == 4 || ... */
     815             : 
     816             :   /* Test tor_timegm out of range */
     817             : 
     818             :   /* The below tests will all cause a BUG message, so we capture, suppress,
     819             :    * and detect. */
     820             : #define CAPTURE() do {                                          \
     821             :     setup_full_capture_of_logs(LOG_WARN);                       \
     822             :   } while (0)
     823             : #define CHECK_TIMEGM_WARNING(msg) do { \
     824             :     expect_single_log_msg_containing(msg);                              \
     825             :     teardown_capture_of_logs();                                         \
     826             :   } while (0)
     827             : #define CHECK_POSSIBLE_EINVAL() do {                            \
     828             :     if (mock_saved_log_n_entries()) {                           \
     829             :       expect_single_log_msg_containing("Invalid argument");     \
     830             :     }                                                           \
     831             :     teardown_capture_of_logs();                                 \
     832             :   } while (0)
     833             : 
     834             : #define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
     835             :     CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")
     836             : 
     837             :   /* year */
     838             : 
     839             :   /* Wrong year < 1970 */
     840           1 :   a_time.tm_year = 1969-1900;
     841           1 :   CAPTURE();
     842           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     843           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     844             : 
     845           1 :   a_time.tm_year = -1-1900;
     846           1 :   CAPTURE();
     847           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     848           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     849             : 
     850             : #if SIZEOF_INT == 4 || SIZEOF_INT == 8
     851           1 :     a_time.tm_year = -1*(1 << 16);
     852           1 :     CAPTURE();
     853           1 :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     854           1 :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     855             : 
     856             :     /* one of the smallest tm_year values my 64 bit system supports:
     857             :      * t_res = -9223372036854775LL without clamping */
     858           1 :     a_time.tm_year = -292275055-1900;
     859           1 :     CAPTURE();
     860           1 :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     861           1 :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     862             : 
     863           1 :     a_time.tm_year = INT32_MIN;
     864           1 :     CAPTURE();
     865           1 :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     866           1 :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     867             : #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
     868             : 
     869             : #if SIZEOF_INT == 8
     870             :     a_time.tm_year = -1*(1 << 48);
     871             :     CAPTURE();
     872             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     873             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     874             : 
     875             :     /* while unlikely, the system's gmtime(_r) could return
     876             :      * a "correct" retrospective gregorian negative year value,
     877             :      * which I'm pretty sure is:
     878             :      * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
     879             :      * 730485 is the number of days in two millennia, including leap days */
     880             :     a_time.tm_year = -292277022657-1900;
     881             :     CAPTURE();
     882             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     883             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     884             : 
     885             :     a_time.tm_year = INT64_MIN;
     886             :     CAPTURE();
     887             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     888             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     889             : #endif /* SIZEOF_INT == 8 */
     890             : 
     891             :   /* Wrong year >= INT32_MAX - 1900 */
     892             : #if SIZEOF_INT == 4 || SIZEOF_INT == 8
     893           1 :     a_time.tm_year = INT32_MAX-1900;
     894           1 :     CAPTURE();
     895           1 :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     896           1 :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     897             : 
     898           1 :     a_time.tm_year = INT32_MAX;
     899           1 :     CAPTURE();
     900           1 :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     901           1 :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     902             : #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
     903             : 
     904             : #if SIZEOF_INT == 8
     905             :     /* one of the largest tm_year values my 64 bit system supports */
     906             :     a_time.tm_year = 292278994-1900;
     907             :     CAPTURE();
     908             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     909             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     910             : 
     911             :     /* while unlikely, the system's gmtime(_r) could return
     912             :      * a "correct" proleptic gregorian year value,
     913             :      * which I'm pretty sure is:
     914             :      * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
     915             :      * 730485 is the number of days in two millennia, including leap days */
     916             :     a_time.tm_year = 292277026596-1900;
     917             :     CAPTURE();
     918             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     919             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     920             : 
     921             :     a_time.tm_year = INT64_MAX-1900;
     922             :     CAPTURE();
     923             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     924             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     925             : 
     926             :     a_time.tm_year = INT64_MAX;
     927             :     CAPTURE();
     928             :     tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     929             :     CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     930             : #endif /* SIZEOF_INT == 8 */
     931             : 
     932             :   /* month */
     933           1 :   a_time.tm_year = 2007-1900;  /* restore valid year */
     934             : 
     935           1 :   a_time.tm_mon = 12;          /* Wrong month, it's 0-based */
     936           1 :   CAPTURE();
     937           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     938           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     939             : 
     940           1 :   a_time.tm_mon = -1;          /* Wrong month */
     941           1 :   CAPTURE();
     942           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     943           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     944             : 
     945             :   /* day */
     946           1 :   a_time.tm_mon = 6;            /* Try July */
     947           1 :   a_time.tm_mday = 32;          /* Wrong day */
     948           1 :   CAPTURE();
     949           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     950           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     951             : 
     952           1 :   a_time.tm_mon = 5;            /* Try June */
     953           1 :   a_time.tm_mday = 31;          /* Wrong day */
     954           1 :   CAPTURE();
     955           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     956           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     957             : 
     958           1 :   a_time.tm_year = 2008-1900;   /* Try a leap year */
     959           1 :   a_time.tm_mon = 1;            /* in feb. */
     960           1 :   a_time.tm_mday = 30;          /* Wrong day */
     961           1 :   CAPTURE();
     962           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     963           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     964             : 
     965           1 :   a_time.tm_year = 2011-1900;   /* Try a non-leap year */
     966           1 :   a_time.tm_mon = 1;            /* in feb. */
     967           1 :   a_time.tm_mday = 29;          /* Wrong day */
     968           1 :   CAPTURE();
     969           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     970           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     971             : 
     972           1 :   a_time.tm_mday = 0;           /* Wrong day, it's 1-based (to be different) */
     973           1 :   CAPTURE();
     974           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     975           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     976             : 
     977             :   /* hour */
     978           1 :   a_time.tm_mday = 3;           /* restore valid month day */
     979             : 
     980           1 :   a_time.tm_hour = 24;          /* Wrong hour, it's 0-based */
     981           1 :   CAPTURE();
     982           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     983           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     984             : 
     985           1 :   a_time.tm_hour = -1;          /* Wrong hour */
     986           1 :   CAPTURE();
     987           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     988           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     989             : 
     990             :   /* minute */
     991           1 :   a_time.tm_hour = 22;          /* restore valid hour */
     992             : 
     993           1 :   a_time.tm_min = 60;           /* Wrong minute, it's 0-based */
     994           1 :   CAPTURE();
     995           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
     996           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
     997             : 
     998           1 :   a_time.tm_min = -1;           /* Wrong minute */
     999           1 :   CAPTURE();
    1000           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
    1001           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
    1002             : 
    1003             :   /* second */
    1004           1 :   a_time.tm_min = 37;           /* restore valid minute */
    1005             : 
    1006           1 :   a_time.tm_sec = 61;           /* Wrong second: 0-based with leap seconds */
    1007           1 :   CAPTURE();
    1008           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
    1009           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
    1010             : 
    1011           1 :   a_time.tm_sec = -1;           /* Wrong second */
    1012           1 :   CAPTURE();
    1013           1 :   tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
    1014           1 :   CHECK_TIMEGM_ARG_OUT_OF_RANGE();
    1015             : 
    1016             :   /* Test tor_gmtime_r out of range */
    1017             : 
    1018             :   /* time_t < 0 yields a year clamped to 1 or 1970,
    1019             :    * depending on whether the implementation of the system gmtime(_r)
    1020             :    * sets struct tm (1) or not (1970) */
    1021           1 :   t_res = -1;
    1022           1 :   CAPTURE();
    1023           1 :   tor_gmtime_r(&t_res, &b_time);
    1024           1 :   CHECK_POSSIBLE_EINVAL();
    1025           1 :   tt_assert(b_time.tm_year == (1970-1900) ||
    1026             :             b_time.tm_year == (1969-1900));
    1027             : 
    1028           1 :   if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
    1029           1 :     t_res = -1*(1 << 30);
    1030           1 :     CAPTURE();
    1031           1 :     tor_gmtime_r(&t_res, &b_time);
    1032           1 :     CHECK_POSSIBLE_EINVAL();
    1033           1 :     tt_assert(b_time.tm_year == (1970-1900) ||
    1034             :               b_time.tm_year == (1935-1900));
    1035             : 
    1036           1 :     t_res = INT32_MIN;
    1037           1 :     CAPTURE();
    1038           1 :     tor_gmtime_r(&t_res, &b_time);
    1039           1 :     CHECK_POSSIBLE_EINVAL();
    1040           1 :     tt_assert(b_time.tm_year == (1970-1900) ||
    1041             :               b_time.tm_year == (1901-1900));
    1042             :   }
    1043             : 
    1044             : #if SIZEOF_TIME_T == 8
    1045             :   {
    1046             :     /* one of the smallest tm_year values my 64 bit system supports:
    1047             :      * b_time.tm_year == (-292275055LL-1900LL) without clamping */
    1048           1 :     t_res = -9223372036854775LL;
    1049           1 :     CAPTURE();
    1050           1 :     tor_gmtime_r(&t_res, &b_time);
    1051           1 :     CHECK_POSSIBLE_EINVAL();
    1052           1 :     tt_assert(b_time.tm_year == (1970-1900) ||
    1053             :               b_time.tm_year == (1-1900));
    1054             : 
    1055             :     /* while unlikely, the system's gmtime(_r) could return
    1056             :      * a "correct" retrospective gregorian negative year value,
    1057             :      * which I'm pretty sure is:
    1058             :      * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
    1059             :      * 730485 is the number of days in two millennia, including leap days
    1060             :      * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
    1061           1 :     t_res = INT64_MIN;
    1062           1 :     CAPTURE();
    1063           1 :     tor_gmtime_r(&t_res, &b_time);
    1064           1 :     if (! (b_time.tm_year == (1970-1900) ||
    1065             :            b_time.tm_year == (1-1900))) {
    1066           0 :       tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
    1067             :     }
    1068           1 :     if (b_time.tm_year != 1970-1900) {
    1069           0 :       CHECK_TIMEGM_WARNING("Rounding up to ");
    1070             :     } else {
    1071           1 :       teardown_capture_of_logs();
    1072             :     }
    1073             :   }
    1074             :   {
    1075             :     /* As above, but with localtime. */
    1076           1 :     t_res = -9223372036854775LL;
    1077           1 :     CAPTURE();
    1078           1 :     tor_localtime_r(&t_res, &b_time);
    1079           1 :     CHECK_POSSIBLE_EINVAL();
    1080           1 :     tt_assert(b_time.tm_year == (1970-1900) ||
    1081             :               b_time.tm_year == (1-1900));
    1082             : 
    1083             :     /* while unlikely, the system's gmtime(_r) could return
    1084             :      * a "correct" retrospective gregorian negative year value,
    1085             :      * which I'm pretty sure is:
    1086             :      * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
    1087             :      * 730485 is the number of days in two millennia, including leap days
    1088             :      * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
    1089           1 :     t_res = INT64_MIN;
    1090           1 :     CAPTURE();
    1091           1 :     tor_localtime_r(&t_res, &b_time);
    1092           1 :     if (! (b_time.tm_year == (1970-1900) ||
    1093             :            b_time.tm_year == (1-1900))) {
    1094           0 :       tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
    1095             :     }
    1096           1 :     if (b_time.tm_year != 1970-1900) {
    1097           0 :       CHECK_TIMEGM_WARNING("Rounding up to ");
    1098             :     } else {
    1099           1 :       teardown_capture_of_logs();
    1100             :     }
    1101             :   }
    1102             : #endif /* SIZEOF_TIME_T == 8 */
    1103             : 
    1104             :   /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
    1105             :    * depending on whether the implementation of the system gmtime(_r)
    1106             :    * sets struct tm (9999) or not (2037) */
    1107             : #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
    1108             :   {
    1109           1 :     t_res = 3*(1 << 29);
    1110           1 :     tor_gmtime_r(&t_res, &b_time);
    1111           1 :     tt_assert(b_time.tm_year == (2021-1900));
    1112             : 
    1113           1 :     t_res = INT32_MAX;
    1114           1 :     tor_gmtime_r(&t_res, &b_time);
    1115           1 :     tt_assert(b_time.tm_year == (2037-1900) ||
    1116             :               b_time.tm_year == (2038-1900));
    1117             :   }
    1118             :   {
    1119             :     /* as above but with localtime. */
    1120           1 :     t_res = 3*(1 << 29);
    1121           1 :     tor_localtime_r(&t_res, &b_time);
    1122           1 :     tt_assert(b_time.tm_year == (2021-1900));
    1123             : 
    1124           1 :     t_res = INT32_MAX;
    1125           1 :     tor_localtime_r(&t_res, &b_time);
    1126           1 :     tt_assert(b_time.tm_year == (2037-1900) ||
    1127             :               b_time.tm_year == (2038-1900));
    1128             :   }
    1129             : #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */
    1130             : 
    1131             : #if SIZEOF_TIME_T == 8
    1132             :   {
    1133             :     /* one of the largest tm_year values my 64 bit system supports:
    1134             :      * b_time.tm_year == (292278994L-1900L) without clamping */
    1135           1 :     t_res = 9223372036854775LL;
    1136           1 :     CAPTURE();
    1137           1 :     tor_gmtime_r(&t_res, &b_time);
    1138           1 :     CHECK_POSSIBLE_EINVAL();
    1139           1 :     tt_assert(b_time.tm_year == (2037-1900) ||
    1140             :               b_time.tm_year == (9999-1900));
    1141             : 
    1142             :     /* while unlikely, the system's gmtime(_r) could return
    1143             :      * a "correct" proleptic gregorian year value,
    1144             :      * which I'm pretty sure is:
    1145             :      * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
    1146             :      * 730485 is the number of days in two millennia, including leap days
    1147             :      * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
    1148           1 :     t_res = INT64_MAX;
    1149           1 :     CAPTURE();
    1150           1 :     tor_gmtime_r(&t_res, &b_time);
    1151           1 :     CHECK_TIMEGM_WARNING("Rounding down to ");
    1152             : 
    1153           1 :     tt_assert(b_time.tm_year == (2037-1900) ||
    1154             :               b_time.tm_year == (9999-1900));
    1155             :   }
    1156             :   {
    1157             :     /* As above but with localtime. */
    1158           1 :     t_res = 9223372036854775LL;
    1159           1 :     CAPTURE();
    1160           1 :     tor_localtime_r(&t_res, &b_time);
    1161           1 :     CHECK_POSSIBLE_EINVAL();
    1162           1 :     tt_assert(b_time.tm_year == (2037-1900) ||
    1163             :               b_time.tm_year == (9999-1900));
    1164             : 
    1165             :     /* while unlikely, the system's gmtime(_r) could return
    1166             :      * a "correct" proleptic gregorian year value,
    1167             :      * which I'm pretty sure is:
    1168             :      * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
    1169             :      * 730485 is the number of days in two millennia, including leap days
    1170             :      * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
    1171           1 :     t_res = INT64_MAX;
    1172           1 :     CAPTURE();
    1173           1 :     tor_localtime_r(&t_res, &b_time);
    1174           1 :     CHECK_TIMEGM_WARNING("Rounding down to ");
    1175             : 
    1176           1 :     tt_assert(b_time.tm_year == (2037-1900) ||
    1177             :               b_time.tm_year == (9999-1900));
    1178             :   }
    1179             : #endif /* SIZEOF_TIME_T == 8 */
    1180             : 
    1181             :   /* Test {format,parse}_rfc1123_time */
    1182             : 
    1183           1 :   format_rfc1123_time(timestr, 0);
    1184           1 :   tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
    1185           1 :   format_rfc1123_time(timestr, (time_t)1091580502UL);
    1186           1 :   tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
    1187             : 
    1188           1 :   t_res = 0;
    1189           1 :   i = parse_rfc1123_time(timestr, &t_res);
    1190           1 :   tt_int_op(0,OP_EQ, i);
    1191           1 :   tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
    1192             : 
    1193             :   /* This value is in range with 32 bit and 64 bit time_t */
    1194           1 :   format_rfc1123_time(timestr, (time_t)2080000000UL);
    1195           1 :   tt_str_op("Fri, 30 Nov 2035 01:46:40 GMT",OP_EQ, timestr);
    1196             : 
    1197           1 :   t_res = 0;
    1198           1 :   i = parse_rfc1123_time(timestr, &t_res);
    1199           1 :   tt_int_op(0,OP_EQ, i);
    1200           1 :   tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
    1201             : 
    1202             :   /* This value is out of range with 32 bit time_t, but in range for 64 bit
    1203             :    * time_t */
    1204           1 :   CAPTURE();
    1205           1 :   format_rfc1123_time(timestr, (time_t)2150000000UL);
    1206           1 :   CHECK_POSSIBLE_EINVAL();
    1207             : 
    1208             : #if SIZEOF_TIME_T == 4
    1209             : #if 0
    1210             :   /* Wrapping around will have made it this. */
    1211             :   /* On windows, at least, this is clipped to 1 Jan 1970. ??? */
    1212             :   tt_str_op("Sat, 11 Jan 1902 23:45:04 GMT",OP_EQ, timestr);
    1213             : #endif
    1214             :   /* Make sure that the right date doesn't parse. */
    1215             :   strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr));
    1216             : 
    1217             :   t_res = 0;
    1218             :   CAPTURE();
    1219             :   i = parse_rfc1123_time(timestr, &t_res);
    1220             :   CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
    1221             :   tt_int_op(-1,OP_EQ, i);
    1222             : #elif SIZEOF_TIME_T == 8
    1223           1 :   tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr);
    1224             : 
    1225           1 :   t_res = 0;
    1226           1 :   i = parse_rfc1123_time(timestr, &t_res);
    1227           1 :   tt_int_op(0,OP_EQ, i);
    1228           1 :   tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
    1229             : #endif /* SIZEOF_TIME_T == 4 || ... */
    1230             : 
    1231             :   /* The timezone doesn't matter */
    1232           1 :   t_res = 0;
    1233           1 :   tt_int_op(0,OP_EQ,
    1234             :             parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
    1235           1 :   tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
    1236           1 :   tt_int_op(-1,OP_EQ,
    1237             :             parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
    1238           1 :   tt_int_op(-1,OP_EQ,
    1239             :             parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
    1240           1 :   tt_int_op(-1,OP_EQ,
    1241             :             parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
    1242           1 :   tt_int_op(-1,OP_EQ,
    1243             :             parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
    1244           1 :   tt_int_op(-1,OP_EQ,
    1245             :             parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
    1246           1 :   tt_int_op(-1,OP_EQ,
    1247             :             parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
    1248           1 :   tt_int_op(-1,OP_EQ,
    1249             :             parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
    1250           1 :   tt_int_op(-1,OP_EQ,
    1251             :             parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
    1252           1 :   tt_int_op(-1,OP_EQ,
    1253             :             parse_rfc1123_time("Wed, 30 Mar 1900 23:59:59 GMT", &t_res));
    1254             : 
    1255             :   /* Leap year. */
    1256           1 :   tt_int_op(-1,OP_EQ,
    1257             :             parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
    1258           1 :   tt_int_op(0,OP_EQ,
    1259             :             parse_rfc1123_time("Wed, 29 Feb 2012 16:00:00 GMT", &t_res));
    1260             : 
    1261             :   /* Leap second plus one */
    1262           1 :   tt_int_op(-1,OP_EQ,
    1263             :             parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
    1264             : 
    1265             :   /* Test parse_iso_time */
    1266             : 
    1267           1 :   t_res = 0;
    1268           1 :   i = parse_iso_time("", &t_res);
    1269           1 :   tt_int_op(-1,OP_EQ, i);
    1270           1 :   t_res = 0;
    1271           1 :   i = parse_iso_time("2004-08-32 00:48:22", &t_res);
    1272           1 :   tt_int_op(-1,OP_EQ, i);
    1273           1 :   t_res = 0;
    1274           1 :   i = parse_iso_time("1969-08-03 00:48:22", &t_res);
    1275           1 :   tt_int_op(-1,OP_EQ, i);
    1276             : 
    1277           1 :   t_res = 0;
    1278           1 :   i = parse_iso_time("2004-08-04 00:48:22", &t_res);
    1279           1 :   tt_int_op(0,OP_EQ, i);
    1280           1 :   tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
    1281           1 :   t_res = 0;
    1282           1 :   i = parse_iso_time("2004-8-4 0:48:22", &t_res);
    1283           1 :   tt_int_op(0,OP_EQ, i);
    1284           1 :   tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
    1285             : 
    1286             :   /* This value is in range with 32 bit and 64 bit time_t */
    1287           1 :   t_res = 0;
    1288           1 :   i = parse_iso_time("2035-11-30 01:46:40", &t_res);
    1289           1 :   tt_int_op(0,OP_EQ, i);
    1290           1 :   tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
    1291             : 
    1292             :   /* This value is out of range with 32 bit time_t, but in range for 64 bit
    1293             :    * time_t */
    1294           1 :   t_res = 0;
    1295             : #if SIZEOF_TIME_T == 4
    1296             :   CAPTURE();
    1297             :   i = parse_iso_time("2038-02-17 06:13:20", &t_res);
    1298             :   tt_int_op(-1,OP_EQ, i);
    1299             :   CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
    1300             : #elif SIZEOF_TIME_T == 8
    1301           1 :   i = parse_iso_time("2038-02-17 06:13:20", &t_res);
    1302           1 :   tt_int_op(0,OP_EQ, i);
    1303           1 :   tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
    1304             : #endif /* SIZEOF_TIME_T == 4 || ... */
    1305             : 
    1306           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
    1307           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
    1308           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
    1309           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
    1310           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
    1311           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
    1312           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
    1313           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
    1314           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
    1315           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
    1316           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
    1317             : 
    1318             :   /* but... that _is_ acceptable if we aren't being strict. */
    1319           1 :   t_res = 0;
    1320           1 :   i = parse_iso_time_("2004-08-04 00:48:22XYZ", &t_res, 0, 0);
    1321           1 :   tt_int_op(0,OP_EQ, i);
    1322           1 :   tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
    1323             : 
    1324             :   /* try nospace variant. */
    1325           1 :   t_res = 0;
    1326           1 :   i = parse_iso_time_nospace("2004-08-04T00:48:22", &t_res);
    1327           1 :   tt_int_op(0,OP_EQ, i);
    1328           1 :   tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
    1329             : 
    1330           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04T00:48:22", &t_res));
    1331           1 :   tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04 00:48:22", &t_res));
    1332           1 :   tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04x00:48:22", &t_res));
    1333           1 :   tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04x00:48:22", &t_res));
    1334             : 
    1335             :   /* Test tor_gettimeofday */
    1336             : 
    1337           1 :   end.tv_sec = 4;
    1338           1 :   end.tv_usec = 999990;
    1339           1 :   start.tv_sec = 1;
    1340           1 :   start.tv_usec = 500;
    1341             : 
    1342           1 :   tor_gettimeofday(&start);
    1343             :   /* now make sure time works. */
    1344           1 :   tor_gettimeofday(&end);
    1345             :   /* We might've timewarped a little. */
    1346           1 :   tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
    1347             : 
    1348             :   /* Test format_iso_time */
    1349             : 
    1350           1 :   tv.tv_sec = (time_t)1326296338UL;
    1351           1 :   tv.tv_usec = 3060;
    1352           1 :   format_iso_time(timestr, (time_t)tv.tv_sec);
    1353           1 :   tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
    1354             :   /* The output of format_local_iso_time will vary by timezone, and setting
    1355             :      our timezone for testing purposes would be a nontrivial flaky pain.
    1356             :      Skip this test for now.
    1357             :   format_local_iso_time(timestr, tv.tv_sec);
    1358             :   test_streq("2012-01-11 10:38:58", timestr);
    1359             :   */
    1360           1 :   format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
    1361           1 :   tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
    1362           1 :   tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
    1363           1 :   format_iso_time_nospace_usec(timestr, &tv);
    1364           1 :   tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
    1365           1 :   tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
    1366             : 
    1367           1 :   tv.tv_usec = 0;
    1368             :   /* This value is in range with 32 bit and 64 bit time_t */
    1369           1 :   tv.tv_sec = (time_t)2080000000UL;
    1370           1 :   format_iso_time(timestr, (time_t)tv.tv_sec);
    1371           1 :   tt_str_op("2035-11-30 01:46:40",OP_EQ, timestr);
    1372             : 
    1373             :   /* This value is out of range with 32 bit time_t, but in range for 64 bit
    1374             :    * time_t */
    1375           1 :   tv.tv_sec = (time_t)2150000000UL;
    1376           1 :   CAPTURE();
    1377           1 :   format_iso_time(timestr, (time_t)tv.tv_sec);
    1378           1 :   CHECK_POSSIBLE_EINVAL();
    1379             : #if SIZEOF_TIME_T == 4
    1380             :   /* format_iso_time should indicate failure on overflow, but it doesn't yet.
    1381             :    * Hopefully #18480 will improve the failure semantics in this case.
    1382             :    tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
    1383             :    */
    1384             : #elif SIZEOF_TIME_T == 8
    1385             : #ifndef _WIN32
    1386             :   /* This SHOULD work on windows too; see bug #18665 */
    1387           1 :   tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
    1388             : #endif
    1389             : #endif /* SIZEOF_TIME_T == 4 || ... */
    1390             : 
    1391             : #undef CAPTURE
    1392             : #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE
    1393             : #undef CHECK_POSSIBLE_EINVAL
    1394             : 
    1395           1 :  done:
    1396           1 :   teardown_capture_of_logs();
    1397           1 : }
    1398             : 
    1399             : static void
    1400           1 : test_util_parse_http_time(void *arg)
    1401             : {
    1402           1 :   struct tm a_time;
    1403           1 :   char b[ISO_TIME_LEN+1];
    1404           1 :   (void)arg;
    1405             : 
    1406             : #define T(s) do {                               \
    1407             :     format_iso_time(b, tor_timegm(&a_time));    \
    1408             :     tt_str_op(b, OP_EQ, (s));                      \
    1409             :     b[0]='\0';                                  \
    1410             :   } while (0)
    1411             : 
    1412             :   /* Test parse_http_time */
    1413             : 
    1414           1 :   tt_int_op(-1,OP_EQ,
    1415             :             parse_http_time("", &a_time));
    1416           1 :   tt_int_op(-1,OP_EQ,
    1417             :             parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
    1418           1 :   tt_int_op(-1,OP_EQ,
    1419             :             parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
    1420           1 :   tt_int_op(-1,OP_EQ,
    1421             :             parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
    1422           1 :   tt_int_op(-1,OP_EQ,
    1423             :             parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
    1424           1 :   tt_int_op(-1,OP_EQ,
    1425             :             parse_http_time("Sunday, August the third", &a_time));
    1426           1 :   tt_int_op(-1,OP_EQ,
    1427             :             parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
    1428             : 
    1429           1 :   tt_int_op(0,OP_EQ,
    1430             :             parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
    1431           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1432           1 :   T("1994-08-04 00:48:22");
    1433           1 :   tt_int_op(0,OP_EQ,
    1434             :             parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
    1435           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1436           1 :   T("1994-08-04 00:48:22");
    1437           1 :   tt_int_op(0,OP_EQ,
    1438             :             parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
    1439           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1440           1 :   T("1994-08-04 00:48:22");
    1441           1 :   tt_int_op(0,OP_EQ,
    1442             :             parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
    1443           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1444           1 :   T("1994-08-04 00:48:22");
    1445           1 :   tt_int_op(0,OP_EQ,
    1446             :             parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
    1447           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1448           1 :   T("1994-08-04 00:48:22");
    1449           1 :   tt_int_op(0,OP_EQ,
    1450             :             parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
    1451           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1452           1 :   T("1994-08-04 00:48:22");
    1453           1 :   tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
    1454           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1455           1 :   T("1994-08-04 00:48:22");
    1456           1 :   tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
    1457           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1458           1 :   T("1994-08-04 00:48:22");
    1459           1 :   tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
    1460           1 :   tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
    1461           1 :   T("1994-08-04 00:48:22");
    1462           1 :   tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
    1463           1 :   tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
    1464           1 :   T("2012-01-01 00:00:00");
    1465           1 :   tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
    1466           1 :   tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
    1467           1 :   T("2012-12-31 00:00:00");
    1468             : 
    1469             :   /* This value is in range with 32 bit and 64 bit time_t */
    1470           1 :   tt_int_op(0,OP_EQ,parse_http_time("Fri, 30 Nov 2035 01:46:40 GMT", &a_time));
    1471           1 :   tt_int_op((time_t)2080000000UL,OP_EQ, tor_timegm(&a_time));
    1472           1 :   T("2035-11-30 01:46:40");
    1473             : 
    1474             :   /* This value is out of range with 32 bit time_t, but in range for 64 bit
    1475             :    * time_t */
    1476             : #if SIZEOF_TIME_T == 4
    1477             :   /* parse_http_time should indicate failure on overflow, but it doesn't yet.
    1478             :    * Hopefully #18480 will improve the failure semantics in this case. */
    1479             :   setup_full_capture_of_logs(LOG_WARN);
    1480             :   tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
    1481             :   tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time));
    1482             :   expect_single_log_msg_containing("does not fit in tor_timegm");
    1483             :   teardown_capture_of_logs();
    1484             : #elif SIZEOF_TIME_T == 8
    1485           1 :   tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
    1486           1 :   tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time));
    1487           1 :   T("2038-02-17 06:13:20");
    1488             : #endif /* SIZEOF_TIME_T == 4 || ... */
    1489             : 
    1490           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
    1491           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
    1492           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
    1493           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
    1494           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
    1495           1 :   tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
    1496           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
    1497           1 :   tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
    1498             : 
    1499             : #undef T
    1500           1 :  done:
    1501           1 :   teardown_capture_of_logs();
    1502           1 : }
    1503             : 
    1504             : static void
    1505           1 : test_util_config_line(void *arg)
    1506             : {
    1507           1 :   char buf[1024];
    1508           1 :   char *k=NULL, *v=NULL;
    1509           1 :   const char *str;
    1510             : 
    1511             :   /* Test parse_config_line_from_str */
    1512           1 :   (void)arg;
    1513           1 :   strlcpy(buf, "k v\n" " key    value with spaces   \n" "keykey val\n"
    1514             :           "k2\n"
    1515             :           "k3 \n" "\n" "   \n" "#comment\n"
    1516             :           "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
    1517             :           "kseven   \"a quoted 'string\"\n"
    1518             :           "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
    1519             :           "k9 a line that\\\n spans two lines.\n\n"
    1520             :           "k10 more than\\\n one contin\\\nuation\n"
    1521             :           "k11  \\\ncontinuation at the start\n"
    1522             :           "k12 line with a\\\n#comment\n embedded\n"
    1523             :           "k13\\\ncontinuation at the very start\n"
    1524             :           "k14 a line that has a comment and # ends with a slash \\\n"
    1525             :           "k15 this should be the next new line\n"
    1526             :           "k16 a line that has a comment and # ends without a slash \n"
    1527             :           "k17 this should be the next new line\n"
    1528             :           , sizeof(buf));
    1529           1 :   str = buf;
    1530             : 
    1531           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1532           1 :   tt_str_op(k,OP_EQ, "k");
    1533           1 :   tt_str_op(v,OP_EQ, "v");
    1534           1 :   tor_free(k); tor_free(v);
    1535           1 :   tt_assert(!strcmpstart(str, "key    value with"));
    1536             : 
    1537           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1538           1 :   tt_str_op(k,OP_EQ, "key");
    1539           1 :   tt_str_op(v,OP_EQ, "value with spaces");
    1540           1 :   tor_free(k); tor_free(v);
    1541           1 :   tt_assert(!strcmpstart(str, "keykey"));
    1542             : 
    1543           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1544           1 :   tt_str_op(k,OP_EQ, "keykey");
    1545           1 :   tt_str_op(v,OP_EQ, "val");
    1546           1 :   tor_free(k); tor_free(v);
    1547           1 :   tt_assert(!strcmpstart(str, "k2\n"));
    1548             : 
    1549           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1550           1 :   tt_str_op(k,OP_EQ, "k2");
    1551           1 :   tt_str_op(v,OP_EQ, "");
    1552           1 :   tor_free(k); tor_free(v);
    1553           1 :   tt_assert(!strcmpstart(str, "k3 \n"));
    1554             : 
    1555           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1556           1 :   tt_str_op(k,OP_EQ, "k3");
    1557           1 :   tt_str_op(v,OP_EQ, "");
    1558           1 :   tor_free(k); tor_free(v);
    1559           1 :   tt_assert(!strcmpstart(str, "#comment"));
    1560             : 
    1561           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1562           1 :   tt_str_op(k,OP_EQ, "k4");
    1563           1 :   tt_str_op(v,OP_EQ, "");
    1564           1 :   tor_free(k); tor_free(v);
    1565           1 :   tt_assert(!strcmpstart(str, "k5#abc"));
    1566             : 
    1567           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1568           1 :   tt_str_op(k,OP_EQ, "k5");
    1569           1 :   tt_str_op(v,OP_EQ, "");
    1570           1 :   tor_free(k); tor_free(v);
    1571           1 :   tt_assert(!strcmpstart(str, "k6"));
    1572             : 
    1573           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1574           1 :   tt_str_op(k,OP_EQ, "k6");
    1575           1 :   tt_str_op(v,OP_EQ, "val");
    1576           1 :   tor_free(k); tor_free(v);
    1577           1 :   tt_assert(!strcmpstart(str, "kseven"));
    1578             : 
    1579           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1580           1 :   tt_str_op(k,OP_EQ, "kseven");
    1581           1 :   tt_str_op(v,OP_EQ, "a quoted \'string");
    1582           1 :   tor_free(k); tor_free(v);
    1583           1 :   tt_assert(!strcmpstart(str, "k8 "));
    1584             : 
    1585           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1586           1 :   tt_str_op(k,OP_EQ, "k8");
    1587           1 :   tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
    1588           1 :   tor_free(k); tor_free(v);
    1589             : 
    1590           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1591           1 :   tt_str_op(k,OP_EQ, "k9");
    1592           1 :   tt_str_op(v,OP_EQ, "a line that spans two lines.");
    1593           1 :   tor_free(k); tor_free(v);
    1594             : 
    1595           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1596           1 :   tt_str_op(k,OP_EQ, "k10");
    1597           1 :   tt_str_op(v,OP_EQ, "more than one continuation");
    1598           1 :   tor_free(k); tor_free(v);
    1599             : 
    1600           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1601           1 :   tt_str_op(k,OP_EQ, "k11");
    1602           1 :   tt_str_op(v,OP_EQ, "continuation at the start");
    1603           1 :   tor_free(k); tor_free(v);
    1604             : 
    1605           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1606           1 :   tt_str_op(k,OP_EQ, "k12");
    1607           1 :   tt_str_op(v,OP_EQ, "line with a embedded");
    1608           1 :   tor_free(k); tor_free(v);
    1609             : 
    1610           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1611           1 :   tt_str_op(k,OP_EQ, "k13");
    1612           1 :   tt_str_op(v,OP_EQ, "continuation at the very start");
    1613           1 :   tor_free(k); tor_free(v);
    1614             : 
    1615           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1616           1 :   tt_str_op(k,OP_EQ, "k14");
    1617           1 :   tt_str_op(v,OP_EQ, "a line that has a comment and" );
    1618           1 :   tor_free(k); tor_free(v);
    1619             : 
    1620           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1621           1 :   tt_str_op(k,OP_EQ, "k15");
    1622           1 :   tt_str_op(v,OP_EQ, "this should be the next new line");
    1623           1 :   tor_free(k); tor_free(v);
    1624             : 
    1625           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1626           1 :   tt_str_op(k,OP_EQ, "k16");
    1627           1 :   tt_str_op(v,OP_EQ, "a line that has a comment and" );
    1628           1 :   tor_free(k); tor_free(v);
    1629             : 
    1630           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1631           1 :   tt_str_op(k,OP_EQ, "k17");
    1632           1 :   tt_str_op(v,OP_EQ, "this should be the next new line");
    1633           1 :   tor_free(k); tor_free(v);
    1634             : 
    1635           1 :   tt_str_op(str,OP_EQ, "");
    1636             : 
    1637           1 :  done:
    1638           1 :   tor_free(k);
    1639           1 :   tor_free(v);
    1640           1 : }
    1641             : 
    1642             : static void
    1643           1 : test_util_config_line_quotes(void *arg)
    1644             : {
    1645           1 :   char buf1[1024];
    1646           1 :   char buf2[128];
    1647           1 :   char buf3[128];
    1648           1 :   char buf4[128];
    1649           1 :   char *k=NULL, *v=NULL;
    1650           1 :   const char *str;
    1651             : 
    1652             :   /* Test parse_config_line_from_str */
    1653           1 :   (void)arg;
    1654           1 :   strlcpy(buf1, "kTrailingSpace \"quoted value\"   \n"
    1655             :           "kTrailingGarbage \"quoted value\"trailing garbage\n"
    1656             :           , sizeof(buf1));
    1657           1 :   strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
    1658             :           , sizeof(buf2));
    1659           1 :   strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
    1660             :           , sizeof(buf3));
    1661           1 :   strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
    1662             :           , sizeof(buf4));
    1663           1 :   str = buf1;
    1664             : 
    1665           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1666           1 :   tt_str_op(k,OP_EQ, "kTrailingSpace");
    1667           1 :   tt_str_op(v,OP_EQ, "quoted value");
    1668           1 :   tor_free(k); tor_free(v);
    1669             : 
    1670           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1671           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1672           1 :   tor_free(k); tor_free(v);
    1673             : 
    1674           1 :   str = buf2;
    1675             : 
    1676           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1677           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1678           1 :   tor_free(k); tor_free(v);
    1679             : 
    1680           1 :   str = buf3;
    1681             : 
    1682           1 :   const char *err = NULL;
    1683           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, &err);
    1684           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1685           1 :   tor_free(k); tor_free(v);
    1686           1 :   tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
    1687             : 
    1688           1 :   str = buf4;
    1689             : 
    1690           1 :   err = NULL;
    1691           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, &err);
    1692           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1693           1 :   tor_free(k); tor_free(v);
    1694           1 :   tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
    1695             : 
    1696           1 :  done:
    1697           1 :   tor_free(k);
    1698           1 :   tor_free(v);
    1699           1 : }
    1700             : 
    1701             : static void
    1702           1 : test_util_config_line_comment_character(void *arg)
    1703             : {
    1704           1 :   char buf[1024];
    1705           1 :   char *k=NULL, *v=NULL;
    1706           1 :   const char *str;
    1707             : 
    1708             :   /* Test parse_config_line_from_str */
    1709           1 :   (void)arg;
    1710           1 :   strlcpy(buf, "k1 \"# in quotes\"\n"
    1711             :           "k2 some value    # some comment\n"
    1712             :           "k3 /home/user/myTorNetwork#2\n"    /* Testcase for #1323 */
    1713             :           , sizeof(buf));
    1714           1 :   str = buf;
    1715             : 
    1716           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1717           1 :   tt_str_op(k,OP_EQ, "k1");
    1718           1 :   tt_str_op(v,OP_EQ, "# in quotes");
    1719           1 :   tor_free(k); tor_free(v);
    1720             : 
    1721           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1722           1 :   tt_str_op(k,OP_EQ, "k2");
    1723           1 :   tt_str_op(v,OP_EQ, "some value");
    1724           1 :   tor_free(k); tor_free(v);
    1725             : 
    1726           1 :   tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
    1727             : 
    1728             : #if 0
    1729             :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1730             :   test_streq(k, "k3");
    1731             :   test_streq(v, "/home/user/myTorNetwork#2");
    1732             :   tor_free(k); tor_free(v);
    1733             : 
    1734             :   test_streq(str, "");
    1735             : #endif /* 0 */
    1736             : 
    1737           1 :  done:
    1738           1 :   tor_free(k);
    1739           1 :   tor_free(v);
    1740           1 : }
    1741             : 
    1742             : static void
    1743           1 : test_util_config_line_escaped_content(void *arg)
    1744             : {
    1745           1 :   char buf1[1024];
    1746           1 :   char buf2[128];
    1747           1 :   char buf3[128];
    1748           1 :   char buf4[128];
    1749           1 :   char buf5[128];
    1750           1 :   char buf6[128];
    1751           1 :   char *k=NULL, *v=NULL;
    1752           1 :   const char *str;
    1753             : 
    1754             :   /* Test parse_config_line_from_str */
    1755           1 :   (void)arg;
    1756           1 :   strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
    1757             :           "HexadecimalUpper \"\\x2A\"\n"
    1758             :           "HexadecimalUpperX \"\\X2A\"\n"
    1759             :           "Octal \"\\52\"\n"
    1760             :           "Newline \"\\n\"\n"
    1761             :           "Tab \"\\t\"\n"
    1762             :           "CarriageReturn \"\\r\"\n"
    1763             :           "DoubleQuote \"\\\"\"\n"
    1764             :           "SimpleQuote \"\\'\"\n"
    1765             :           "Backslash \"\\\\\"\n"
    1766             :           "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
    1767             :           , sizeof(buf1));
    1768             : 
    1769           1 :   strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
    1770             :           , sizeof(buf2));
    1771             : 
    1772           1 :   strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
    1773             :           , sizeof(buf3));
    1774             : 
    1775           1 :   strlcpy(buf4, "BrokenOctal \"\\8\"\n"
    1776             :           , sizeof(buf4));
    1777             : 
    1778           1 :   strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
    1779             :           , sizeof(buf5));
    1780             : 
    1781           1 :   strlcpy(buf6, "BrokenEscape \"\\"
    1782             :           , sizeof(buf6));
    1783             : 
    1784           1 :   str = buf1;
    1785             : 
    1786           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1787           1 :   tt_str_op(k,OP_EQ, "HexadecimalLower");
    1788           1 :   tt_str_op(v,OP_EQ, "*");
    1789           1 :   tor_free(k); tor_free(v);
    1790             : 
    1791           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1792           1 :   tt_str_op(k,OP_EQ, "HexadecimalUpper");
    1793           1 :   tt_str_op(v,OP_EQ, "*");
    1794           1 :   tor_free(k); tor_free(v);
    1795             : 
    1796           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1797           1 :   tt_str_op(k,OP_EQ, "HexadecimalUpperX");
    1798           1 :   tt_str_op(v,OP_EQ, "*");
    1799           1 :   tor_free(k); tor_free(v);
    1800             : 
    1801           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1802           1 :   tt_str_op(k,OP_EQ, "Octal");
    1803           1 :   tt_str_op(v,OP_EQ, "*");
    1804           1 :   tor_free(k); tor_free(v);
    1805             : 
    1806           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1807           1 :   tt_str_op(k,OP_EQ, "Newline");
    1808           1 :   tt_str_op(v,OP_EQ, "\n");
    1809           1 :   tor_free(k); tor_free(v);
    1810             : 
    1811           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1812           1 :   tt_str_op(k,OP_EQ, "Tab");
    1813           1 :   tt_str_op(v,OP_EQ, "\t");
    1814           1 :   tor_free(k); tor_free(v);
    1815             : 
    1816           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1817           1 :   tt_str_op(k,OP_EQ, "CarriageReturn");
    1818           1 :   tt_str_op(v,OP_EQ, "\r");
    1819           1 :   tor_free(k); tor_free(v);
    1820             : 
    1821           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1822           1 :   tt_str_op(k,OP_EQ, "DoubleQuote");
    1823           1 :   tt_str_op(v,OP_EQ, "\"");
    1824           1 :   tor_free(k); tor_free(v);
    1825             : 
    1826           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1827           1 :   tt_str_op(k,OP_EQ, "SimpleQuote");
    1828           1 :   tt_str_op(v,OP_EQ, "'");
    1829           1 :   tor_free(k); tor_free(v);
    1830             : 
    1831           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1832           1 :   tt_str_op(k,OP_EQ, "Backslash");
    1833           1 :   tt_str_op(v,OP_EQ, "\\");
    1834           1 :   tor_free(k); tor_free(v);
    1835             : 
    1836           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1837           1 :   tt_str_op(k,OP_EQ, "Mix");
    1838           1 :   tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
    1839           1 :   tor_free(k); tor_free(v);
    1840           1 :   tt_str_op(str,OP_EQ, "");
    1841             : 
    1842           1 :   str = buf2;
    1843             : 
    1844           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1845           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1846           1 :   tor_free(k); tor_free(v);
    1847             : 
    1848           1 :   str = buf3;
    1849             : 
    1850           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1851           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1852           1 :   tor_free(k); tor_free(v);
    1853             : 
    1854           1 :   str = buf4;
    1855             : 
    1856           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1857           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1858           1 :   tor_free(k); tor_free(v);
    1859             : 
    1860             : #if 0
    1861             :   str = buf5;
    1862             : 
    1863             :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1864             :   tt_ptr_op(str, OP_EQ, NULL);
    1865             :   tor_free(k); tor_free(v);
    1866             : #endif /* 0 */
    1867             : 
    1868           1 :   str = buf6;
    1869             : 
    1870           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1871           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1872           1 :   tor_free(k); tor_free(v);
    1873             : 
    1874             :   /* more things to try. */
    1875             :   /* Bad hex: */
    1876           1 :   strlcpy(buf1, "Foo \"\\x9g\"\n", sizeof(buf1));
    1877           1 :   strlcpy(buf2, "Foo \"\\xg0\"\n", sizeof(buf2));
    1878           1 :   strlcpy(buf3, "Foo \"\\xf\"\n", sizeof(buf3));
    1879             :   /* bad escape */
    1880           1 :   strlcpy(buf4, "Foo \"\\q\"\n", sizeof(buf4));
    1881             :   /* missing endquote */
    1882           1 :   strlcpy(buf5, "Foo \"hello\n", sizeof(buf5));
    1883             :   /* extra stuff */
    1884           1 :   strlcpy(buf6, "Foo \"hello\" world\n", sizeof(buf6));
    1885             : 
    1886           1 :   str=buf1;
    1887           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1888           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1889           1 :   tor_free(k); tor_free(v);
    1890             : 
    1891           1 :   str=buf2;
    1892           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1893           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1894           1 :   tor_free(k); tor_free(v);
    1895             : 
    1896           1 :   str=buf3;
    1897           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1898           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1899           1 :   tor_free(k); tor_free(v);
    1900             : 
    1901           1 :   str=buf4;
    1902           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1903           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1904           1 :   tor_free(k); tor_free(v);
    1905             : 
    1906           1 :   str=buf5;
    1907             : 
    1908           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
    1909           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1910           1 :   tor_free(k); tor_free(v);
    1911             : 
    1912           1 :   str=buf6;
    1913           1 :   const char *err = NULL;
    1914           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, &err);
    1915           1 :   tt_ptr_op(str,OP_EQ, NULL);
    1916           1 :   tor_free(k); tor_free(v);
    1917           1 :   tt_str_op(err,OP_EQ, "Excess data after quoted string");
    1918             : 
    1919           1 :  done:
    1920           1 :   tor_free(k);
    1921           1 :   tor_free(v);
    1922           1 : }
    1923             : 
    1924             : static void
    1925           1 : test_util_config_line_crlf(void *arg)
    1926             : {
    1927           1 :   char *k=NULL, *v=NULL;
    1928           1 :   const char *err = NULL;
    1929           1 :   (void)arg;
    1930           1 :   const char *str =
    1931             :     "Hello world\r\n"
    1932             :     "Hello \"nice big world\"\r\n";
    1933             : 
    1934           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, &err);
    1935           1 :   tt_assert(str);
    1936           1 :   tt_str_op(k,OP_EQ,"Hello");
    1937           1 :   tt_str_op(v,OP_EQ,"world");
    1938           1 :   tt_ptr_op(err, OP_EQ, NULL);
    1939           1 :   tor_free(k); tor_free(v);
    1940             : 
    1941           1 :   str = parse_config_line_from_str_verbose(str, &k, &v, &err);
    1942           1 :   tt_assert(str);
    1943           1 :   tt_str_op(k,OP_EQ,"Hello");
    1944           1 :   tt_str_op(v,OP_EQ,"nice big world");
    1945           1 :   tt_ptr_op(err, OP_EQ, NULL);
    1946           1 :   tor_free(k); tor_free(v);
    1947           1 :   tt_str_op(str,OP_EQ, "");
    1948             : 
    1949           1 :  done:
    1950           1 :   tor_free(k); tor_free(v);
    1951           1 : }
    1952             : 
    1953             : static void
    1954           1 : test_util_config_line_partition(void *arg)
    1955             : {
    1956           1 :   (void)arg;
    1957           1 :   config_line_t *lines = NULL, *orig, *rest = NULL;
    1958             : 
    1959           1 :   config_line_append(&lines, "Header", "X");
    1960           1 :   config_line_append(&lines, "Item", "Y");
    1961           1 :   config_line_append(&lines, "Thing", "Z");
    1962             : 
    1963           1 :   config_line_append(&lines, "HEADER", "X2");
    1964             : 
    1965           1 :   config_line_append(&lines, "header", "X3");
    1966           1 :   config_line_append(&lines, "Item3", "Foob");
    1967             : 
    1968             :   /* set up h2 and h3 to point to the places where we hope the headers will
    1969             :      be. */
    1970           1 :   config_line_t *h2 = lines->next->next->next;
    1971           1 :   config_line_t *h3 = h2->next;
    1972           1 :   tt_str_op(h2->key, OP_EQ, "HEADER");
    1973           1 :   tt_str_op(h3->key, OP_EQ, "header");
    1974             : 
    1975           1 :   orig = lines;
    1976           1 :   rest = config_lines_partition(lines, "Header");
    1977           1 :   tt_ptr_op(lines, OP_EQ, orig);
    1978           1 :   tt_ptr_op(rest, OP_EQ, h2);
    1979           1 :   tt_str_op(lines->next->key, OP_EQ, "Item");
    1980           1 :   tt_str_op(lines->next->next->key, OP_EQ, "Thing");
    1981           1 :   tt_ptr_op(lines->next->next->next, OP_EQ, NULL);
    1982           1 :   config_free_lines(lines);
    1983             : 
    1984           1 :   orig = lines = rest;
    1985           1 :   rest = config_lines_partition(lines, "Header");
    1986           1 :   tt_ptr_op(lines, OP_EQ, orig);
    1987           1 :   tt_ptr_op(rest, OP_EQ, h3);
    1988           1 :   tt_ptr_op(lines->next, OP_EQ, NULL);
    1989           1 :   config_free_lines(lines);
    1990             : 
    1991           1 :   orig = lines = rest;
    1992           1 :   rest = config_lines_partition(lines, "Header");
    1993           1 :   tt_ptr_op(lines, OP_EQ, orig);
    1994           1 :   tt_ptr_op(rest, OP_EQ, NULL);
    1995           1 :   tt_str_op(lines->next->key, OP_EQ, "Item3");
    1996           1 :   tt_ptr_op(lines->next->next, OP_EQ, NULL);
    1997             : 
    1998           1 :  done:
    1999           1 :   config_free_lines(lines);
    2000           1 :   config_free_lines(rest);
    2001           1 : }
    2002             : 
    2003             : #ifndef DISABLE_PWDB_TESTS
    2004             : static void
    2005           1 : test_util_expand_filename(void *arg)
    2006             : {
    2007           1 :   char *str;
    2008             : 
    2009           1 :   (void)arg;
    2010           1 :   setenv("HOME", "/home/itv", 1); /* For "internal test value" */
    2011             : 
    2012           1 :   str = expand_filename("");
    2013           1 :   tt_str_op("",OP_EQ, str);
    2014           1 :   tor_free(str);
    2015             : 
    2016           1 :   str = expand_filename("/normal/path");
    2017           1 :   tt_str_op("/normal/path",OP_EQ, str);
    2018           1 :   tor_free(str);
    2019             : 
    2020           1 :   str = expand_filename("/normal/trailing/path/");
    2021           1 :   tt_str_op("/normal/trailing/path/",OP_EQ, str);
    2022           1 :   tor_free(str);
    2023             : 
    2024           1 :   str = expand_filename("~");
    2025           1 :   tt_str_op("/home/itv/",OP_EQ, str);
    2026           1 :   tor_free(str);
    2027             : 
    2028           1 :   str = expand_filename("$HOME/nodice");
    2029           1 :   tt_str_op("$HOME/nodice",OP_EQ, str);
    2030           1 :   tor_free(str);
    2031             : 
    2032           1 :   str = expand_filename("~/");
    2033           1 :   tt_str_op("/home/itv/",OP_EQ, str);
    2034           1 :   tor_free(str);
    2035             : 
    2036           1 :   str = expand_filename("~/foobarqux");
    2037           1 :   tt_str_op("/home/itv/foobarqux",OP_EQ, str);
    2038           1 :   tor_free(str);
    2039             : 
    2040           1 :   str = expand_filename("~/../../etc/passwd");
    2041           1 :   tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
    2042           1 :   tor_free(str);
    2043             : 
    2044           1 :   str = expand_filename("~/trailing/");
    2045           1 :   tt_str_op("/home/itv/trailing/",OP_EQ, str);
    2046           1 :   tor_free(str);
    2047             :   /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
    2048             :      have to somehow inject/fake the get_user_homedir call) */
    2049             : 
    2050             :   /* $HOME ending in a trailing slash */
    2051           1 :   setenv("HOME", "/home/itv/", 1);
    2052             : 
    2053           1 :   str = expand_filename("~");
    2054           1 :   tt_str_op("/home/itv/",OP_EQ, str);
    2055           1 :   tor_free(str);
    2056             : 
    2057           1 :   str = expand_filename("~/");
    2058           1 :   tt_str_op("/home/itv/",OP_EQ, str);
    2059           1 :   tor_free(str);
    2060             : 
    2061           1 :   str = expand_filename("~/foo");
    2062           1 :   tt_str_op("/home/itv/foo",OP_EQ, str);
    2063           1 :   tor_free(str);
    2064             : 
    2065             :   /* Try with empty $HOME */
    2066             : 
    2067           1 :   setenv("HOME", "", 1);
    2068             : 
    2069           1 :   str = expand_filename("~");
    2070           1 :   tt_str_op("/",OP_EQ, str);
    2071           1 :   tor_free(str);
    2072             : 
    2073           1 :   str = expand_filename("~/");
    2074           1 :   tt_str_op("/",OP_EQ, str);
    2075           1 :   tor_free(str);
    2076             : 
    2077           1 :   str = expand_filename("~/foobar");
    2078           1 :   tt_str_op("/foobar",OP_EQ, str);
    2079           1 :   tor_free(str);
    2080             : 
    2081             :   /* Try with $HOME unset */
    2082             : 
    2083           1 :   unsetenv("HOME");
    2084             : 
    2085           1 :   str = expand_filename("~");
    2086           1 :   tt_str_op("/",OP_EQ, str);
    2087           1 :   tor_free(str);
    2088             : 
    2089           1 :   str = expand_filename("~/");
    2090           1 :   tt_str_op("/",OP_EQ, str);
    2091           1 :   tor_free(str);
    2092             : 
    2093           1 :   str = expand_filename("~/foobar");
    2094           1 :   tt_str_op("/foobar",OP_EQ, str);
    2095           1 :   tor_free(str);
    2096             : 
    2097           1 :  done:
    2098           1 :   tor_free(str);
    2099           1 : }
    2100             : #endif /* !defined(DISABLE_PWDB_TESTS) */
    2101             : 
    2102             : /** Test tor_escape_str_for_pt_args(). */
    2103             : static void
    2104           1 : test_util_escape_string_socks(void *arg)
    2105             : {
    2106           1 :   char *escaped_string = NULL;
    2107             : 
    2108             :   /** Simple backslash escape. */
    2109           1 :   (void)arg;
    2110           1 :   escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
    2111           1 :   tt_assert(escaped_string);
    2112           1 :   tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
    2113           1 :   tor_free(escaped_string);
    2114             : 
    2115             :   /** Simple semicolon escape. */
    2116           1 :   escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
    2117           1 :   tt_assert(escaped_string);
    2118           1 :   tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
    2119           1 :   tor_free(escaped_string);
    2120             : 
    2121             :   /** Empty string. */
    2122           1 :   escaped_string = tor_escape_str_for_pt_args("", ";\\");
    2123           1 :   tt_assert(escaped_string);
    2124           1 :   tt_str_op(escaped_string,OP_EQ, "");
    2125           1 :   tor_free(escaped_string);
    2126             : 
    2127             :   /** Escape all characters. */
    2128           1 :   escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
    2129           1 :   tt_assert(escaped_string);
    2130           1 :   tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
    2131           1 :   tor_free(escaped_string);
    2132             : 
    2133           1 :   escaped_string = tor_escape_str_for_pt_args(";", ";\\");
    2134           1 :   tt_assert(escaped_string);
    2135           1 :   tt_str_op(escaped_string,OP_EQ, "\\;");
    2136           1 :   tor_free(escaped_string);
    2137             : 
    2138           1 :  done:
    2139           1 :   tor_free(escaped_string);
    2140           1 : }
    2141             : 
    2142             : static void
    2143           1 : test_util_string_is_key_value(void *ptr)
    2144             : {
    2145           1 :   (void)ptr;
    2146           1 :   tt_assert(string_is_key_value(LOG_WARN, "key=value"));
    2147           1 :   tt_assert(string_is_key_value(LOG_WARN, "k=v"));
    2148           1 :   tt_assert(string_is_key_value(LOG_WARN, "key="));
    2149           1 :   tt_assert(string_is_key_value(LOG_WARN, "x="));
    2150           1 :   tt_assert(string_is_key_value(LOG_WARN, "xx="));
    2151           1 :   tt_assert(!string_is_key_value(LOG_WARN, "=value"));
    2152           1 :   tt_assert(!string_is_key_value(LOG_WARN, "=x"));
    2153           1 :   tt_assert(!string_is_key_value(LOG_WARN, "="));
    2154             : 
    2155             :   /* ??? */
    2156             :   /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
    2157           1 :  done:
    2158           1 :   ;
    2159           1 : }
    2160             : 
    2161             : /** Test basic string functionality. */
    2162             : static void
    2163           1 : test_util_strmisc(void *arg)
    2164             : {
    2165           1 :   char buf[1024];
    2166           1 :   char *cp_tmp = NULL;
    2167             : 
    2168             :   /* Test strl operations */
    2169           1 :   (void)arg;
    2170           1 :   tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
    2171           1 :   tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
    2172           1 :   tt_str_op(buf,OP_EQ, "Hello");
    2173           1 :   tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
    2174           1 :   tt_str_op(buf,OP_EQ, "Hello");
    2175           1 :   tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
    2176           1 :   tt_str_op(buf,OP_EQ, "Hell");
    2177           1 :   strlcpy(buf, "Hello", sizeof(buf));
    2178           1 :   tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
    2179             : 
    2180             :   /* Test strstrip() */
    2181           1 :   strlcpy(buf, "Testing 1 2 3", sizeof(buf));
    2182           1 :   tor_strstrip(buf, ",!");
    2183           1 :   tt_str_op(buf,OP_EQ, "Testing 1 2 3");
    2184           1 :   strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
    2185           1 :   tor_strstrip(buf, "!? ");
    2186           1 :   tt_str_op(buf,OP_EQ, "Testing123");
    2187           1 :   strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
    2188           1 :   tor_strstrip(buf, "!? ");
    2189           1 :   tt_str_op(buf,OP_EQ, "Testing123");
    2190             : 
    2191             :   /* Test snprintf */
    2192             :   /* Returning -1 when there's not enough room in the output buffer */
    2193           1 :   tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
    2194           1 :   tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
    2195           1 :   tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
    2196           1 :   tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
    2197             :   /* Always NUL-terminate the output */
    2198           1 :   tor_snprintf(buf, 5, "abcdef");
    2199           1 :   tt_int_op(0,OP_EQ, buf[4]);
    2200           1 :   tor_snprintf(buf, 10, "abcdef");
    2201           1 :   tt_int_op(0,OP_EQ, buf[6]);
    2202             :   /* uint64 */
    2203           1 :   tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x",
    2204             :                (UINT64_C(12345678901)));
    2205           1 :   tt_str_op("x!12345678901!x",OP_EQ, buf);
    2206             : 
    2207             :   /* Test str{,case}cmpstart */
    2208           1 :   tt_assert(strcmpstart("abcdef", "abcdef")==0);
    2209           1 :   tt_assert(strcmpstart("abcdef", "abc")==0);
    2210           1 :   tt_assert(strcmpstart("abcdef", "abd")<0);
    2211           1 :   tt_assert(strcmpstart("abcdef", "abb")>0);
    2212           1 :   tt_assert(strcmpstart("ab", "abb")<0);
    2213           1 :   tt_assert(strcmpstart("ab", "")==0);
    2214           1 :   tt_assert(strcmpstart("ab", "ab ")<0);
    2215           1 :   tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
    2216           1 :   tt_assert(strcasecmpstart("abcDeF", "abc")==0);
    2217           1 :   tt_assert(strcasecmpstart("abcdef", "Abd")<0);
    2218           1 :   tt_assert(strcasecmpstart("Abcdef", "abb")>0);
    2219           1 :   tt_assert(strcasecmpstart("ab", "Abb")<0);
    2220           1 :   tt_assert(strcasecmpstart("ab", "")==0);
    2221           1 :   tt_assert(strcasecmpstart("ab", "ab ")<0);
    2222             : 
    2223             :   /* Test str{,case}cmpend */
    2224           1 :   tt_assert(strcmpend("abcdef", "abcdef")==0);
    2225           1 :   tt_assert(strcmpend("abcdef", "def")==0);
    2226           1 :   tt_assert(strcmpend("abcdef", "deg")<0);
    2227           1 :   tt_assert(strcmpend("abcdef", "dee")>0);
    2228           1 :   tt_assert(strcmpend("ab", "aab")>0);
    2229           1 :   tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
    2230           1 :   tt_assert(strcasecmpend("abcdef", "dEF")==0);
    2231           1 :   tt_assert(strcasecmpend("abcdef", "Deg")<0);
    2232           1 :   tt_assert(strcasecmpend("abcDef", "dee")>0);
    2233           1 :   tt_assert(strcasecmpend("AB", "abb")<0);
    2234             : 
    2235             :   /* Test digest_is_zero */
    2236           1 :   memset(buf,0,20);
    2237           1 :   buf[20] = 'x';
    2238           1 :   tt_assert(tor_digest_is_zero(buf));
    2239           1 :   buf[19] = 'x';
    2240           1 :   tt_assert(!tor_digest_is_zero(buf));
    2241             : 
    2242             :   /* Test mem_is_zero */
    2243           1 :   memset(buf,0,128);
    2244           1 :   buf[128] = 'x';
    2245           1 :   tt_assert(fast_mem_is_zero(buf, 10));
    2246           1 :   tt_assert(fast_mem_is_zero(buf, 20));
    2247           1 :   tt_assert(fast_mem_is_zero(buf, 128));
    2248           1 :   tt_assert(!fast_mem_is_zero(buf, 129));
    2249           1 :   buf[60] = (char)255;
    2250           1 :   tt_assert(!fast_mem_is_zero(buf, 128));
    2251           1 :   buf[0] = (char)1;
    2252           1 :   tt_assert(!fast_mem_is_zero(buf, 10));
    2253             : 
    2254             :   /* Test 'escaped' */
    2255           1 :   tt_ptr_op(escaped(NULL), OP_EQ, NULL);
    2256           1 :   tt_str_op("\"\"",OP_EQ, escaped(""));
    2257           1 :   tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
    2258           1 :   tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
    2259           1 :   tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
    2260             :              escaped("unnecessary \'backslashes\'"));
    2261             :   /* Non-printable characters appear as octal */
    2262           1 :   tt_str_op("\"z\\001abc\\277d\"",OP_EQ,  escaped("z\001abc\277d"));
    2263           1 :   tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
    2264             : 
    2265             :   /* Other cases of esc_for_log{,_len} */
    2266           1 :   cp_tmp = esc_for_log(NULL);
    2267           1 :   tt_str_op(cp_tmp, OP_EQ, "(null)");
    2268           1 :   tor_free(cp_tmp);
    2269           1 :   cp_tmp = esc_for_log_len("abcdefg", 3);
    2270           1 :   tt_str_op(cp_tmp, OP_EQ, "\"abc\"");
    2271           1 :   tor_free(cp_tmp);
    2272           1 :   cp_tmp = esc_for_log_len("abcdefg", 100);
    2273           1 :   tt_str_op(cp_tmp, OP_EQ, "\"abcdefg\"");
    2274           1 :   tor_free(cp_tmp);
    2275             : 
    2276             :   /* Test strndup and memdup */
    2277             :   {
    2278           1 :     const char *s = "abcdefghijklmnopqrstuvwxyz";
    2279           1 :     cp_tmp = tor_strndup(s, 30);
    2280           1 :     tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
    2281           1 :     tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
    2282           1 :     tor_free(cp_tmp);
    2283             : 
    2284           1 :     cp_tmp = tor_strndup(s, 5);
    2285           1 :     tt_str_op(cp_tmp,OP_EQ, "abcde");
    2286           1 :     tor_free(cp_tmp);
    2287             : 
    2288           1 :     s = "a\0b\0c\0d\0e\0";
    2289           1 :     cp_tmp = tor_memdup(s,10);
    2290           1 :     tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
    2291           1 :     tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
    2292           1 :     tor_free(cp_tmp);
    2293             :   }
    2294             : 
    2295             :   /* Test str-foo functions */
    2296           1 :   cp_tmp = tor_strdup("abcdef");
    2297           1 :   tt_assert(tor_strisnonupper(cp_tmp));
    2298           1 :   cp_tmp[3] = 'D';
    2299           1 :   tt_assert(!tor_strisnonupper(cp_tmp));
    2300           1 :   tor_strupper(cp_tmp);
    2301           1 :   tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
    2302           1 :   tor_strlower(cp_tmp);
    2303           1 :   tt_str_op(cp_tmp,OP_EQ, "abcdef");
    2304           1 :   tt_assert(tor_strisnonupper(cp_tmp));
    2305           1 :   tt_assert(tor_strisprint(cp_tmp));
    2306           1 :   cp_tmp[3] = 3;
    2307           1 :   tt_assert(!tor_strisprint(cp_tmp));
    2308           1 :   tor_free(cp_tmp);
    2309             : 
    2310             :   /* Test memmem and memstr */
    2311             :   {
    2312           1 :     const char *haystack = "abcde";
    2313           1 :     tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL);
    2314           1 :     tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
    2315           1 :     tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
    2316           1 :     tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL);
    2317           1 :     haystack = "ababcad";
    2318           1 :     tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
    2319           1 :     tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
    2320           1 :     tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
    2321           1 :     tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL);
    2322           1 :     tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL);
    2323             :     /* memstr */
    2324           1 :     tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
    2325           1 :     tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
    2326           1 :     tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL);
    2327           1 :     tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL);
    2328           1 :     tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL);
    2329           1 :     tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL);
    2330             :   }
    2331             : 
    2332             :   /* Test hex_str */
    2333             :   {
    2334             :     char binary_data[68];
    2335             :     size_t idx;
    2336          69 :     for (idx = 0; idx < sizeof(binary_data); ++idx)
    2337          68 :       binary_data[idx] = idx;
    2338           1 :     tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
    2339           1 :     tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
    2340           1 :     tt_str_op(hex_str(binary_data, 17),OP_EQ,
    2341             :               "000102030405060708090A0B0C0D0E0F10");
    2342           1 :     tt_str_op(hex_str(binary_data, 32),OP_EQ,
    2343             :                "000102030405060708090A0B0C0D0E0F"
    2344             :                "101112131415161718191A1B1C1D1E1F");
    2345           1 :     tt_str_op(hex_str(binary_data, 34),OP_EQ,
    2346             :                "000102030405060708090A0B0C0D0E0F"
    2347             :                "101112131415161718191A1B1C1D1E1F");
    2348             :     /* Repeat these tests for shorter strings after longer strings
    2349             :        have been tried, to make sure we're correctly terminating strings */
    2350           1 :     tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
    2351           1 :     tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
    2352             :   }
    2353             : 
    2354             :   /* Test strcmp_opt */
    2355           1 :   tt_int_op(strcmp_opt("",   "foo"), OP_LT, 0);
    2356           1 :   tt_int_op(strcmp_opt("",    ""),  OP_EQ, 0);
    2357           1 :   tt_int_op(strcmp_opt("foo", ""),   OP_GT, 0);
    2358             : 
    2359           1 :   tt_int_op(strcmp_opt(NULL,  ""),    OP_LT, 0);
    2360           1 :   tt_int_op(strcmp_opt(NULL,  NULL), OP_EQ, 0);
    2361           1 :   tt_int_op(strcmp_opt("",    NULL),  OP_GT, 0);
    2362             : 
    2363           1 :   tt_int_op(strcmp_opt(NULL,  "foo"), OP_LT, 0);
    2364           1 :   tt_int_op(strcmp_opt("foo", NULL),  OP_GT, 0);
    2365             : 
    2366           1 :  done:
    2367           1 :   tor_free(cp_tmp);
    2368           1 : }
    2369             : 
    2370             : static void
    2371           1 : test_util_parse_integer(void *arg)
    2372             : {
    2373           1 :   (void)arg;
    2374           1 :   int i;
    2375           1 :   char *cp;
    2376             : 
    2377             :   /* Test parse_long */
    2378             :   /* Empty/zero input */
    2379           1 :   tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
    2380           1 :   tt_int_op(0,OP_EQ, i);
    2381           1 :   tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
    2382           1 :   tt_int_op(1,OP_EQ, i);
    2383             :   /* Normal cases */
    2384           1 :   tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
    2385           1 :   tt_int_op(1,OP_EQ, i);
    2386           1 :   tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
    2387           1 :   tt_int_op(1,OP_EQ, i);
    2388           1 :   tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
    2389           1 :   tt_int_op(1,OP_EQ, i);
    2390           1 :   tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
    2391           1 :   tt_int_op(1,OP_EQ, i);
    2392           1 :   tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
    2393           1 :   tt_int_op(1,OP_EQ, i);
    2394           1 :   tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
    2395           1 :   tt_int_op(1,OP_EQ, i);
    2396             :   /* Extra garbage */
    2397           1 :   tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
    2398           1 :   tt_int_op(0,OP_EQ, i);
    2399           1 :   tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
    2400           1 :   tt_int_op(0,OP_EQ, i);
    2401           1 :   tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
    2402           1 :   tt_int_op(1,OP_EQ, i);
    2403           1 :   tt_str_op(cp,OP_EQ, "m");
    2404           1 :   tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
    2405           1 :   tt_int_op(1,OP_EQ, i);
    2406           1 :   tt_str_op(cp,OP_EQ, " plus garbage");
    2407             :   /* Illogical min max */
    2408           1 :   tt_int_op(0L,OP_EQ,  tor_parse_long("10",10,50,4,&i,NULL));
    2409           1 :   tt_int_op(0,OP_EQ, i);
    2410           1 :   tt_int_op(0L,OP_EQ,   tor_parse_long("-50",10,100,-100,&i,NULL));
    2411           1 :   tt_int_op(0,OP_EQ, i);
    2412             :   /* Out of bounds */
    2413           1 :   tt_int_op(0L,OP_EQ,  tor_parse_long("10",10,50,100,&i,NULL));
    2414           1 :   tt_int_op(0,OP_EQ, i);
    2415           1 :   tt_int_op(0L,OP_EQ,   tor_parse_long("-50",10,0,100,&i,NULL));
    2416           1 :   tt_int_op(0,OP_EQ, i);
    2417             :   /* Base different than 10 */
    2418           1 :   tt_int_op(2L,OP_EQ,   tor_parse_long("10",2,0,100,NULL,NULL));
    2419           1 :   tt_int_op(0L,OP_EQ,   tor_parse_long("2",2,0,100,NULL,NULL));
    2420           1 :   tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
    2421           1 :   tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
    2422           1 :   tt_int_op(0L,OP_EQ,   tor_parse_long("10",-2,0,100,NULL,NULL));
    2423           1 :   tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
    2424           1 :   tt_int_op(i,OP_EQ, 0);
    2425             : 
    2426             :   /* Test parse_ulong */
    2427           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
    2428           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
    2429           1 :   tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
    2430           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
    2431           1 :   tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
    2432           1 :   tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
    2433           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
    2434           1 :   tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
    2435           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
    2436           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
    2437           1 :   tt_int_op(0,OP_EQ, i);
    2438           1 :   tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
    2439           1 :   tt_int_op(0,OP_EQ, i);
    2440             : 
    2441             :   /* Test parse_uint64 */
    2442           1 :   tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
    2443           1 :   tt_int_op(1,OP_EQ, i);
    2444           1 :   tt_str_op(cp,OP_EQ, " x");
    2445           1 :   tt_assert(UINT64_C(12345678901) ==
    2446             :               tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
    2447           1 :   tt_int_op(1,OP_EQ, i);
    2448           1 :   tt_str_op(cp,OP_EQ, "");
    2449           1 :   tt_assert(UINT64_C(0) ==
    2450             :               tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
    2451           1 :   tt_int_op(0,OP_EQ, i);
    2452           1 :   tt_assert(UINT64_C(0) ==
    2453             :               tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
    2454           1 :   tt_int_op(0,OP_EQ, i);
    2455             : 
    2456             :   {
    2457             :   /* Test parse_double */
    2458           1 :   double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
    2459           1 :   tt_int_op(1,OP_EQ, i);
    2460           1 :   tt_assert(((uint64_t)d) == 10);
    2461           1 :   d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
    2462           1 :   tt_int_op(1,OP_EQ, i);
    2463           1 :   tt_assert(((uint64_t)d) == 0);
    2464           1 :   d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
    2465           1 :   tt_double_op(fabs(d), OP_LT, 1e-10);
    2466           1 :   tt_int_op(0,OP_EQ, i);
    2467           1 :   d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL);
    2468           1 :   tt_double_op(fabs(d), OP_LT, 1e-10);
    2469           1 :   tt_int_op(0,OP_EQ, i);
    2470           1 :   d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp);
    2471           1 :   tt_double_op(fabs(d), OP_LT, 1e-10);
    2472           1 :   tt_int_op(1,OP_EQ, i);
    2473           1 :   d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
    2474           1 :   tt_int_op(1,OP_EQ, i);
    2475           1 :   tt_assert(((uint64_t)d) == 0);
    2476           1 :   d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
    2477           1 :   tt_int_op(1,OP_EQ, i);
    2478           1 :   tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
    2479             :   }
    2480             : 
    2481             :   {
    2482             :     /* Test tor_parse_* where we overflow/underflow the underlying type. */
    2483             :     /* This string should overflow 64-bit ints. */
    2484             : #define TOOBIG "100000000000000000000000000"
    2485           1 :     tt_int_op(0L, OP_EQ,
    2486             :               tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
    2487           1 :     tt_int_op(i,OP_EQ, 0);
    2488           1 :     tt_int_op(0L,OP_EQ,
    2489             :               tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
    2490           1 :     tt_int_op(i,OP_EQ, 0);
    2491           1 :     tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
    2492           1 :     tt_int_op(i,OP_EQ, 0);
    2493           1 :     tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
    2494             :                                              0, UINT64_MAX, &i, NULL));
    2495           1 :     tt_int_op(i,OP_EQ, 0);
    2496             :   }
    2497           1 :  done:
    2498           1 :   ;
    2499           1 : }
    2500             : 
    2501             : static void
    2502           1 : test_util_pow2(void *arg)
    2503             : {
    2504             :   /* Test tor_log2(). */
    2505           1 :   (void)arg;
    2506           1 :   tt_int_op(tor_log2(64),OP_EQ, 6);
    2507           1 :   tt_int_op(tor_log2(65),OP_EQ, 6);
    2508           1 :   tt_int_op(tor_log2(63),OP_EQ, 5);
    2509             :   /* incorrect mathematically, but as specified: */
    2510           1 :   tt_int_op(tor_log2(0),OP_EQ, 0);
    2511           1 :   tt_int_op(tor_log2(1),OP_EQ, 0);
    2512           1 :   tt_int_op(tor_log2(2),OP_EQ, 1);
    2513           1 :   tt_int_op(tor_log2(3),OP_EQ, 1);
    2514           1 :   tt_int_op(tor_log2(4),OP_EQ, 2);
    2515           1 :   tt_int_op(tor_log2(5),OP_EQ, 2);
    2516           1 :   tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55);
    2517           1 :   tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
    2518             : 
    2519             :   /* Test round_to_power_of_2 */
    2520           1 :   tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
    2521           1 :   tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
    2522           1 :   tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
    2523           1 :   tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ,
    2524             :             UINT64_C(1)<<55);
    2525           1 :   tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ,
    2526             :           UINT64_C(1)<<63);
    2527           1 :   tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
    2528           1 :   tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
    2529           1 :   tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
    2530           1 :   tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
    2531           1 :   tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
    2532           1 :   tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
    2533           1 :   tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
    2534           1 :   tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
    2535             : 
    2536           1 :  done:
    2537           1 :   ;
    2538           1 : }
    2539             : 
    2540             : static void
    2541           6 : test_util_compress_impl(compress_method_t method)
    2542             : {
    2543           6 :   char *buf1=NULL, *buf2=NULL, *buf3=NULL;
    2544           6 :   size_t len1, len2;
    2545             : 
    2546           6 :   tt_assert(tor_compress_supports_method(method));
    2547             : 
    2548           6 :   if (method != NO_METHOD) {
    2549           5 :     tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
    2550           5 :     tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
    2551             :   }
    2552             : 
    2553           6 :   buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
    2554           6 :   tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
    2555             : 
    2556           6 :   tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
    2557           6 :   tt_ptr_op(buf2, OP_NE, NULL);
    2558           6 :   if (method == NO_METHOD) {
    2559             :     // The identity transform doesn't actually compress, and it isn't
    2560             :     // detectable as "the identity transform."
    2561           1 :     tt_int_op(len1, OP_EQ, strlen(buf1)+1);
    2562           1 :     tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
    2563             :   } else {
    2564           5 :     tt_int_op(len1, OP_LT, strlen(buf1));
    2565           5 :     tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
    2566             :   }
    2567             : 
    2568           6 :   tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
    2569           6 :   tt_ptr_op(buf3, OP_NE, NULL);
    2570           6 :   tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
    2571           6 :   tt_str_op(buf1, OP_EQ, buf3);
    2572           6 :   tt_int_op(buf3[len2], OP_EQ, 0);
    2573             : 
    2574             :   /* Check whether we can uncompress concatenated, compressed strings. */
    2575           6 :   tor_free(buf3);
    2576           6 :   buf2 = tor_reallocarray(buf2, len1, 2);
    2577           6 :   memcpy(buf2+len1, buf2, len1);
    2578           6 :   tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
    2579           6 :   tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
    2580           6 :   tt_mem_op(buf3, OP_EQ,
    2581             :              "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
    2582             :              "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
    2583           6 :              (strlen(buf1)+1)*2);
    2584           6 :   tt_int_op(buf3[len2], OP_EQ, 0);
    2585             : 
    2586             :   /* Check whether we can uncompress partial strings */
    2587             : 
    2588           6 :   tor_free(buf1);
    2589           6 :   tor_free(buf2);
    2590           6 :   tor_free(buf3);
    2591             : 
    2592           6 :   size_t b1len = 1<<10;
    2593           6 :   if (method == ZSTD_METHOD) {
    2594             :     // zstd needs a big input before it starts generating output that it
    2595             :     // can partially decompress.
    2596           2 :     b1len = 1<<18;
    2597             :   }
    2598           6 :   buf1 = tor_malloc(b1len);
    2599           6 :   crypto_rand(buf1, b1len);
    2600           6 :   tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
    2601           6 :   tt_int_op(len1, OP_GT, 16);
    2602             :   /* when we allow an incomplete output we should succeed.*/
    2603           6 :   tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
    2604             :                             method, 0, LOG_INFO));
    2605           6 :   tt_int_op(len2, OP_GT, 5);
    2606           6 :   tt_int_op(len2, OP_LE, len1);
    2607           6 :   tt_assert(fast_memeq(buf1, buf3, len2));
    2608           6 :   tt_int_op(buf3[len2], OP_EQ, 0);
    2609             : 
    2610             :   /* when we demand a complete output from a real compression method, this
    2611             :    * must fail. */
    2612           6 :   tor_free(buf3);
    2613           6 :   if (method != NO_METHOD) {
    2614           5 :     tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
    2615             :                              method, 1, LOG_INFO));
    2616           5 :     tt_ptr_op(buf3, OP_EQ, NULL);
    2617             :   }
    2618             : 
    2619           6 :  done:
    2620           6 :   tor_free(buf1);
    2621           6 :   tor_free(buf2);
    2622           6 :   tor_free(buf3);
    2623           6 : }
    2624             : 
    2625             : static void
    2626          24 : test_util_compress_stream_impl(compress_method_t method,
    2627             :                                compression_level_t level)
    2628             : {
    2629          24 :   char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
    2630          24 :   const char *ccp2;
    2631          24 :   size_t len1, len2;
    2632             : 
    2633          24 :   tor_compress_state_t *state = NULL;
    2634          24 :   state = tor_compress_new(1, method, level);
    2635          24 :   tt_assert(state);
    2636          24 :   cp1 = buf1 = tor_malloc(1024);
    2637          24 :   len1 = 1024;
    2638          24 :   ccp2 = "ABCDEFGHIJABCDEFGHIJ";
    2639          24 :   len2 = 21;
    2640          24 :   tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
    2641             :             OP_EQ, TOR_COMPRESS_OK);
    2642          24 :   tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
    2643          24 :   tt_assert(cp1 > buf1);
    2644             : 
    2645          24 :   len2 = 0;
    2646          24 :   cp2 = cp1;
    2647          24 :   tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
    2648             :             OP_EQ, TOR_COMPRESS_DONE);
    2649          24 :   tt_int_op(0, OP_EQ, len2);
    2650          24 :   if (method == NO_METHOD) {
    2651           4 :     tt_ptr_op(cp1, OP_EQ, cp2);
    2652             :   } else {
    2653          20 :     tt_assert(cp1 > cp2); /* Make sure we really added something. */
    2654             :   }
    2655             : 
    2656          24 :   tt_int_op(tor_compress_state_size(state), OP_GT, 0);
    2657             : 
    2658          24 :   tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
    2659             :                             method, 1, LOG_WARN));
    2660             :   /* Make sure it compressed right. */
    2661          24 :   tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
    2662          24 :   tt_int_op(21, OP_EQ, len2);
    2663             : 
    2664          24 :  done:
    2665          24 :   if (state)
    2666          24 :     tor_compress_free(state);
    2667          24 :   tor_free(buf1);
    2668          24 :   tor_free(buf2);
    2669          24 :   tor_free(buf3);
    2670          24 : }
    2671             : 
    2672             : /** Setup function for compression tests: handles x-zstd:nostatic
    2673             :  */
    2674             : static void *
    2675          20 : compression_test_setup(const struct testcase_t *testcase)
    2676             : {
    2677          20 :   tor_assert(testcase->setup_data);
    2678          20 :   tor_assert(testcase->setup_data != (void*)TT_SKIP);
    2679          20 :   const char *methodname = testcase->setup_data;
    2680             : 
    2681          20 :   if (!strcmp(methodname, "x-zstd:nostatic")) {
    2682           3 :     methodname = "x-zstd";
    2683           3 :     tor_zstd_set_static_apis_disabled_for_testing(1);
    2684             :   }
    2685             : 
    2686          20 :   return (void *)methodname;
    2687             : }
    2688             : 
    2689             : /** Cleanup for compression tests: disables nostatic */
    2690             : static int
    2691          20 : compression_test_cleanup(const struct testcase_t *testcase, void *ptr)
    2692             : {
    2693          20 :   (void)testcase;
    2694          20 :   (void)ptr;
    2695          20 :   tor_zstd_set_static_apis_disabled_for_testing(0);
    2696          20 :   return 1;
    2697             : }
    2698             : 
    2699             : static const struct testcase_setup_t compress_setup = {
    2700             :   compression_test_setup, compression_test_cleanup
    2701             : };
    2702             : 
    2703             : /** Run unit tests for compression functions */
    2704             : static void
    2705           6 : test_util_compress(void *arg)
    2706             : {
    2707           6 :   const char *methodname = arg;
    2708           6 :   tt_assert(methodname);
    2709             : 
    2710           6 :   compress_method_t method = compression_method_get_by_name(methodname);
    2711           6 :   tt_int_op(method, OP_NE, UNKNOWN_METHOD);
    2712             : 
    2713           6 :   if (! tor_compress_supports_method(method)) {
    2714           0 :     tt_skip();
    2715             :   }
    2716             : 
    2717           6 :   compression_level_t levels[] = {
    2718             :     BEST_COMPRESSION,
    2719             :     HIGH_COMPRESSION,
    2720             :     MEDIUM_COMPRESSION,
    2721             :     LOW_COMPRESSION
    2722             :   };
    2723             : 
    2724           6 :   test_util_compress_impl(method);
    2725             : 
    2726          30 :   for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
    2727          24 :     compression_level_t level = levels[l];
    2728          24 :     test_util_compress_stream_impl(method, level);
    2729             :   }
    2730           6 :  done:
    2731           6 :   ;
    2732           6 : }
    2733             : 
    2734             : static void
    2735           6 : test_util_decompress_concatenated_impl(compress_method_t method)
    2736             : {
    2737           6 :   char input[4096];
    2738           6 :   char *c1 = NULL, *c2 = NULL, *c3 = NULL;
    2739           6 :   char *result = NULL;
    2740           6 :   size_t sz1, sz2, sz3, szr;
    2741           6 :   int r;
    2742             : 
    2743           6 :   crypto_rand(input, sizeof(input));
    2744             : 
    2745             :   /* Compress the input in two chunks. */
    2746           6 :   r = tor_compress(&c1, &sz1, input, 2048, method);
    2747           6 :   tt_int_op(r, OP_EQ, 0);
    2748           6 :   r = tor_compress(&c2, &sz2, input+2048, 2048, method);
    2749           6 :   tt_int_op(r, OP_EQ, 0);
    2750             : 
    2751             :   /* concatenate the chunks. */
    2752           6 :   sz3 = sz1 + sz2;
    2753           6 :   c3 = tor_malloc(sz3);
    2754           6 :   memcpy(c3, c1, sz1);
    2755           6 :   memcpy(c3+sz1, c2, sz2);
    2756             : 
    2757             :   /* decompress the concatenated result */
    2758           6 :   r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
    2759           6 :   tt_int_op(r, OP_EQ, 0);
    2760           6 :   tt_int_op(szr, OP_EQ, sizeof(input));
    2761           6 :   tt_mem_op(result, OP_EQ, input, sizeof(input));
    2762             : 
    2763           6 :  done:
    2764           6 :   tor_free(c1);
    2765           6 :   tor_free(c2);
    2766           6 :   tor_free(c3);
    2767           6 :   tor_free(result);
    2768           6 : }
    2769             : 
    2770             : static void
    2771           6 : test_util_decompress_concatenated(void *arg)
    2772             : {
    2773           6 :   const char *methodname = arg;
    2774           6 :   tt_assert(methodname);
    2775             : 
    2776           6 :   compress_method_t method = compression_method_get_by_name(methodname);
    2777           6 :   tt_int_op(method, OP_NE, UNKNOWN_METHOD);
    2778           6 :   if (! tor_compress_supports_method(method)) {
    2779           0 :     tt_skip();
    2780             :   }
    2781             : 
    2782           6 :   test_util_decompress_concatenated_impl(method);
    2783           6 :  done:
    2784           6 :   ;
    2785           6 : }
    2786             : 
    2787             : static void
    2788           3 : test_util_decompress_junk_impl(compress_method_t method)
    2789             : {
    2790           3 :   char input[4096];
    2791           3 :   char *result = NULL, *result2 = NULL;
    2792           3 :   size_t szr, szr2, sz;
    2793           3 :   int r;
    2794             : 
    2795             :   /* This shouldn't be a compressed string according to any method. */
    2796           3 :   strlcpy(input, "This shouldn't be a compressed string by any means.",
    2797             :           sizeof(input));
    2798           3 :   sz = strlen(input);
    2799           3 :   setup_capture_of_logs(LOG_WARN);
    2800           3 :   r = tor_uncompress(&result, &szr, input, sz, method, 0, LOG_WARN);
    2801           3 :   tt_int_op(r, OP_EQ, -1);
    2802           3 :   tt_ptr_op(result, OP_EQ, NULL);
    2803           3 :   expect_log_msg_containing("Error while uncompressing data: bad input?");
    2804           3 :   mock_clean_saved_logs();
    2805             : 
    2806             :   /* Now try again, with a compressed object that starts out good and turns to
    2807             :      junk. */
    2808           3 :   crypto_rand(input, sizeof(input));
    2809           3 :   r = tor_compress(&result, &szr, input, sizeof(input), method);
    2810           3 :   tt_int_op(r, OP_EQ, 0);
    2811           3 :   crypto_rand(result+szr/2, szr-(szr/2)); // trash the 2nd half of the result
    2812           3 :   r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
    2813           3 :   tt_int_op(r, OP_EQ, -1);
    2814           3 :   expect_log_msg_containing("Error while uncompressing data: bad input?");
    2815             : 
    2816           3 :  done:
    2817           3 :   teardown_capture_of_logs();
    2818           3 :   tor_free(result);
    2819           3 :   tor_free(result2);
    2820           3 : }
    2821             : 
    2822             : static void
    2823           3 : test_util_decompress_junk(void *arg)
    2824             : {
    2825           3 :   const char *methodname = arg;
    2826           3 :   tt_assert(methodname);
    2827             : 
    2828           3 :   compress_method_t method = compression_method_get_by_name(methodname);
    2829           3 :   tt_int_op(method, OP_NE, UNKNOWN_METHOD);
    2830           3 :   if (! tor_compress_supports_method(method)) {
    2831           0 :     tt_skip();
    2832             :   }
    2833             : 
    2834           3 :   test_util_decompress_junk_impl(method);
    2835           3 :  done:
    2836           3 :   ;
    2837           3 : }
    2838             : 
    2839             : /* mock replacement for tor_compress_is_compression_bomb that doesn't
    2840             :  * believe in compression bombs. */
    2841             : static int
    2842           5 : mock_is_never_compression_bomb(size_t in, size_t out)
    2843             : {
    2844           5 :   (void)in;
    2845           5 :   (void) out;
    2846           5 :   return 0;
    2847             : }
    2848             : 
    2849             : static void
    2850           5 : test_util_decompress_dos_impl(compress_method_t method)
    2851             : {
    2852           5 :   char *input;
    2853           5 :   char *result = NULL, *result2 = NULL;
    2854           5 :   size_t szr, szr2;
    2855           5 :   int r;
    2856             : 
    2857           5 :   const size_t big = 1024*1024;
    2858             :   /* one megabyte of 0s. */
    2859           5 :   input = tor_malloc_zero(big);
    2860             : 
    2861             :   /* Compress it into "result": it should fail. */
    2862           5 :   setup_full_capture_of_logs(LOG_WARN);
    2863           5 :   r = tor_compress(&result, &szr, input, big, method);
    2864           5 :   tt_int_op(r, OP_EQ, -1);
    2865           5 :   expect_log_msg_containing(
    2866           5 :                  "other Tors would think this was a compression bomb");
    2867           5 :   teardown_capture_of_logs();
    2868             : 
    2869             :   /* Try again, but this time suppress compression-bomb detection */
    2870           5 :   MOCK(tor_compress_is_compression_bomb, mock_is_never_compression_bomb);
    2871           5 :   r = tor_compress(&result, &szr, input, big, method);
    2872           5 :   UNMOCK(tor_compress_is_compression_bomb);
    2873           5 :   tt_int_op(r, OP_EQ, 0);
    2874           5 :   tt_ptr_op(result, OP_NE, NULL);
    2875             : 
    2876             :   /* We should refuse to uncomrpess it again, since it looks like a
    2877             :    * compression bomb. */
    2878           5 :   setup_capture_of_logs(LOG_WARN);
    2879           5 :   r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
    2880           5 :   tt_int_op(r, OP_EQ, -1);
    2881           5 :   expect_log_msg_containing("bomb; abandoning stream");
    2882             : 
    2883           5 :  done:
    2884           5 :   teardown_capture_of_logs();
    2885           5 :   tor_free(input);
    2886           5 :   tor_free(result);
    2887           5 :   tor_free(result2);
    2888           5 : }
    2889             : 
    2890             : static void
    2891           5 : test_util_decompress_dos(void *arg)
    2892             : {
    2893           5 :   const char *methodname = arg;
    2894           5 :   tt_assert(methodname);
    2895             : 
    2896           5 :   compress_method_t method = compression_method_get_by_name(methodname);
    2897           5 :   tt_int_op(method, OP_NE, UNKNOWN_METHOD);
    2898           5 :   if (! tor_compress_supports_method(method)) {
    2899           0 :     tt_skip();
    2900             :   }
    2901             : 
    2902           5 :   test_util_decompress_dos_impl(method);
    2903           5 :  done:
    2904           5 :   ;
    2905           5 : }
    2906             : 
    2907             : static void
    2908           1 : test_util_gzip_compression_bomb(void *arg)
    2909             : {
    2910             :   /* A 'compression bomb' is a very small object that uncompresses to a huge
    2911             :    * one. Most compression formats support them, but they can be a DOS vector.
    2912             :    * In Tor we try not to generate them, and we don't accept them.
    2913             :    */
    2914           1 :   (void) arg;
    2915           1 :   size_t one_million = 1<<20;
    2916           1 :   char *one_mb = tor_malloc_zero(one_million);
    2917           1 :   char *result = NULL;
    2918           1 :   size_t result_len = 0;
    2919           1 :   tor_compress_state_t *state = NULL;
    2920             : 
    2921             :   /* Make sure we can't produce a compression bomb */
    2922           1 :   setup_full_capture_of_logs(LOG_WARN);
    2923           1 :   tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
    2924             :                                     one_mb, one_million,
    2925             :                                     ZLIB_METHOD));
    2926           1 :   expect_single_log_msg_containing(
    2927             :          "We compressed something and got an insanely high "
    2928             :          "compression factor; other Tors would think this "
    2929             :          "was a compression bomb.");
    2930           1 :   teardown_capture_of_logs();
    2931             : 
    2932             :   /* Here's a compression bomb that we made manually. */
    2933           1 :   const char compression_bomb[1039] =
    2934             :     { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
    2935             :       0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
    2936           1 :   tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
    2937             :                                       compression_bomb, 1039,
    2938             :                                       ZLIB_METHOD, 0, LOG_WARN));
    2939             : 
    2940             :   /* Now try streaming that. */
    2941           1 :   state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
    2942           1 :   tor_compress_output_t r;
    2943           1 :   const char *inp = compression_bomb;
    2944           1 :   size_t inlen = 1039;
    2945          16 :   do {
    2946          16 :     char *outp = one_mb;
    2947          16 :     size_t outleft = 4096; /* small on purpose */
    2948          16 :     r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
    2949          16 :     tt_int_op(inlen, OP_NE, 0);
    2950          16 :   } while (r == TOR_COMPRESS_BUFFER_FULL);
    2951             : 
    2952           1 :   tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
    2953             : 
    2954           1 :  done:
    2955           1 :   tor_free(one_mb);
    2956           1 :   tor_compress_free(state);
    2957           1 : }
    2958             : 
    2959             : /** Run unit tests for mmap() wrapper functionality. */
    2960             : static void
    2961           1 : test_util_mmap(void *arg)
    2962             : {
    2963           1 :   char *fname1 = tor_strdup(get_fname("mapped_1"));
    2964           1 :   char *fname2 = tor_strdup(get_fname("mapped_2"));
    2965           1 :   char *fname3 = tor_strdup(get_fname("mapped_3"));
    2966           1 :   const size_t buflen = 17000;
    2967           1 :   char *buf = tor_malloc(17000);
    2968           1 :   tor_mmap_t *mapping = NULL;
    2969             : 
    2970           1 :   (void)arg;
    2971           1 :   crypto_rand(buf, buflen);
    2972             : 
    2973           1 :   mapping = tor_mmap_file(fname1);
    2974           1 :   tt_ptr_op(mapping, OP_EQ, NULL);
    2975             : 
    2976           1 :   write_str_to_file(fname1, "Short file.", 1);
    2977             : 
    2978           1 :   mapping = tor_mmap_file(fname1);
    2979           1 :   tt_assert(mapping);
    2980           1 :   tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
    2981           1 :   tt_str_op(mapping->data,OP_EQ, "Short file.");
    2982             : #ifdef _WIN32
    2983             :   tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
    2984             :   mapping = NULL;
    2985             :   tt_assert(unlink(fname1) == 0);
    2986             : #else
    2987             :   /* make sure we can unlink. */
    2988           1 :   tt_assert(unlink(fname1) == 0);
    2989           1 :   tt_str_op(mapping->data,OP_EQ, "Short file.");
    2990           1 :   tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
    2991           1 :   mapping = NULL;
    2992             : #endif /* defined(_WIN32) */
    2993             : 
    2994             :   /* Now a zero-length file. */
    2995           1 :   write_str_to_file(fname1, "", 1);
    2996           1 :   mapping = tor_mmap_file(fname1);
    2997           1 :   tt_ptr_op(mapping,OP_EQ, NULL);
    2998           1 :   tt_int_op(ERANGE,OP_EQ, errno);
    2999           1 :   unlink(fname1);
    3000             : 
    3001             :   /* Make sure that we fail to map a no-longer-existent file. */
    3002           1 :   mapping = tor_mmap_file(fname1);
    3003           1 :   tt_ptr_op(mapping, OP_EQ, NULL);
    3004             : 
    3005             :   /* Now try a big file that stretches across a few pages and isn't aligned */
    3006           1 :   write_bytes_to_file(fname2, buf, buflen, 1);
    3007           1 :   mapping = tor_mmap_file(fname2);
    3008           1 :   tt_assert(mapping);
    3009           1 :   tt_int_op(mapping->size,OP_EQ, buflen);
    3010           1 :   tt_mem_op(mapping->data,OP_EQ, buf, buflen);
    3011           1 :   tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
    3012           1 :   mapping = NULL;
    3013             : 
    3014             :   /* Now try a big aligned file. */
    3015           1 :   write_bytes_to_file(fname3, buf, 16384, 1);
    3016           1 :   mapping = tor_mmap_file(fname3);
    3017           1 :   tt_assert(mapping);
    3018           1 :   tt_int_op(mapping->size,OP_EQ, 16384);
    3019           1 :   tt_mem_op(mapping->data,OP_EQ, buf, 16384);
    3020           1 :   tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
    3021             :   mapping = NULL;
    3022             : 
    3023           1 :  done:
    3024           1 :   unlink(fname1);
    3025           1 :   unlink(fname2);
    3026           1 :   unlink(fname3);
    3027             : 
    3028           1 :   tor_free(fname1);
    3029           1 :   tor_free(fname2);
    3030           1 :   tor_free(fname3);
    3031           1 :   tor_free(buf);
    3032             : 
    3033           1 :   tor_munmap_file(mapping);
    3034           1 : }
    3035             : 
    3036             : /** Run unit tests for escaping/unescaping data for use by controllers. */
    3037             : static void
    3038           1 : test_util_control_formats(void *arg)
    3039             : {
    3040           1 :   char *out = NULL;
    3041           1 :   const char *inp =
    3042             :     "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
    3043           1 :   size_t sz;
    3044             : 
    3045           1 :   (void)arg;
    3046           1 :   sz = read_escaped_data(inp, strlen(inp), &out);
    3047           1 :   tt_str_op(out,OP_EQ,
    3048             :              ".This is a test\nof the emergency \n.system.\n\rZ.\n");
    3049           1 :   tt_int_op(sz,OP_EQ, strlen(out));
    3050             : 
    3051           1 :  done:
    3052           1 :   tor_free(out);
    3053           1 : }
    3054             : 
    3055             : #define test_feq(value1,value2) do {                               \
    3056             :     double v1 = (value1), v2=(value2);                             \
    3057             :     double tf_diff = v1-v2;                                        \
    3058             :     double tf_tolerance = ((v1+v2)/2.0)/1e8;                       \
    3059             :     if (tf_diff<0) tf_diff=-tf_diff;                               \
    3060             :     if (tf_tolerance<0) tf_tolerance=-tf_tolerance;                \
    3061             :     if (tf_diff<tf_tolerance) {                                    \
    3062             :       TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2));  \
    3063             :     } else {                                                       \
    3064             :       TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
    3065             :     }                                                              \
    3066             :   } while (0)
    3067             : 
    3068             : static void
    3069           1 : test_util_sscanf(void *arg)
    3070             : {
    3071           1 :   unsigned u1, u2, u3;
    3072           1 :   unsigned long ulng;
    3073           1 :   char s1[20], s2[10], s3[10], ch, *huge = NULL;
    3074           1 :   int r;
    3075           1 :   long lng1,lng2;
    3076           1 :   int int1, int2;
    3077           1 :   double d1,d2,d3,d4;
    3078             : 
    3079             :   /* Simple tests (malformed patterns, literal matching, ...) */
    3080           1 :   (void)arg;
    3081           1 :   tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
    3082           1 :   tt_int_op(-1,OP_EQ,
    3083             :             tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
    3084           1 :   tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
    3085             :   /* this will fail because we don't allow widths longer than 9999 */
    3086             :   {
    3087           1 :     huge = tor_malloc(1000000);
    3088           1 :     r = tor_sscanf("prettylongstring", "%99999s", huge);
    3089           1 :     tor_free(huge);
    3090           1 :     tt_int_op(-1,OP_EQ, r);
    3091             :   }
    3092             : #if 0
    3093             :   /* GCC thinks these two are illegal. */
    3094             :   test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
    3095             :   test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
    3096             : #endif
    3097             :   /* No '%'-strings: always "success" */
    3098           1 :   tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
    3099           1 :   tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
    3100             :   /* Excess data */
    3101           1 :   tt_int_op(0,OP_EQ,
    3102             :             tor_sscanf("hello 3", "%u", &u1));  /* have to match the start */
    3103           1 :   tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
    3104           1 :   tt_int_op(0,OP_EQ,
    3105             :             tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
    3106           1 :   tt_int_op(1,OP_EQ,
    3107             :             tor_sscanf("3 hello", "%u", &u1));  /* but trailing is alright */
    3108             : 
    3109             :   /* Numbers (ie. %u) */
    3110           1 :   tt_int_op(0,OP_EQ,
    3111             :             tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
    3112           1 :   tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
    3113           1 :   tt_int_op(12345u,OP_EQ, u1);
    3114           1 :   tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
    3115           1 :   tt_int_op(12346u,OP_EQ, u1);
    3116           1 :   tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
    3117           1 :   tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
    3118           1 :   tt_int_op(12348u,OP_EQ, u1);
    3119           1 :   tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
    3120           1 :   tt_int_op(0u,OP_EQ, u1);
    3121           1 :   tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
    3122           1 :   tt_int_op(0u,OP_EQ, u2);
    3123           1 :   tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
    3124           1 :   tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
    3125           1 :   tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
    3126             : 
    3127             :   /* Numbers with size (eg. %2u) */
    3128           1 :   tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
    3129           1 :   tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
    3130           1 :   tt_int_op(12u,OP_EQ, u1);
    3131           1 :   tt_int_op(3456u,OP_EQ, u2);
    3132           1 :   tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
    3133           1 :   tt_int_op(123456u,OP_EQ, u1);
    3134           1 :   tt_int_op(1,OP_EQ, tor_sscanf("123457  ", "%8u", &u1));
    3135           1 :   tt_int_op(123457u,OP_EQ, u1);
    3136           1 :   tt_int_op(0,OP_EQ, tor_sscanf("  123456", "%8u", &u1));
    3137           1 :   tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
    3138           1 :   tt_int_op(12u,OP_EQ, u1);
    3139           1 :   tt_int_op(3u,OP_EQ, u2);
    3140           1 :   tt_int_op(456u,OP_EQ, u3);
    3141           1 :   tt_int_op(3,OP_EQ,
    3142             :             tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
    3143           1 :   tt_int_op(67u,OP_EQ, u1);
    3144           1 :   tt_int_op(8u,OP_EQ, u2);
    3145           1 :   tt_int_op(99u,OP_EQ, u3);
    3146             :   /* %u does not match space.*/
    3147           1 :   tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
    3148           1 :   tt_int_op(12u,OP_EQ, u1);
    3149           1 :   tt_int_op(3u,OP_EQ, u2);
    3150             :   /* %u does not match negative numbers. */
    3151           1 :   tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
    3152           1 :   tt_int_op(67u,OP_EQ, u1);
    3153           1 :   tt_int_op(8u,OP_EQ, u2);
    3154             :   /* Arbitrary amounts of 0-padding are okay */
    3155           1 :   tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
    3156             :                         &u1, &u2, &u3));
    3157           1 :   tt_int_op(12u,OP_EQ, u1);
    3158           1 :   tt_int_op(3u,OP_EQ, u2);
    3159           1 :   tt_int_op(99u,OP_EQ, u3);
    3160             : 
    3161             :   /* Hex (ie. %x) */
    3162           1 :   tt_int_op(3,OP_EQ,
    3163             :             tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
    3164           1 :   tt_int_op(0x1234,OP_EQ, u1);
    3165           1 :   tt_int_op(0x2ABCDEF,OP_EQ, u2);
    3166           1 :   tt_int_op(0xFF,OP_EQ, u3);
    3167             :   /* Width works on %x */
    3168           1 :   tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
    3169           1 :   tt_int_op(0xf00d,OP_EQ, u1);
    3170           1 :   tt_int_op(0xcafe,OP_EQ, u2);
    3171           1 :   tt_int_op(444,OP_EQ, u3);
    3172             : 
    3173             :   /* Literal '%' (ie. '%%') */
    3174           1 :   tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
    3175           1 :   tt_int_op(99,OP_EQ, u1);
    3176           1 :   tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
    3177           1 :   tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
    3178           1 :   tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
    3179           1 :   tt_int_op(99,OP_EQ, u1);
    3180           1 :   tt_str_op(s1,OP_EQ, "fresh");
    3181           1 :   tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
    3182           1 :   tt_str_op("boo",OP_EQ, s1);
    3183             : 
    3184             :   /* Strings (ie. %s) */
    3185           1 :   tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
    3186           1 :   tt_str_op(s1,OP_EQ, "hel");
    3187           1 :   tt_str_op(s2,OP_EQ, "lo");
    3188           1 :   tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
    3189           1 :   tt_str_op(s3,OP_EQ, "WD");
    3190           1 :   tt_int_op(40,OP_EQ, u1);
    3191           1 :   tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
    3192           1 :   tt_str_op(s3,OP_EQ, "WD4");
    3193           1 :   tt_int_op(0,OP_EQ, u1);
    3194           1 :   tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
    3195           1 :   tt_int_op(76,OP_EQ, u1);
    3196           1 :   tt_str_op(s1,OP_EQ, "trombones");
    3197             :   {
    3198           1 :     huge = tor_malloc(1000);
    3199           1 :     r = tor_sscanf("prettylongstring", "%999s", huge);
    3200           1 :     tt_int_op(1,OP_EQ, r);
    3201           1 :     tt_str_op(huge,OP_EQ, "prettylongstring");
    3202           1 :     tor_free(huge);
    3203             :   }
    3204             :   /* %s doesn't eat spaces */
    3205           1 :   tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
    3206           1 :   tt_str_op(s1,OP_EQ, "hello");
    3207           1 :   tt_str_op(s2,OP_EQ, "world");
    3208           1 :   tt_int_op(2,OP_EQ, tor_sscanf("bye   world?", "%9s %9s", s1, s2));
    3209           1 :   tt_str_op(s1,OP_EQ, "bye");
    3210           1 :   tt_str_op(s2,OP_EQ, "");
    3211           1 :   tt_int_op(3,OP_EQ,
    3212             :             tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
    3213           1 :   tt_str_op(s1,OP_EQ, "hi");
    3214           1 :   tt_str_op(s2,OP_EQ, "");
    3215           1 :   tt_str_op(s3,OP_EQ, "");
    3216             : 
    3217           1 :   tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
    3218           1 :   tt_int_op(4,OP_EQ,
    3219             :             tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
    3220           1 :   tt_int_op(' ',OP_EQ, ch);
    3221             : 
    3222           1 :   r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
    3223           1 :   tt_int_op(r,OP_EQ, 3);
    3224           1 :   tt_int_op(int1,OP_EQ, 12345);
    3225           1 :   tt_int_op(lng1,OP_EQ, -67890);
    3226           1 :   tt_int_op(int2,OP_EQ, -1);
    3227             : 
    3228             : #if SIZEOF_INT == 4
    3229             :   /* %u */
    3230             :   /* UINT32_MAX should work */
    3231           1 :   tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
    3232           1 :   tt_int_op(4294967295U,OP_EQ, u1);
    3233             : 
    3234             :   /* But UINT32_MAX + 1 shouldn't work */
    3235           1 :   tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
    3236             :   /* but parsing only 9... */
    3237           1 :   tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
    3238           1 :   tt_int_op(429496729U,OP_EQ, u1);
    3239             : 
    3240             :   /* %x */
    3241             :   /* UINT32_MAX should work */
    3242           1 :   tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
    3243           1 :   tt_int_op(0xFFFFFFFF,OP_EQ, u1);
    3244             : 
    3245             :   /* But UINT32_MAX + 1 shouldn't work */
    3246           1 :   tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
    3247             : 
    3248             :   /* %d */
    3249             :   /* INT32_MIN and INT32_MAX should work */
    3250           1 :   r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
    3251           1 :   tt_int_op(r,OP_EQ, 2);
    3252           1 :   tt_int_op(int1,OP_EQ, -2147483647 - 1);
    3253           1 :   tt_int_op(int2,OP_EQ, 2147483647);
    3254             : 
    3255             :   /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
    3256           1 :   r = tor_sscanf("-2147483649.", "%d.", &int1);
    3257           1 :   tt_int_op(r,OP_EQ, 0);
    3258             : 
    3259           1 :   r = tor_sscanf("2147483648.", "%d.", &int1);
    3260           1 :   tt_int_op(r,OP_EQ, 0);
    3261             : 
    3262             :   /* and the first failure stops further processing */
    3263           1 :   r = tor_sscanf("-2147483648. 2147483648.",
    3264             :                  "%d. %d.", &int1, &int2);
    3265           1 :   tt_int_op(r,OP_EQ, 1);
    3266             : 
    3267           1 :   r = tor_sscanf("-2147483649. 2147483647.",
    3268             :                  "%d. %d.", &int1, &int2);
    3269           1 :   tt_int_op(r,OP_EQ, 0);
    3270             : 
    3271           1 :   r = tor_sscanf("2147483648. -2147483649.",
    3272             :                  "%d. %d.", &int1, &int2);
    3273           1 :   tt_int_op(r,OP_EQ, 0);
    3274             : #elif SIZEOF_INT == 8
    3275             :   /* %u */
    3276             :   /* UINT64_MAX should work */
    3277             :   tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
    3278             :   tt_int_op(18446744073709551615U,OP_EQ, u1);
    3279             : 
    3280             :   /* But UINT64_MAX + 1 shouldn't work */
    3281             :   tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
    3282             :   /* but parsing only 19... */
    3283             :   tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
    3284             :   tt_int_op(1844674407370955161U,OP_EQ, u1);
    3285             : 
    3286             :   /* %x */
    3287             :   /* UINT64_MAX should work */
    3288             :   tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
    3289             :   tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
    3290             : 
    3291             :   /* But UINT64_MAX + 1 shouldn't work */
    3292             :   tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
    3293             : 
    3294             :   /* %d */
    3295             :   /* INT64_MIN and INT64_MAX should work */
    3296             :   r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
    3297             :                  "%d. %d.", &int1, &int2);
    3298             :   tt_int_op(r,OP_EQ, 2);
    3299             :   tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
    3300             :   tt_int_op(int2,OP_EQ, 9223372036854775807);
    3301             : 
    3302             :   /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
    3303             :   r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
    3304             :   tt_int_op(r,OP_EQ, 0);
    3305             : 
    3306             :   r = tor_sscanf("9223372036854775808.", "%d.", &int1);
    3307             :   tt_int_op(r,OP_EQ, 0);
    3308             : 
    3309             :   /* and the first failure stops further processing */
    3310             :   r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
    3311             :                  "%d. %d.", &int1, &int2);
    3312             :   tt_int_op(r,OP_EQ, 1);
    3313             : 
    3314             :   r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
    3315             :                  "%d. %d.", &int1, &int2);
    3316             :   tt_int_op(r,OP_EQ, 0);
    3317             : 
    3318             :   r = tor_sscanf("9223372036854775808. -9223372036854775809.",
    3319             :                  "%d. %d.", &int1, &int2);
    3320             :   tt_int_op(r,OP_EQ, 0);
    3321             : #endif /* SIZEOF_INT == 4 || ... */
    3322             : 
    3323             : #if SIZEOF_LONG == 4
    3324             :   /* %lu */
    3325             :   /* UINT32_MAX should work */
    3326             :   tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
    3327             :   tt_int_op(4294967295UL,OP_EQ, ulng);
    3328             : 
    3329             :   /* But UINT32_MAX + 1 shouldn't work */
    3330             :   tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
    3331             :   /* but parsing only 9... */
    3332             :   tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
    3333             :   tt_int_op(429496729UL,OP_EQ, ulng);
    3334             : 
    3335             :   /* %lx */
    3336             :   /* UINT32_MAX should work */
    3337             :   tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
    3338             :   tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
    3339             : 
    3340             :   /* But UINT32_MAX + 1 shouldn't work */
    3341             :   tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
    3342             : 
    3343             :   /* %ld */
    3344             :   /* INT32_MIN and INT32_MAX should work */
    3345             :   r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
    3346             :   tt_int_op(r,OP_EQ, 2);
    3347             :   tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
    3348             :   tt_int_op(lng2,OP_EQ, 2147483647L);
    3349             : 
    3350             :   /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
    3351             :   r = tor_sscanf("-2147483649.", "%ld.", &lng1);
    3352             :   tt_int_op(r,OP_EQ, 0);
    3353             : 
    3354             :   r = tor_sscanf("2147483648.", "%ld.", &lng1);
    3355             :   tt_int_op(r,OP_EQ, 0);
    3356             : 
    3357             :   /* and the first failure stops further processing */
    3358             :   r = tor_sscanf("-2147483648. 2147483648.",
    3359             :                  "%ld. %ld.", &lng1, &lng2);
    3360             :   tt_int_op(r,OP_EQ, 1);
    3361             : 
    3362             :   r = tor_sscanf("-2147483649. 2147483647.",
    3363             :                  "%ld. %ld.", &lng1, &lng2);
    3364             :   tt_int_op(r,OP_EQ, 0);
    3365             : 
    3366             :   r = tor_sscanf("2147483648. -2147483649.",
    3367             :                  "%ld. %ld.", &lng1, &lng2);
    3368             :   tt_int_op(r,OP_EQ, 0);
    3369             : #elif SIZEOF_LONG == 8
    3370             :   /* %lu */
    3371             :   /* UINT64_MAX should work */
    3372           1 :   tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
    3373           1 :   tt_int_op(18446744073709551615UL,OP_EQ, ulng);
    3374             : 
    3375             :   /* But UINT64_MAX + 1 shouldn't work */
    3376           1 :   tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
    3377             :   /* but parsing only 19... */
    3378           1 :   tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
    3379           1 :   tt_int_op(1844674407370955161UL,OP_EQ, ulng);
    3380             : 
    3381             :   /* %lx */
    3382             :   /* UINT64_MAX should work */
    3383           1 :   tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
    3384           1 :   tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
    3385             : 
    3386             :   /* But UINT64_MAX + 1 shouldn't work */
    3387           1 :   tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
    3388             : 
    3389             :   /* %ld */
    3390             :   /* INT64_MIN and INT64_MAX should work */
    3391           1 :   r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
    3392             :                  "%ld. %ld.", &lng1, &lng2);
    3393           1 :   tt_int_op(r,OP_EQ, 2);
    3394           1 :   tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
    3395           1 :   tt_int_op(lng2,OP_EQ, 9223372036854775807L);
    3396             : 
    3397             :   /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
    3398           1 :   r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
    3399           1 :   tt_int_op(r,OP_EQ, 0);
    3400             : 
    3401           1 :   r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
    3402           1 :   tt_int_op(r,OP_EQ, 0);
    3403             : 
    3404             :   /* and the first failure stops further processing */
    3405           1 :   r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
    3406             :                  "%ld. %ld.", &lng1, &lng2);
    3407           1 :   tt_int_op(r,OP_EQ, 1);
    3408             : 
    3409           1 :   r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
    3410             :                  "%ld. %ld.", &lng1, &lng2);
    3411           1 :   tt_int_op(r,OP_EQ, 0);
    3412             : 
    3413           1 :   r = tor_sscanf("9223372036854775808. -9223372036854775809.",
    3414             :                  "%ld. %ld.", &lng1, &lng2);
    3415           1 :   tt_int_op(r,OP_EQ, 0);
    3416             : #endif /* SIZEOF_LONG == 4 || ... */
    3417             : 
    3418           1 :   r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
    3419             :                  "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
    3420           1 :   tt_int_op(r,OP_EQ, 4);
    3421           1 :   test_feq(d1, 123.456);
    3422           1 :   test_feq(d2, .000007);
    3423           1 :   test_feq(d3, -900123123.2000787);
    3424           1 :   test_feq(d4, 3.2);
    3425             : 
    3426             :   /* missing float */
    3427           1 :   r = tor_sscanf("3 ", "%d %lf", &int1, &d1);
    3428           1 :   tt_int_op(r, OP_EQ, 1);
    3429           1 :   tt_int_op(int1, OP_EQ, 3);
    3430             : 
    3431             :   /* not a float */
    3432           1 :   r = tor_sscanf("999 notafloat", "%d %lf", &int1, &d1);
    3433           1 :   tt_int_op(r, OP_EQ, 1);
    3434           1 :   tt_int_op(int1, OP_EQ, 999);
    3435             : 
    3436             :   /* %s but no buffer. */
    3437           1 :   char *nullbuf = NULL;
    3438           1 :   r = tor_sscanf("hello", "%3s", nullbuf);
    3439           1 :   tt_int_op(r, OP_EQ, 0);
    3440             : 
    3441           1 :  done:
    3442           1 :   tor_free(huge);
    3443           1 : }
    3444             : 
    3445             : #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
    3446             : #define tt_ci_char_op(a,op,b) \
    3447             :   tt_char_op(TOR_TOLOWER((int)a),op,TOR_TOLOWER((int)b))
    3448             : 
    3449             : #ifndef HAVE_STRNLEN
    3450             : static size_t
    3451             : strnlen(const char *s, size_t len)
    3452             : {
    3453             :   const char *p = memchr(s, 0, len);
    3454             :   if (!p)
    3455             :     return len;
    3456             :   return p - s;
    3457             : }
    3458             : #endif /* !defined(HAVE_STRNLEN) */
    3459             : 
    3460             : static void
    3461           1 : test_util_format_time_interval(void *arg)
    3462             : {
    3463             :   /* use the same sized buffer and integers as tor uses */
    3464             : #define DBUF_SIZE 64
    3465           1 :   char dbuf[DBUF_SIZE];
    3466             : #define T_        "%ld"
    3467           1 :   long sec, min, hour, day;
    3468             : 
    3469             :   /* we don't care about the exact spelling of the
    3470             :    * second(s), minute(s), hour(s), day(s) labels */
    3471             : #define LABEL_SIZE 21
    3472             : #define L_        "%20s"
    3473           1 :   char label_s[LABEL_SIZE];
    3474           1 :   char label_m[LABEL_SIZE];
    3475           1 :   char label_h[LABEL_SIZE];
    3476           1 :   char label_d[LABEL_SIZE];
    3477             : 
    3478             : #define TL_       T_ " " L_
    3479             : 
    3480           1 :   int r;
    3481             : 
    3482           1 :   (void)arg;
    3483             : 
    3484             :   /* In these tests, we're not picky about
    3485             :    * spelling or abbreviations */
    3486             : 
    3487             :   /* seconds: 0, 1, 9, 10, 59 */
    3488             : 
    3489             :   /* ignore exact spelling of "second(s)"*/
    3490           1 :   format_time_interval(dbuf, sizeof(dbuf), 0);
    3491           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3492           1 :   r = tor_sscanf(dbuf, TL_, &sec, label_s);
    3493           1 :   tt_int_op(r,OP_EQ, 2);
    3494           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3495           1 :   tt_int_op(sec,OP_EQ, 0);
    3496             : 
    3497           1 :   format_time_interval(dbuf, sizeof(dbuf), 1);
    3498           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3499           1 :   r = tor_sscanf(dbuf, TL_, &sec, label_s);
    3500           1 :   tt_int_op(r,OP_EQ, 2);
    3501           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3502           1 :   tt_int_op(sec,OP_EQ, 1);
    3503             : 
    3504           1 :   format_time_interval(dbuf, sizeof(dbuf), 10);
    3505           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3506           1 :   r = tor_sscanf(dbuf, TL_, &sec, label_s);
    3507           1 :   tt_int_op(r,OP_EQ, 2);
    3508           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3509           1 :   tt_int_op(sec,OP_EQ, 10);
    3510             : 
    3511           1 :   format_time_interval(dbuf, sizeof(dbuf), 59);
    3512           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3513           1 :   r = tor_sscanf(dbuf, TL_, &sec, label_s);
    3514           1 :   tt_int_op(r,OP_EQ, 2);
    3515           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3516           1 :   tt_int_op(sec,OP_EQ, 59);
    3517             : 
    3518             :   /* negative seconds are reported as their absolute value */
    3519             : 
    3520           1 :   format_time_interval(dbuf, sizeof(dbuf), -4);
    3521           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3522           1 :   r = tor_sscanf(dbuf, TL_, &sec, label_s);
    3523           1 :   tt_int_op(r,OP_EQ, 2);
    3524           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3525           1 :   tt_int_op(sec,OP_EQ, 4);
    3526           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3527             : 
    3528           1 :   format_time_interval(dbuf, sizeof(dbuf), -32);
    3529           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3530           1 :   r = tor_sscanf(dbuf, TL_, &sec, label_s);
    3531           1 :   tt_int_op(r,OP_EQ, 2);
    3532           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3533           1 :   tt_int_op(sec,OP_EQ, 32);
    3534           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3535             : 
    3536             :   /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
    3537             : 
    3538             :   /* ignore trailing "0 second(s)", if present */
    3539           1 :   format_time_interval(dbuf, sizeof(dbuf), 60);
    3540           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3541           1 :   r = tor_sscanf(dbuf, TL_, &min, label_m);
    3542           1 :   tt_int_op(r,OP_EQ, 2);
    3543           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3544           1 :   tt_int_op(min,OP_EQ, 1);
    3545           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3546             : 
    3547             :   /* ignore exact spelling of "minute(s)," and "second(s)" */
    3548           1 :   format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
    3549           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3550           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3551             :                  &min, label_m, &sec, label_s);
    3552           1 :   tt_int_op(r,OP_EQ, 4);
    3553           1 :   tt_int_op(min,OP_EQ, 1);
    3554           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3555           1 :   tt_int_op(sec,OP_EQ, 1);
    3556           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3557           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3558             : 
    3559           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
    3560           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3561           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3562             :                  &min, label_m, &sec, label_s);
    3563           1 :   tt_int_op(r,OP_EQ, 4);
    3564           1 :   tt_int_op(min,OP_EQ, 1);
    3565           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3566           1 :   tt_int_op(sec,OP_EQ, 59);
    3567           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3568             : 
    3569             :   /* ignore trailing "0 second(s)", if present */
    3570           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*2);
    3571           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3572           1 :   r = tor_sscanf(dbuf, TL_, &min, label_m);
    3573           1 :   tt_int_op(r,OP_EQ, 2);
    3574           1 :   tt_int_op(min,OP_EQ, 2);
    3575           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3576             : 
    3577             :   /* ignore exact spelling of "minute(s)," and "second(s)" */
    3578           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
    3579           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3580           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3581             :                  &min, label_m, &sec, label_s);
    3582           1 :   tt_int_op(r,OP_EQ, 4);
    3583           1 :   tt_int_op(min,OP_EQ, 2);
    3584           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3585           1 :   tt_int_op(sec,OP_EQ, 1);
    3586           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3587             : 
    3588           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
    3589           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3590           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3591             :                  &min, label_m, &sec, label_s);
    3592           1 :   tt_int_op(r,OP_EQ, 4);
    3593           1 :   tt_int_op(min,OP_EQ, 59);
    3594           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3595           1 :   tt_int_op(sec,OP_EQ, 59);
    3596           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3597             : 
    3598             :   /* negative minutes are reported as their absolute value */
    3599             : 
    3600             :   /* ignore trailing "0 second(s)", if present */
    3601           1 :   format_time_interval(dbuf, sizeof(dbuf), -3*60);
    3602           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3603           1 :   r = tor_sscanf(dbuf, TL_, &min, label_m);
    3604           1 :   tt_int_op(r,OP_EQ, 2);
    3605           1 :   tt_int_op(min,OP_EQ, 3);
    3606           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3607             : 
    3608             :   /* ignore exact spelling of "minute(s)," and "second(s)" */
    3609           1 :   format_time_interval(dbuf, sizeof(dbuf), -96);
    3610           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3611           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3612             :                  &min, label_m, &sec, label_s);
    3613           1 :   tt_int_op(r,OP_EQ, 4);
    3614           1 :   tt_int_op(min,OP_EQ, 1);
    3615           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3616           1 :   tt_int_op(sec,OP_EQ, 36);
    3617           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3618             : 
    3619           1 :   format_time_interval(dbuf, sizeof(dbuf), -2815);
    3620           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3621           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3622             :                  &min, label_m, &sec, label_s);
    3623           1 :   tt_int_op(r,OP_EQ, 4);
    3624           1 :   tt_int_op(min,OP_EQ, 46);
    3625           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3626           1 :   tt_int_op(sec,OP_EQ, 55);
    3627           1 :   tt_ci_char_op(label_s[0],OP_EQ, 's');
    3628             : 
    3629             :   /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
    3630             :   /* always ignore trailing seconds, if present */
    3631             : 
    3632             :   /* ignore trailing "0 minute(s)" etc., if present */
    3633           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*60);
    3634           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3635           1 :   r = tor_sscanf(dbuf, TL_, &hour, label_h);
    3636           1 :   tt_int_op(r,OP_EQ, 2);
    3637           1 :   tt_int_op(hour,OP_EQ, 1);
    3638           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3639             : 
    3640           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
    3641           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3642           1 :   r = tor_sscanf(dbuf, TL_, &hour, label_h);
    3643           1 :   tt_int_op(r,OP_EQ, 2);
    3644           1 :   tt_int_op(hour,OP_EQ, 1);
    3645           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3646             : 
    3647             :   /* ignore exact spelling of "hour(s)," etc. */
    3648           1 :   format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
    3649           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3650           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3651             :                  &hour, label_h, &min, label_m);
    3652           1 :   tt_int_op(r,OP_EQ, 4);
    3653           1 :   tt_int_op(hour,OP_EQ, 1);
    3654           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3655           1 :   tt_int_op(min,OP_EQ, 1);
    3656           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3657             : 
    3658           1 :   format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
    3659           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3660           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3661             :                  &hour, label_h, &min, label_m);
    3662           1 :   tt_int_op(r,OP_EQ, 4);
    3663           1 :   tt_int_op(hour,OP_EQ, 23);
    3664           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3665           1 :   tt_int_op(min,OP_EQ, 59);
    3666           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3667             : 
    3668           1 :   format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
    3669           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3670           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3671             :                  &hour, label_h, &min, label_m);
    3672           1 :   tt_int_op(r,OP_EQ, 4);
    3673           1 :   tt_int_op(hour,OP_EQ, 23);
    3674           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3675           1 :   tt_int_op(min,OP_EQ, 59);
    3676           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3677             : 
    3678             :   /* negative hours are reported as their absolute value */
    3679             : 
    3680             :   /* ignore exact spelling of "hour(s)," etc., if present */
    3681           1 :   format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
    3682           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3683           1 :   r = tor_sscanf(dbuf, TL_, &hour, label_h);
    3684           1 :   tt_int_op(r,OP_EQ, 2);
    3685           1 :   tt_int_op(hour,OP_EQ, 2);
    3686           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3687             : 
    3688           1 :   format_time_interval(dbuf, sizeof(dbuf), -75804);
    3689           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3690           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3691             :                  &hour, label_h, &min, label_m);
    3692           1 :   tt_int_op(r,OP_EQ, 4);
    3693           1 :   tt_int_op(hour,OP_EQ, 21);
    3694           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3695           1 :   tt_int_op(min,OP_EQ, 3);
    3696           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3697             : 
    3698             :   /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
    3699             :   /* always ignore trailing seconds, if present */
    3700             : 
    3701             :   /* ignore trailing "0 hours(s)" etc., if present */
    3702           1 :   format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
    3703           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3704           1 :   r = tor_sscanf(dbuf, TL_, &day, label_d);
    3705           1 :   tt_int_op(r,OP_EQ, 2);
    3706           1 :   tt_int_op(day,OP_EQ, 1);
    3707           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3708             : 
    3709           1 :   format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
    3710           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3711           1 :   r = tor_sscanf(dbuf, TL_, &day, label_d);
    3712           1 :   tt_int_op(r,OP_EQ, 2);
    3713           1 :   tt_int_op(day,OP_EQ, 1);
    3714           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3715             : 
    3716             :   /* ignore exact spelling of "days(s)," etc. */
    3717           1 :   format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
    3718           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3719           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3720             :                  &day, label_d, &hour, label_h, &min, label_m);
    3721           1 :   if (r == -1) {
    3722             :     /* ignore 0 hours(s), if present */
    3723           0 :     r = tor_sscanf(dbuf, TL_ " " TL_,
    3724             :                    &day, label_d, &min, label_m);
    3725             :   }
    3726           1 :   tt_assert(r == 4 || r == 6);
    3727           1 :   tt_int_op(day,OP_EQ, 1);
    3728           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3729           1 :   if (r == 6) {
    3730           1 :     tt_int_op(hour,OP_EQ, 0);
    3731           1 :     tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3732             :   }
    3733           1 :   tt_int_op(min,OP_EQ, 1);
    3734           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3735             : 
    3736             :   /* ignore trailing "0 minutes(s)" etc., if present */
    3737           1 :   format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
    3738           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3739           1 :   r = tor_sscanf(dbuf, TL_ " " TL_,
    3740             :                  &day, label_d, &hour, label_h);
    3741           1 :   tt_int_op(r,OP_EQ, 4);
    3742           1 :   tt_int_op(day,OP_EQ, 1);
    3743           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3744           1 :   tt_int_op(hour,OP_EQ, 1);
    3745           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3746             : 
    3747             :   /* negative days are reported as their absolute value */
    3748             : 
    3749           1 :   format_time_interval(dbuf, sizeof(dbuf), -21936184);
    3750           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3751           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3752             :                  &day, label_d, &hour, label_h, &min, label_m);
    3753           1 :   tt_int_op(r,OP_EQ, 6);
    3754           1 :   tt_int_op(day,OP_EQ, 253);
    3755           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3756           1 :   tt_int_op(hour,OP_EQ, 21);
    3757           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3758           1 :   tt_int_op(min,OP_EQ, 23);
    3759           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3760             : 
    3761             :   /* periods > 1 year are reported in days (warn?) */
    3762             : 
    3763             :   /* ignore exact spelling of "days(s)," etc., if present */
    3764           1 :   format_time_interval(dbuf, sizeof(dbuf), 758635154);
    3765           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3766           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3767             :                  &day, label_d, &hour, label_h, &min, label_m);
    3768           1 :   tt_int_op(r,OP_EQ, 6);
    3769           1 :   tt_int_op(day,OP_EQ, 8780);
    3770           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3771           1 :   tt_int_op(hour,OP_EQ, 11);
    3772           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3773           1 :   tt_int_op(min,OP_EQ, 59);
    3774           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3775             : 
    3776             :   /* negative periods > 1 year are reported in days (warn?) */
    3777             : 
    3778           1 :   format_time_interval(dbuf, sizeof(dbuf), -1427014922);
    3779           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3780           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3781             :                  &day, label_d, &hour, label_h, &min, label_m);
    3782           1 :   tt_int_op(r,OP_EQ, 6);
    3783           1 :   tt_int_op(day,OP_EQ, 16516);
    3784           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3785           1 :   tt_int_op(hour,OP_EQ, 9);
    3786           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3787           1 :   tt_int_op(min,OP_EQ, 2);
    3788           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3789             : 
    3790             : #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
    3791             : 
    3792             :   /* We can try INT32_MIN/MAX */
    3793             :   /* Always ignore second(s) */
    3794             : 
    3795             :   /* INT32_MAX */
    3796           1 :   format_time_interval(dbuf, sizeof(dbuf), 2147483647);
    3797           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3798           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3799             :                  &day, label_d, &hour, label_h, &min, label_m);
    3800           1 :   tt_int_op(r,OP_EQ, 6);
    3801           1 :   tt_int_op(day,OP_EQ, 24855);
    3802           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3803           1 :   tt_int_op(hour,OP_EQ, 3);
    3804           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3805           1 :   tt_int_op(min,OP_EQ, 14);
    3806           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3807             :   /* and 7 seconds - ignored */
    3808             : 
    3809             :   /* INT32_MIN: check that we get the absolute value of interval,
    3810             :    * which doesn't actually fit in int32_t.
    3811             :    * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
    3812           1 :   format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
    3813           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3814           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3815             :                  &day, label_d, &hour, label_h, &min, label_m);
    3816           1 :   tt_int_op(r,OP_EQ, 6);
    3817           1 :   tt_int_op(day,OP_EQ, 24855);
    3818           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3819           1 :   tt_int_op(hour,OP_EQ, 3);
    3820           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3821           1 :   tt_int_op(min,OP_EQ, 14);
    3822           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3823             :   /* and 7 or 8 seconds - ignored */
    3824             : 
    3825             : #endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */
    3826             : 
    3827             : #if SIZEOF_LONG == 8
    3828             : 
    3829             :   /* We can try INT64_MIN/MAX */
    3830             :   /* Always ignore second(s) */
    3831             : 
    3832             :   /* INT64_MAX */
    3833           1 :   format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
    3834           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3835           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3836             :                  &day, label_d, &hour, label_h, &min, label_m);
    3837           1 :   tt_int_op(r,OP_EQ, 6);
    3838           1 :   tt_int_op(day,OP_EQ, 106751991167300L);
    3839           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3840           1 :   tt_int_op(hour,OP_EQ, 15);
    3841           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3842           1 :   tt_int_op(min,OP_EQ, 30);
    3843           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3844             :   /* and 7 seconds - ignored */
    3845             : 
    3846             :   /* INT64_MIN: check that we get the absolute value of interval,
    3847             :    * which doesn't actually fit in int64_t.
    3848             :    * We expect INT64_MAX */
    3849           1 :   format_time_interval(dbuf, sizeof(dbuf),
    3850             :                        -9223372036854775807L - 1L);
    3851           1 :   tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
    3852           1 :   r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
    3853             :                  &day, label_d, &hour, label_h, &min, label_m);
    3854           1 :   tt_int_op(r,OP_EQ, 6);
    3855           1 :   tt_int_op(day,OP_EQ, 106751991167300L);
    3856           1 :   tt_ci_char_op(label_d[0],OP_EQ, 'd');
    3857           1 :   tt_int_op(hour,OP_EQ, 15);
    3858           1 :   tt_ci_char_op(label_h[0],OP_EQ, 'h');
    3859           1 :   tt_int_op(min,OP_EQ, 30);
    3860           1 :   tt_ci_char_op(label_m[0],OP_EQ, 'm');
    3861             :   /* and 7 or 8 seconds - ignored */
    3862             : 
    3863             : #endif /* SIZEOF_LONG == 8 */
    3864             : 
    3865           1 :  done:
    3866           1 :   ;
    3867           1 : }
    3868             : 
    3869             : #undef tt_char_op
    3870             : #undef tt_ci_char_op
    3871             : #undef DBUF_SIZE
    3872             : #undef T_
    3873             : #undef LABEL_SIZE
    3874             : #undef L_
    3875             : #undef TL_
    3876             : 
    3877             : static void
    3878           1 : test_util_path_is_relative(void *arg)
    3879             : {
    3880             :   /* OS-independent tests */
    3881           1 :   (void)arg;
    3882           1 :   tt_int_op(1,OP_EQ, path_is_relative(""));
    3883           1 :   tt_int_op(1,OP_EQ, path_is_relative("dir"));
    3884           1 :   tt_int_op(1,OP_EQ, path_is_relative("dir/"));
    3885           1 :   tt_int_op(1,OP_EQ, path_is_relative("./dir"));
    3886           1 :   tt_int_op(1,OP_EQ, path_is_relative("../dir"));
    3887             : 
    3888           1 :   tt_int_op(0,OP_EQ, path_is_relative("/"));
    3889           1 :   tt_int_op(0,OP_EQ, path_is_relative("/dir"));
    3890           1 :   tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
    3891             : 
    3892             :   /* Windows */
    3893             : #ifdef _WIN32
    3894             :   /* I don't have Windows so I can't test this, hence the "#ifdef
    3895             :      0". These are tests that look useful, so please try to get them
    3896             :      running and uncomment if it all works as it should */
    3897             :   tt_int_op(1,OP_EQ, path_is_relative("dir"));
    3898             :   tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
    3899             :   tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
    3900             :   tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
    3901             :   tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
    3902             : 
    3903             :   tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
    3904             :   tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
    3905             :   tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
    3906             : #endif /* defined(_WIN32) */
    3907             : 
    3908           1 :  done:
    3909           1 :   ;
    3910           1 : }
    3911             : 
    3912             : /** Run unittests for memory area allocator */
    3913             : static void
    3914           1 : test_util_memarea(void *arg)
    3915             : {
    3916           1 :   memarea_t *area = memarea_new();
    3917           1 :   char *p1, *p2, *p3, *p1_orig;
    3918           1 :   void *malloced_ptr = NULL;
    3919           1 :   int i;
    3920             : 
    3921             : #ifdef DISABLE_MEMORY_SENTINELS
    3922             :   /* If memory sentinels are disabled, this whole module is just an alias for
    3923             :      malloc(), which is free to lay out memory most any way it wants. */
    3924             :   if (1)
    3925             :     tt_skip();
    3926             : #endif /* defined(DISABLE_MEMORY_SENTINELS) */
    3927             : 
    3928           1 :   (void)arg;
    3929           1 :   tt_assert(area);
    3930             : 
    3931           1 :   p1_orig = p1 = memarea_alloc(area,64);
    3932           1 :   p2 = memarea_alloc_zero(area,52);
    3933           1 :   p3 = memarea_alloc(area,11);
    3934             : 
    3935           1 :   tt_assert(memarea_owns_ptr(area, p1));
    3936           1 :   tt_assert(memarea_owns_ptr(area, p2));
    3937           1 :   tt_assert(memarea_owns_ptr(area, p3));
    3938             :   /* Make sure we left enough space. */
    3939           1 :   tt_assert(p1+64 <= p2);
    3940           1 :   tt_assert(p2+52 <= p3);
    3941             :   /* Make sure we aligned. */
    3942           1 :   tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
    3943           1 :   tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
    3944           1 :   tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
    3945           1 :   tt_assert(!memarea_owns_ptr(area, p3+8192));
    3946           1 :   tt_assert(!memarea_owns_ptr(area, p3+30));
    3947           1 :   tt_assert(fast_mem_is_zero(p2, 52));
    3948             :   /* Make sure we don't overalign. */
    3949           1 :   p1 = memarea_alloc(area, 1);
    3950           1 :   p2 = memarea_alloc(area, 1);
    3951           1 :   tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
    3952             :   {
    3953           1 :     malloced_ptr = tor_malloc(64);
    3954           1 :     tt_assert(!memarea_owns_ptr(area, malloced_ptr));
    3955           1 :     tor_free(malloced_ptr);
    3956             :   }
    3957             : 
    3958             :   /* memarea_memdup */
    3959             :   {
    3960           1 :     malloced_ptr = tor_malloc(64);
    3961           1 :     crypto_rand((char*)malloced_ptr, 64);
    3962           1 :     p1 = memarea_memdup(area, malloced_ptr, 64);
    3963           1 :     tt_assert(p1 != malloced_ptr);
    3964           1 :     tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
    3965           1 :     tor_free(malloced_ptr);
    3966             :   }
    3967             : 
    3968             :   /* memarea_strdup. */
    3969           1 :   p1 = memarea_strdup(area,"");
    3970           1 :   p2 = memarea_strdup(area, "abcd");
    3971           1 :   tt_assert(p1);
    3972           1 :   tt_assert(p2);
    3973           1 :   tt_str_op(p1,OP_EQ, "");
    3974           1 :   tt_str_op(p2,OP_EQ, "abcd");
    3975             : 
    3976             :   /* memarea_strndup. */
    3977             :   {
    3978           1 :     const char *s = "Ad ogni porta batte la morte e grida: il nome!";
    3979             :     /* (From Turandot, act 3.) */
    3980           1 :     size_t len = strlen(s);
    3981           1 :     p1 = memarea_strndup(area, s, 1000);
    3982           1 :     p2 = memarea_strndup(area, s, 10);
    3983           1 :     tt_str_op(p1,OP_EQ, s);
    3984           1 :     tt_assert(p2 >= p1 + len + 1);
    3985           1 :     tt_mem_op(s,OP_EQ, p2, 10);
    3986           1 :     tt_int_op(p2[10],OP_EQ, '\0');
    3987           1 :     p3 = memarea_strndup(area, s, len);
    3988           1 :     tt_str_op(p3,OP_EQ, s);
    3989           1 :     p3 = memarea_strndup(area, s, len-1);
    3990           1 :     tt_mem_op(s,OP_EQ, p3, len-1);
    3991           1 :     tt_int_op(p3[len-1],OP_EQ, '\0');
    3992             :   }
    3993             : 
    3994           1 :   memarea_clear(area);
    3995           1 :   p1 = memarea_alloc(area, 1);
    3996           1 :   tt_ptr_op(p1,OP_EQ, p1_orig);
    3997           1 :   memarea_clear(area);
    3998           1 :   size_t total = 0, initial_allocation, allocation2, dummy;
    3999           1 :   memarea_get_stats(area, &initial_allocation, &dummy);
    4000             : 
    4001             :   /* Check for running over an area's size. */
    4002        4098 :   for (i = 0; i < 4096; ++i) {
    4003        4096 :     size_t n = crypto_rand_int(6);
    4004        4096 :     p1 = memarea_alloc(area, n);
    4005        4096 :     total += n;
    4006        4096 :     tt_assert(memarea_owns_ptr(area, p1));
    4007             :   }
    4008           1 :   memarea_assert_ok(area);
    4009           1 :   memarea_get_stats(area, &allocation2, &dummy);
    4010             :   /* Make sure we can allocate a too-big object. */
    4011           1 :   p1 = memarea_alloc_zero(area, 9000);
    4012           1 :   p2 = memarea_alloc_zero(area, 16);
    4013           1 :   total += 9000;
    4014           1 :   total += 16;
    4015           1 :   tt_assert(memarea_owns_ptr(area, p1));
    4016           1 :   tt_assert(memarea_owns_ptr(area, p2));
    4017             : 
    4018             :   /* Now test stats... */
    4019           1 :   size_t allocated = 0, used = 0;
    4020           1 :   memarea_get_stats(area, &allocated, &used);
    4021           1 :   tt_int_op(used, OP_LE, allocated);
    4022           1 :   tt_int_op(used, OP_GE, total); /* not EQ, because of alignment and headers*/
    4023           1 :   tt_int_op(allocated, OP_GT, allocation2);
    4024             : 
    4025           1 :   tt_int_op(allocation2, OP_GT, initial_allocation);
    4026             : 
    4027           1 :   memarea_clear(area);
    4028           1 :   memarea_get_stats(area, &allocated, &used);
    4029           1 :   tt_int_op(used, OP_LT, 128); /* Not 0, because of header */
    4030           1 :   tt_int_op(allocated, OP_EQ, initial_allocation);
    4031             : 
    4032           1 :  done:
    4033           1 :   memarea_drop_all(area);
    4034           1 :   tor_free(malloced_ptr);
    4035           1 : }
    4036             : 
    4037             : /** Run unit tests for utility functions to get file names relative to
    4038             :  * the data directory. */
    4039             : static void
    4040           1 : test_util_datadir(void *arg)
    4041             : {
    4042           1 :   char buf[1024];
    4043           1 :   char *f = NULL;
    4044           1 :   char *temp_dir = NULL;
    4045             : 
    4046           1 :   (void)arg;
    4047           1 :   temp_dir = get_datadir_fname(NULL);
    4048           1 :   f = get_datadir_fname("state");
    4049           1 :   tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
    4050           1 :   tt_str_op(f,OP_EQ, buf);
    4051           1 :   tor_free(f);
    4052           1 :   f = get_datadir_fname2("cache", "thingy");
    4053           1 :   tor_snprintf(buf, sizeof(buf),
    4054             :                "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
    4055           1 :   tt_str_op(f,OP_EQ, buf);
    4056           1 :   tor_free(f);
    4057           1 :   f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
    4058           1 :   tor_snprintf(buf, sizeof(buf),
    4059             :                "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
    4060           1 :   tt_str_op(f,OP_EQ, buf);
    4061           1 :   tor_free(f);
    4062           1 :   f = get_datadir_fname_suffix("cache", ".foo");
    4063           1 :   tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
    4064             :                temp_dir);
    4065           1 :   tt_str_op(f,OP_EQ, buf);
    4066             : 
    4067           1 :  done:
    4068           1 :   tor_free(f);
    4069           1 :   tor_free(temp_dir);
    4070           1 : }
    4071             : 
    4072             : static void
    4073           1 : test_util_strtok(void *arg)
    4074             : {
    4075           1 :   char buf[128];
    4076           1 :   char buf2[128];
    4077           1 :   int i;
    4078           1 :   char *cp1, *cp2;
    4079             : 
    4080           1 :   (void)arg;
    4081           4 :   for (i = 0; i < 3; i++) {
    4082           3 :     const char *pad1="", *pad2="";
    4083           3 :     switch (i) {
    4084             :     case 0:
    4085             :       break;
    4086           1 :     case 1:
    4087           1 :       pad1 = " ";
    4088           1 :       pad2 = "!";
    4089           1 :       break;
    4090           1 :     case 2:
    4091           1 :       pad1 = "  ";
    4092           1 :       pad2 = ";!";
    4093           1 :       break;
    4094             :     }
    4095           3 :     tor_snprintf(buf, sizeof(buf), "%s", pad1);
    4096           3 :     tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
    4097           3 :     tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL);
    4098           3 :     tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL);
    4099             : 
    4100           3 :     tor_snprintf(buf, sizeof(buf),
    4101             :                  "%sGraved on the dark  in gestures of descent%s", pad1, pad1);
    4102           3 :     tor_snprintf(buf2, sizeof(buf2),
    4103             :                 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
    4104             :     /*  -- "Year's End", Richard Wilbur */
    4105             : 
    4106           3 :     tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
    4107           3 :     tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
    4108             : #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
    4109             : #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
    4110           3 :     tt_str_op("on",OP_EQ, S1());
    4111           3 :     tt_str_op("the",OP_EQ, S1());
    4112           3 :     tt_str_op("dark",OP_EQ, S1());
    4113           3 :     tt_str_op("seemed",OP_EQ, S2());
    4114           3 :     tt_str_op("their",OP_EQ, S2());
    4115           3 :     tt_str_op("own",OP_EQ, S2());
    4116           3 :     tt_str_op("in",OP_EQ, S1());
    4117           3 :     tt_str_op("gestures",OP_EQ, S1());
    4118           3 :     tt_str_op("of",OP_EQ, S1());
    4119           3 :     tt_str_op("most",OP_EQ, S2());
    4120           3 :     tt_str_op("perfect",OP_EQ, S2());
    4121           3 :     tt_str_op("descent",OP_EQ, S1());
    4122           3 :     tt_str_op("monument",OP_EQ, S2());
    4123           3 :     tt_ptr_op(NULL,OP_EQ, S1());
    4124           3 :     tt_ptr_op(NULL,OP_EQ, S2());
    4125             :   }
    4126             : 
    4127           1 :   buf[0] = 0;
    4128           1 :   tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
    4129           1 :   tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
    4130             : 
    4131           1 :   strlcpy(buf, "Howdy!", sizeof(buf));
    4132           1 :   tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
    4133           1 :   tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
    4134             : 
    4135           1 :   strlcpy(buf, " ", sizeof(buf));
    4136           1 :   tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
    4137           1 :   strlcpy(buf, "  ", sizeof(buf));
    4138           1 :   tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
    4139             : 
    4140           1 :   strlcpy(buf, "something  ", sizeof(buf));
    4141           1 :   tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
    4142           1 :   tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
    4143           1 :  done:
    4144           1 :   ;
    4145           1 : }
    4146             : 
    4147             : static void
    4148           1 : test_util_find_str_at_start_of_line(void *ptr)
    4149             : {
    4150           1 :   const char *long_string =
    4151             :     "howdy world. how are you? i hope it's fine.\n"
    4152             :     "hello kitty\n"
    4153             :     "third line";
    4154           1 :   char *line2 = strchr(long_string,'\n')+1;
    4155           1 :   char *line3 = strchr(line2,'\n')+1;
    4156           1 :   const char *short_string = "hello kitty\n"
    4157             :     "second line\n";
    4158           1 :   char *short_line2 = strchr(short_string,'\n')+1;
    4159             : 
    4160           1 :   (void)ptr;
    4161             : 
    4162           1 :   tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
    4163           1 :   tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
    4164           1 :   tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
    4165           1 :   tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
    4166           1 :   tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
    4167           1 :   tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
    4168           1 :   tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
    4169           1 :   tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
    4170           1 :   tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
    4171           1 :   tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
    4172           1 :   tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
    4173           1 :   tt_ptr_op(line2,OP_EQ,
    4174             :             find_str_at_start_of_line(long_string, "hello kitty\n"));
    4175           1 :   tt_ptr_op(line2,OP_EQ,
    4176             :             find_str_at_start_of_line(long_string, "hello kitty\nt"));
    4177           1 :   tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
    4178           1 :   tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
    4179           1 :   tt_ptr_op(NULL, OP_EQ,
    4180             :             find_str_at_start_of_line(long_string, "third line\n"));
    4181           1 :   tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
    4182             :                                                      "second line\n"));
    4183           1 :  done:
    4184           1 :   ;
    4185           1 : }
    4186             : 
    4187             : static void
    4188           1 : test_util_tor_strreplacechar(void *ptr)
    4189             : {
    4190           1 :   (void)ptr;
    4191           1 :   char empty[] = "";
    4192           1 :   char not_contain[] = "bbb";
    4193           1 :   char contains[] = "bab";
    4194           1 :   char contains_all[] = "aaa";
    4195             : 
    4196           1 :   tor_strreplacechar(empty, 'a', 'b');
    4197           1 :   tt_str_op(empty, OP_EQ, "");
    4198             : 
    4199           1 :   tor_strreplacechar(not_contain, 'a', 'b');
    4200           1 :   tt_str_op(not_contain, OP_EQ, "bbb");
    4201             : 
    4202           1 :   tor_strreplacechar(contains, 'a', 'b');
    4203           1 :   tt_str_op(contains, OP_EQ, "bbb");
    4204             : 
    4205           1 :   tor_strreplacechar(contains_all, 'a', 'b');
    4206           1 :   tt_str_op(contains_all, OP_EQ, "bbb");
    4207             : 
    4208           1 :  done:
    4209           1 :   ;
    4210           1 : }
    4211             : 
    4212             : static void
    4213           1 : test_util_string_is_C_identifier(void *ptr)
    4214             : {
    4215           1 :   (void)ptr;
    4216             : 
    4217           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("string_is_C_identifier"));
    4218           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("_string_is_C_identifier"));
    4219           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
    4220           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
    4221           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
    4222           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
    4223           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
    4224           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
    4225           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
    4226           1 :   tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
    4227             : 
    4228           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
    4229           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
    4230           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier(""));
    4231           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
    4232           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
    4233           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
    4234           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier("í"));
    4235           1 :   tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
    4236             : 
    4237           1 :  done:
    4238           1 :   ;
    4239           1 : }
    4240             : 
    4241             : static void
    4242           1 : test_util_string_is_utf8(void *ptr)
    4243             : {
    4244           1 :   (void)ptr;
    4245             : 
    4246           1 :   tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0));
    4247           1 :   tt_int_op(1, OP_EQ, string_is_utf8("", 1));
    4248           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3));
    4249           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3));
    4250           1 :   tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7));
    4251           1 :   tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9));
    4252             : 
    4253             :   /* Test the utf8_no_bom function */
    4254           1 :   tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFF", 3));
    4255           1 :   tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFFFE", 3));
    4256           1 :   tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFFlove", 7));
    4257           1 :   tt_int_op(1, OP_EQ, string_is_utf8_no_bom("loveandrespect",
    4258             :                                             strlen("loveandrespect")));
    4259             : 
    4260             :   // Validate exactly 'len' bytes.
    4261           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2));
    4262           1 :   tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6));
    4263             : 
    4264             :   // Reject sequences with missing bytes.
    4265           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1));
    4266           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1));
    4267           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2));
    4268           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2));
    4269           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3));
    4270           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3));
    4271           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4));
    4272             : 
    4273             :   // Reject encodings that are overly long.
    4274           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2));
    4275           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2));
    4276           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3));
    4277           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3));
    4278           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4));
    4279           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4));
    4280             : 
    4281             :   // Reject UTF-16 surrogate halves.
    4282           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3));
    4283           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3));
    4284           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
    4285           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
    4286             : 
    4287             :   // The minimum legal codepoint, 0x00.
    4288           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\0", 1));
    4289             : 
    4290             :   // The maximum legal codepoint, 0x10FFFF.
    4291           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
    4292           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
    4293             : 
    4294             :   /* Test cases that vary between programming languages /
    4295             :    * UTF-8 implementations.
    4296             :    * Source: POC||GTFO 19, page 43
    4297             :    * https://www.alchemistowl.org/pocorgtfo/
    4298             :    */
    4299             : 
    4300             :   // Invalid (in most implementations)
    4301             :   // surrogate
    4302           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x81", 3));
    4303             :   // nullsurrog
    4304           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\x30\x00\xed\xa0\x81", 5));
    4305             :   // threehigh
    4306           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
    4307             :   // fourhigh
    4308           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\xbf\xbf", 4));
    4309             :   // fivebyte
    4310           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xfb\x80\x80\x80\x80", 5));
    4311             :   // sixbyte
    4312           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xfd\x80\x80\x80\x80", 5));
    4313             :   // sixhigh
    4314           1 :   tt_int_op(0, OP_EQ, string_is_utf8("\xfd\xbf\xbf\xbf\xbf", 5));
    4315             : 
    4316             :   // Valid (in most implementations)
    4317             :   // fourbyte
    4318           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x8d\x88", 4));
    4319             :   // fourbyte2
    4320           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\xf0\xbf\xbf\xbf", 4));
    4321             :   // nullbyte
    4322           1 :   tt_int_op(1, OP_EQ, string_is_utf8("\x30\x31\x32\x00\x33", 5));
    4323             : 
    4324           1 :  done:
    4325           1 :   ;
    4326           1 : }
    4327             : 
    4328             : static void
    4329           1 : test_util_asprintf(void *ptr)
    4330             : {
    4331             : #define LOREMIPSUM                                              \
    4332             :   "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
    4333           1 :   char *cp=NULL, *cp2=NULL;
    4334           1 :   int r;
    4335           1 :   (void)ptr;
    4336             : 
    4337             :   /* simple string */
    4338           1 :   r = tor_asprintf(&cp, "simple string 100%% safe");
    4339           1 :   tt_assert(cp);
    4340           1 :   tt_str_op("simple string 100% safe",OP_EQ, cp);
    4341           1 :   tt_int_op(strlen(cp),OP_EQ, r);
    4342           1 :   tor_free(cp);
    4343             : 
    4344             :   /* empty string */
    4345           1 :   r = tor_asprintf(&cp, "%s", "");
    4346           1 :   tt_assert(cp);
    4347           1 :   tt_str_op("",OP_EQ, cp);
    4348           1 :   tt_int_op(strlen(cp),OP_EQ, r);
    4349           1 :   tor_free(cp);
    4350             : 
    4351             :   /* numbers (%i) */
    4352           1 :   r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
    4353           1 :   tt_assert(cp);
    4354           1 :   tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
    4355           1 :   tt_int_op(strlen(cp),OP_EQ, r);
    4356             :   /* don't free cp; next test uses it. */
    4357             : 
    4358             :   /* numbers (%d) */
    4359           1 :   r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
    4360           1 :   tt_assert(cp2);
    4361           1 :   tt_int_op(strlen(cp2),OP_EQ, r);
    4362           1 :   tt_str_op("First=101, Second=202",OP_EQ, cp2);
    4363           1 :   tt_assert(cp != cp2);
    4364           1 :   tor_free(cp);
    4365           1 :   tor_free(cp2);
    4366             : 
    4367             :   /* Glass-box test: a string exactly 128 characters long. */
    4368           1 :   r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
    4369           1 :   tt_assert(cp);
    4370           1 :   tt_int_op(128,OP_EQ, r);
    4371           1 :   tt_int_op(cp[128], OP_EQ, '\0');
    4372           1 :   tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
    4373           1 :   tor_free(cp);
    4374             : 
    4375             :   /* String longer than 128 characters */
    4376           1 :   r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
    4377             :                    LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
    4378           1 :   tt_assert(cp);
    4379           1 :   tt_int_op(strlen(cp),OP_EQ, r);
    4380           1 :   tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
    4381             : 
    4382           1 :  done:
    4383           1 :   tor_free(cp);
    4384           1 :   tor_free(cp2);
    4385           1 : }
    4386             : 
    4387             : static void
    4388           1 : test_util_listdir(void *ptr)
    4389             : {
    4390           1 :   smartlist_t *dir_contents = NULL;
    4391           1 :   char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
    4392           1 :   int r;
    4393           1 :   (void)ptr;
    4394             : 
    4395           1 :   fname1 = tor_strdup(get_fname("hopscotch"));
    4396           1 :   fname2 = tor_strdup(get_fname("mumblety-peg"));
    4397           1 :   fname3 = tor_strdup(get_fname(".hidden-file"));
    4398           1 :   dir1   = tor_strdup(get_fname("some-directory"));
    4399           1 :   dirname = tor_strdup(get_fname(NULL));
    4400             : 
    4401           1 :   tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
    4402           1 :   tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
    4403           1 :   tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
    4404             : #ifdef _WIN32
    4405             :   r = mkdir(dir1);
    4406             : #else
    4407           1 :   r = mkdir(dir1, 0700);
    4408             : #endif
    4409           1 :   if (r) {
    4410           0 :     fprintf(stderr, "Can't create directory %s:", dir1);
    4411           0 :     perror("");
    4412           0 :     exit(1);
    4413             :   }
    4414             : 
    4415           1 :   dir_contents = tor_listdir(dirname);
    4416           1 :   tt_assert(dir_contents);
    4417             :   /* make sure that each filename is listed. */
    4418           1 :   tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
    4419           1 :   tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
    4420           1 :   tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
    4421           1 :   tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
    4422             : 
    4423           1 :   tt_assert(!smartlist_contains_string(dir_contents, "."));
    4424           1 :   tt_assert(!smartlist_contains_string(dir_contents, ".."));
    4425             : 
    4426           1 :  done:
    4427           1 :   tor_free(fname1);
    4428           1 :   tor_free(fname2);
    4429           1 :   tor_free(fname3);
    4430           1 :   tor_free(dir1);
    4431           1 :   tor_free(dirname);
    4432           1 :   if (dir_contents) {
    4433           6 :     SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
    4434           1 :     smartlist_free(dir_contents);
    4435             :   }
    4436           1 : }
    4437             : 
    4438             : static void
    4439           1 : test_util_glob(void *ptr)
    4440             : {
    4441           1 :   (void)ptr;
    4442             : 
    4443             : #ifdef HAVE_GLOB
    4444           1 :   smartlist_t *results = NULL;
    4445           1 :   int r, i;
    4446           1 :   char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
    4447           1 :   char *expected = NULL, *pattern = NULL;
    4448             :   // used for cleanup
    4449           1 :   char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
    4450           1 :   char *forbidden_forbidden = NULL;
    4451             : 
    4452           1 :   dirname = tor_strdup(get_fname("test_glob"));
    4453           1 :   tt_ptr_op(dirname, OP_NE, NULL);
    4454             : 
    4455             : #ifdef _WIN32
    4456             :   r = mkdir(dirname);
    4457             : #else
    4458           1 :   r = mkdir(dirname, 0700);
    4459             : #endif
    4460           1 :   if (r) {
    4461           0 :     fprintf(stderr, "Can't create directory %s:", dirname);
    4462           0 :     perror("");
    4463           0 :     exit(1);
    4464             :   }
    4465             : 
    4466           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
    4467           1 :   tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
    4468           1 :   tor_asprintf(&dir1_forbidden,
    4469             :                "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
    4470           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
    4471           1 :   tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
    4472           1 :   tor_asprintf(&dir2_forbidden,
    4473             :                "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
    4474           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
    4475           1 :   tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
    4476           1 :   tor_asprintf(&forbidden_forbidden,
    4477             :                "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
    4478             : #ifndef _WIN32
    4479           1 :   tt_int_op(0, OP_EQ, chmod(forbidden, 0700));
    4480             : #endif
    4481           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
    4482             : #ifndef _WIN32
    4483           1 :   tt_int_op(0, OP_EQ, chmod(forbidden, 0));
    4484             : #endif
    4485             : 
    4486             : #define TEST(input) \
    4487             :   do { \
    4488             :     tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
    4489             :     results = tor_glob(pattern); \
    4490             :     tor_free(pattern); \
    4491             :     tt_assert(results); \
    4492             :     smartlist_sort_strings(results); \
    4493             :   } while (0);
    4494             : 
    4495             : #define EXPECT(result) \
    4496             :   do { \
    4497             :     tt_int_op(smartlist_len(results), OP_EQ, \
    4498             :                             sizeof(result)/sizeof(*result)); \
    4499             :     i = 0; \
    4500             :     SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
    4501             :       tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
    4502             :       tt_str_op(f, OP_EQ, expected); \
    4503             :       i++; \
    4504             :       tor_free(expected); \
    4505             :     } SMARTLIST_FOREACH_END(f); \
    4506             :     SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
    4507             :     smartlist_free(results); \
    4508             :   } while (0);
    4509             : 
    4510             : #define EXPECT_EMPTY() \
    4511             :   do { \
    4512             :     tt_int_op(smartlist_len(results), OP_EQ, 0); \
    4513             :     SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
    4514             :     smartlist_free(results); \
    4515             :   } while (0);
    4516             : 
    4517             :   // wildcards at beginning
    4518           1 :   const char *results_test1[] = {"dir2", "file2"};
    4519           1 :   TEST("*2");
    4520           5 :   EXPECT(results_test1);
    4521             : 
    4522             :   // wildcards at end
    4523           1 :   const char *results_test2[] = {"dir1", "dir2"};
    4524           1 :   TEST("d*");
    4525           5 :   EXPECT(results_test2);
    4526             : 
    4527             :   // wildcards at beginning and end
    4528             : #ifdef _WIN32
    4529             :   // dot files are not ignored on Windows
    4530             :   const char *results_test3[] = {".test-hidden", "dir1", "dir2", "file1",
    4531             :                                  "file2", "forbidden"};
    4532             : #else
    4533           1 :   const char *results_test3[] = {"dir1", "dir2", "file1", "file2",
    4534             :                                  "forbidden"};
    4535             : #endif /* defined(_WIN32) */
    4536           1 :   TEST("*i*");
    4537          11 :   EXPECT(results_test3);
    4538             : 
    4539             :   // wildcards in middle
    4540           1 :   const char *results_test4[] = {"dir1", "dir2"};
    4541           1 :   TEST("d?r*");
    4542           5 :   EXPECT(results_test4);
    4543             : 
    4544             :   // test file that does not exist
    4545           1 :   TEST("not-exist");
    4546           1 :   EXPECT_EMPTY();
    4547             : 
    4548             :   // test wildcard that matches nothing
    4549           1 :   TEST("*not-exist*");
    4550           1 :   EXPECT_EMPTY();
    4551             : 
    4552             :   // test path separator at end - no wildcards
    4553           1 :   const char *results_test7[] = {"dir1"};
    4554           1 :   TEST("dir1");
    4555           3 :   EXPECT(results_test7);
    4556             : 
    4557           1 :   const char *results_test8[] = {"dir1"};
    4558           1 :   TEST("dir1"PATH_SEPARATOR);
    4559           3 :   EXPECT(results_test8);
    4560             : 
    4561           1 :   const char *results_test9[] = {"file1"};
    4562           1 :   TEST("file1");
    4563           3 :   EXPECT(results_test9);
    4564             : 
    4565           1 :   TEST("file1"PATH_SEPARATOR);
    4566           1 :   EXPECT_EMPTY();
    4567             : 
    4568             :   // test path separator at end - with wildcards and linux path separator
    4569           1 :   const char *results_test11[] = {"dir1", "dir2", "forbidden"};
    4570           1 :   TEST("*/");
    4571           7 :   EXPECT(results_test11);
    4572             : 
    4573             : #ifdef _WIN32
    4574             :   // dot files are not ignored on Windows
    4575             :   const char *results_test12[] = {".test-hidden", "dir1", "dir2", "empty",
    4576             :                                   "file1", "file2", "forbidden"};
    4577             : #else
    4578           1 :   const char *results_test12[] = {"dir1", "dir2", "empty", "file1", "file2",
    4579             :                                   "forbidden"};
    4580             : #endif /* defined(_WIN32) */
    4581           1 :   TEST("*");
    4582          13 :   EXPECT(results_test12);
    4583             : 
    4584             :   // wildcards on folder and file and linux path separator
    4585           1 :   const char *results_test13[] = {"dir1"PATH_SEPARATOR"dir1",
    4586             :                                   "dir1"PATH_SEPARATOR"dir2",
    4587             :                                   "dir1"PATH_SEPARATOR"file1",
    4588             :                                   "dir1"PATH_SEPARATOR"file2",
    4589             :                                   "dir2"PATH_SEPARATOR"dir1",
    4590             :                                   "dir2"PATH_SEPARATOR"dir2",
    4591             :                                   "dir2"PATH_SEPARATOR"file1",
    4592             :                                   "dir2"PATH_SEPARATOR"file2"};
    4593           1 :   TEST("?i*/?i*");
    4594          17 :   EXPECT(results_test13);
    4595             : 
    4596             :   // wildcards on file only
    4597           1 :   const char *results_test14[] = {"dir1"PATH_SEPARATOR"dir1",
    4598             :                                   "dir1"PATH_SEPARATOR"dir2",
    4599             :                                   "dir1"PATH_SEPARATOR"file1",
    4600             :                                   "dir1"PATH_SEPARATOR"file2"};
    4601           1 :   TEST("dir1"PATH_SEPARATOR"?i*");
    4602           9 :   EXPECT(results_test14);
    4603             : 
    4604             :   // wildcards on folder only
    4605           1 :   const char *results_test15[] = {"dir1"PATH_SEPARATOR"file1",
    4606             :                                   "dir2"PATH_SEPARATOR"file1"};
    4607           1 :   TEST("?i*"PATH_SEPARATOR"file1");
    4608           5 :   EXPECT(results_test15);
    4609             : 
    4610             :   // wildcards after file name
    4611           1 :   TEST("file1"PATH_SEPARATOR"*");
    4612           1 :   EXPECT_EMPTY();
    4613             : 
    4614             : #ifndef _WIN32
    4615             :   // test wildcard escaping
    4616           1 :   TEST("\\*");
    4617           1 :   EXPECT_EMPTY();
    4618             : 
    4619           1 :   if (getuid() != 0) {
    4620             :     // test forbidden directory, if we're not root.
    4621             :     // (Root will be able to see this directory anyway.)
    4622           1 :     tor_asprintf(&pattern, "%s"PATH_SEPARATOR"*"PATH_SEPARATOR"*", dirname);
    4623           1 :     results = tor_glob(pattern);
    4624           1 :     tor_free(pattern);
    4625           1 :     tt_assert(!results);
    4626             :   }
    4627             : #endif /* !defined(_WIN32) */
    4628             : 
    4629             : #undef TEST
    4630             : #undef EXPECT
    4631             : #undef EXPECT_EMPTY
    4632             : 
    4633           1 :  done:
    4634             : #ifndef _WIN32
    4635           1 :   (void) chmod(forbidden, 0700);
    4636           1 :   (void) chmod(dir1_forbidden, 0700);
    4637           1 :   (void) chmod(dir2_forbidden, 0700);
    4638           1 :   (void) chmod(forbidden_forbidden, 0700);
    4639             : #endif /* !defined(_WIN32) */
    4640           1 :   tor_free(dir1);
    4641           1 :   tor_free(dir2);
    4642           1 :   tor_free(forbidden);
    4643           1 :   tor_free(dirname);
    4644           1 :   tor_free(dir1_forbidden);
    4645           1 :   tor_free(dir2_forbidden);
    4646           1 :   tor_free(forbidden_forbidden);
    4647           1 :   tor_free(expected);
    4648           1 :   tor_free(pattern);
    4649           1 :   if (results) {
    4650           0 :     SMARTLIST_FOREACH(results, char *, f, tor_free(f));
    4651           0 :     smartlist_free(results);
    4652             :   }
    4653             : #else /* !defined(HAVE_GLOB) */
    4654             :   tt_skip();
    4655             :  done:
    4656             :   return;
    4657             : #endif /* defined(HAVE_GLOB) */
    4658           1 : }
    4659             : 
    4660             : static void
    4661           1 : test_util_get_glob_opened_files(void *ptr)
    4662             : {
    4663           1 :   (void)ptr;
    4664             : 
    4665             : #ifdef HAVE_GLOB
    4666           1 :   smartlist_t *results = NULL;
    4667           1 :   int r, i;
    4668           1 :   char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
    4669           1 :   char *expected = NULL, *pattern = NULL;
    4670             :   // used for cleanup
    4671           1 :   char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
    4672           1 :   char *forbidden_forbidden = NULL;
    4673             : 
    4674           1 :   dirname = tor_strdup(get_fname("test_get_glob_opened_files"));
    4675           1 :   tt_ptr_op(dirname, OP_NE, NULL);
    4676             : 
    4677             : #ifdef _WIN32
    4678             :   r = mkdir(dirname);
    4679             : #else
    4680           1 :   r = mkdir(dirname, 0700);
    4681             : #endif
    4682           1 :   if (r) {
    4683           0 :     fprintf(stderr, "Can't create directory %s:", dirname);
    4684           0 :     perror("");
    4685           0 :     exit(1);
    4686             :   }
    4687             : 
    4688           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
    4689           1 :   tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
    4690           1 :   tor_asprintf(&dir1_forbidden,
    4691             :                "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
    4692           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
    4693           1 :   tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
    4694           1 :   tor_asprintf(&dir2_forbidden,
    4695             :                "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
    4696           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
    4697           1 :   tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
    4698           1 :   tor_asprintf(&forbidden_forbidden,
    4699             :                "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
    4700             : #ifndef _WIN32
    4701           1 :   chmod(forbidden, 0700);
    4702             : #endif
    4703           1 :   tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
    4704             : #ifndef _WIN32
    4705           1 :   chmod(forbidden, 0);
    4706             : #endif
    4707             : 
    4708             : #define TEST(input) \
    4709             :   do { \
    4710             :     if (*input) { \
    4711             :       tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
    4712             :     } else { /* do not add path separator if empty string */ \
    4713             :       tor_asprintf(&pattern, "%s", dirname); \
    4714             :     } \
    4715             :     results = get_glob_opened_files(pattern); \
    4716             :     tor_free(pattern); \
    4717             :     tt_assert(results); \
    4718             :     smartlist_sort_strings(results); \
    4719             :   } while (0);
    4720             : 
    4721             : #define EXPECT(result) \
    4722             :   do { \
    4723             :     tt_int_op(smartlist_len(results), OP_EQ, \
    4724             :                           sizeof(result)/sizeof(*result)); \
    4725             :     i = 0; \
    4726             :     SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
    4727             :       if (*result[i]) { \
    4728             :         tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
    4729             :       } else { /* do not add path separator if empty string */ \
    4730             :         tor_asprintf(&expected, "%s", dirname); \
    4731             :       } \
    4732             :       tt_str_op(f, OP_EQ, expected); \
    4733             :       i++; \
    4734             :       tor_free(expected); \
    4735             :     } SMARTLIST_FOREACH_END(f); \
    4736             :     SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
    4737             :     smartlist_free(results); \
    4738             :   } while (0);
    4739             : 
    4740             : #define EXPECT_EMPTY() \
    4741             :   do { \
    4742             :     tt_int_op(smartlist_len(results), OP_EQ, 0); \
    4743             :     SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
    4744             :     smartlist_free(results); \
    4745             :   } while (0);
    4746             : 
    4747             :   // all files on folder
    4748           1 :   const char *results_test1[] = {""}; // only the folder is read
    4749           1 :   TEST("*");
    4750           3 :   EXPECT(results_test1);
    4751             : 
    4752             :   // same as before but ending in path separator
    4753           1 :   const char *results_test2[] = {""}; // only the folder is read
    4754           1 :   TEST("*"PATH_SEPARATOR);
    4755           3 :   EXPECT(results_test2);
    4756             : 
    4757             :   // wildcards in multiple path components
    4758             : #ifndef _WIN32
    4759           1 :   const char *results_test3[] = {"", "dir1", "dir2", "empty", "file1", "file2",
    4760             :                                  "forbidden"};
    4761             : #else
    4762             :   // dot files are not special on windows
    4763             :   const char *results_test3[] = {"", ".test-hidden", "dir1", "dir2", "empty",
    4764             :                                  "file1", "file2", "forbidden"};
    4765             : #endif /* !defined(_WIN32) */
    4766           1 :   TEST("*"PATH_SEPARATOR"*");
    4767          15 :   EXPECT(results_test3);
    4768             : 
    4769             :   // same as before but ending in path separator
    4770             : #ifndef _WIN32
    4771           1 :   const char *results_test4[] = {"", "dir1", "dir2", "empty", "file1", "file2",
    4772             :                                  "forbidden"};
    4773             : #else
    4774             :   // dot files are not special on windows
    4775             :   const char *results_test4[] = {"", ".test-hidden", "dir1", "dir2", "empty",
    4776             :                                  "file1", "file2", "forbidden"};
    4777             : #endif /* !defined(_WIN32) */
    4778           1 :   TEST("*"PATH_SEPARATOR"*"PATH_SEPARATOR);
    4779          15 :   EXPECT(results_test4);
    4780             : 
    4781             :   // no glob - folder
    4782           1 :   TEST("");
    4783           1 :   EXPECT_EMPTY();
    4784             : 
    4785             :   // same as before but ending in path separator
    4786           1 :   TEST(PATH_SEPARATOR);
    4787           1 :   EXPECT_EMPTY();
    4788             : 
    4789             :   // no glob - file
    4790           1 :   TEST("file1");
    4791           1 :   EXPECT_EMPTY();
    4792             : 
    4793             :   // same as before but ending in path separator and linux path separator
    4794           1 :   TEST("file1/");
    4795           1 :   EXPECT_EMPTY();
    4796             : 
    4797             :   // file but with wildcard after
    4798           1 :   const char *results_test9[] = {"file1"};
    4799           1 :   TEST("file1"PATH_SEPARATOR"*");
    4800           3 :   EXPECT(results_test9);
    4801             : 
    4802             :   // dir inside dir and linux path separator
    4803           1 :   TEST("dir1/dir1");
    4804           1 :   EXPECT_EMPTY();
    4805             : 
    4806             :   // same as before but ending in path separator
    4807           1 :   TEST("dir1"PATH_SEPARATOR"dir1"PATH_SEPARATOR);
    4808           1 :   EXPECT_EMPTY();
    4809             : 
    4810             :   // no glob - empty
    4811           1 :   TEST("empty");
    4812           1 :   EXPECT_EMPTY();
    4813             : 
    4814             :   // same as before but ending in path separator
    4815           1 :   TEST("empty"PATH_SEPARATOR);
    4816           1 :   EXPECT_EMPTY();
    4817             : 
    4818             :   // no glob - does not exist
    4819           1 :   TEST("not_exist");
    4820           1 :   EXPECT_EMPTY();
    4821             : 
    4822             : #undef TEST
    4823             : #undef EXPECT
    4824             : #undef EXPECT_EMPTY
    4825             : 
    4826           1 :  done:
    4827             : #ifndef _WIN32
    4828             :   {
    4829           1 :     int chmod_failed = 0;
    4830           1 :     if (forbidden)
    4831           1 :     chmod_failed |= chmod(forbidden, 0700);
    4832           1 :     if (dir1_forbidden)
    4833           1 :       chmod_failed |= chmod(dir1_forbidden, 0700);
    4834           1 :     if (dir2_forbidden)
    4835           1 :       chmod_failed |= chmod(dir2_forbidden, 0700);
    4836           1 :     if (forbidden_forbidden)
    4837           1 :       chmod_failed |= chmod(forbidden_forbidden, 0700);
    4838           1 :     if (chmod_failed) {
    4839           0 :       TT_FAIL(("unable to chmod a file on cleanup: %s", strerror(errno)));
    4840             :     }
    4841             :   }
    4842             : #endif /* !defined(_WIN32) */
    4843           1 :   tor_free(dir1);
    4844           1 :   tor_free(dir2);
    4845           1 :   tor_free(forbidden);
    4846           1 :   tor_free(dirname);
    4847           1 :   tor_free(dir1_forbidden);
    4848           1 :   tor_free(dir2_forbidden);
    4849           1 :   tor_free(forbidden_forbidden);
    4850           1 :   tor_free(expected);
    4851           1 :   tor_free(pattern);
    4852           1 :   if (results) {
    4853           0 :     SMARTLIST_FOREACH(results, char *, f, tor_free(f));
    4854           0 :     smartlist_free(results);
    4855             :   }
    4856             : #else /* !defined(HAVE_GLOB) */
    4857             :   tt_skip();
    4858             :  done:
    4859             :   return;
    4860             : #endif /* defined(HAVE_GLOB) */
    4861           1 : }
    4862             : 
    4863             : static void
    4864           1 : test_util_parent_dir(void *ptr)
    4865             : {
    4866           1 :   char *cp;
    4867           1 :   (void)ptr;
    4868             : 
    4869             : #define T(output,expect_ok,input)               \
    4870             :   do {                                          \
    4871             :     int ok;                                     \
    4872             :     cp = tor_strdup(input);                     \
    4873             :     ok = get_parent_directory(cp);              \
    4874             :     tt_int_op(expect_ok, OP_EQ, ok);               \
    4875             :     if (ok==0)                                  \
    4876             :       tt_str_op(output, OP_EQ, cp);                \
    4877             :     tor_free(cp);                               \
    4878             :   } while (0);
    4879             : 
    4880           1 :   T("/home/wombat", 0, "/home/wombat/knish");
    4881           1 :   T("/home/wombat", 0, "/home/wombat/knish/");
    4882           1 :   T("/home/wombat", 0, "/home/wombat/knish///");
    4883           1 :   T("./home/wombat", 0, "./home/wombat/knish/");
    4884           1 :   T("/", 0, "/home");
    4885           1 :   T("/", 0, "/home//");
    4886           1 :   T(".", 0, "./wombat");
    4887           1 :   T(".", 0, "./wombat/");
    4888           1 :   T(".", 0, "./wombat//");
    4889           1 :   T("wombat", 0, "wombat/foo");
    4890           1 :   T("wombat/..", 0, "wombat/../foo");
    4891           1 :   T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
    4892           1 :   T("wombat/.", 0, "wombat/./foo");
    4893           1 :   T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
    4894           1 :   T("wombat", 0, "wombat/..//");
    4895           1 :   T("wombat", 0, "wombat/foo/");
    4896           1 :   T("wombat", 0, "wombat/.foo");
    4897           1 :   T("wombat", 0, "wombat/.foo/");
    4898             : 
    4899           1 :   T("wombat", -1, "");
    4900           1 :   T("w", -1, "");
    4901           1 :   T("wombat", 0, "wombat/knish");
    4902             : 
    4903           1 :   T("/", 0, "/");
    4904           1 :   T("/", 0, "////");
    4905             : 
    4906           1 :  done:
    4907           1 :   tor_free(cp);
    4908           1 : }
    4909             : 
    4910             : static void
    4911           1 : test_util_ftruncate(void *ptr)
    4912             : {
    4913           1 :   char *buf = NULL;
    4914           1 :   const char *fname;
    4915           1 :   int fd = -1;
    4916           1 :   const char *message = "Hello world";
    4917           1 :   const char *message2 = "Hola mundo";
    4918           1 :   struct stat st;
    4919             : 
    4920           1 :   (void) ptr;
    4921             : 
    4922           1 :   fname = get_fname("ftruncate");
    4923             : 
    4924           1 :   fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
    4925           1 :   tt_int_op(fd, OP_GE, 0);
    4926             : 
    4927             :   /* Make the file be there. */
    4928           1 :   tt_int_op(strlen(message), OP_EQ,
    4929             :             write_all_to_fd(fd, message, strlen(message)));
    4930           1 :   tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
    4931           1 :   tt_int_op(0, OP_EQ, fstat(fd, &st));
    4932           1 :   tt_int_op((int)st.st_size, OP_EQ, strlen(message));
    4933             : 
    4934             :   /* Truncate and see if it got truncated */
    4935           1 :   tt_int_op(0, OP_EQ, tor_ftruncate(fd));
    4936           1 :   tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
    4937           1 :   tt_int_op(0, OP_EQ, fstat(fd, &st));
    4938           1 :   tt_int_op((int)st.st_size, OP_EQ, 0);
    4939             : 
    4940             :   /* Replace, and see if it got replaced */
    4941           1 :   tt_int_op(strlen(message2), OP_EQ,
    4942             :             write_all_to_fd(fd, message2, strlen(message2)));
    4943           1 :   tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
    4944           1 :   tt_int_op(0, OP_EQ, fstat(fd, &st));
    4945           1 :   tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
    4946             : 
    4947           1 :   close(fd);
    4948           1 :   fd = -1;
    4949             : 
    4950           1 :   buf = read_file_to_str(fname, 0, NULL);
    4951           1 :   tt_str_op(message2, OP_EQ, buf);
    4952             : 
    4953           1 :  done:
    4954           0 :   if (fd >= 0)
    4955           0 :     close(fd);
    4956           1 :   tor_free(buf);
    4957           1 : }
    4958             : 
    4959             : static void
    4960           1 : test_util_num_cpus(void *arg)
    4961             : {
    4962           1 :   (void)arg;
    4963           1 :   int num = compute_num_cpus();
    4964           1 :   if (num < 0)
    4965           0 :     tt_skip();
    4966             : 
    4967           1 :   tt_int_op(num, OP_GE, 1);
    4968           1 :   tt_int_op(num, OP_LE, 16);
    4969             : 
    4970           1 :  done:
    4971           1 :   ;
    4972           1 : }
    4973             : 
    4974             : #ifdef _WIN32
    4975             : static void
    4976             : test_util_load_win_lib(void *ptr)
    4977             : {
    4978             :   HANDLE h = load_windows_system_library(_T("advapi32.dll"));
    4979             :   (void) ptr;
    4980             : 
    4981             :   tt_assert(h);
    4982             :  done:
    4983             :   if (h)
    4984             :     FreeLibrary(h);
    4985             : }
    4986             : #endif /* defined(_WIN32) */
    4987             : 
    4988             : /**
    4989             :  * Test for format_hex_number_sigsafe()
    4990             :  */
    4991             : 
    4992             : static void
    4993           1 : test_util_format_hex_number(void *ptr)
    4994             : {
    4995           1 :   int i, len;
    4996           1 :   char buf[33];
    4997           1 :   const struct {
    4998             :     const char *str;
    4999             :     unsigned int x;
    5000           1 :   } test_data[] = {
    5001             :     {"0", 0},
    5002             :     {"1", 1},
    5003             :     {"273A", 0x273a},
    5004             :     {"FFFF", 0xffff},
    5005             :     {"7FFFFFFF", 0x7fffffff},
    5006             :     {"FFFFFFFF", 0xffffffff},
    5007             : #if UINT_MAX >= 0xffffffff
    5008             :     {"31BC421D", 0x31bc421d},
    5009             :     {"FFFFFFFF", 0xffffffff},
    5010             : #endif
    5011             :     {NULL, 0}
    5012             :   };
    5013             : 
    5014           1 :   (void)ptr;
    5015             : 
    5016           9 :   for (i = 0; test_data[i].str != NULL; ++i) {
    5017           8 :     len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
    5018           8 :     tt_int_op(len,OP_NE, 0);
    5019           8 :     tt_int_op(len,OP_EQ, strlen(buf));
    5020           8 :     tt_str_op(buf,OP_EQ, test_data[i].str);
    5021             :   }
    5022             : 
    5023           1 :   tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
    5024           1 :   tt_str_op(buf,OP_EQ, "FFFF");
    5025           1 :   tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
    5026           1 :   tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
    5027             : 
    5028           1 :  done:
    5029           1 :   return;
    5030             : }
    5031             : 
    5032             : /**
    5033             :  * Test for format_hex_number_sigsafe()
    5034             :  */
    5035             : 
    5036             : static void
    5037           1 : test_util_format_dec_number(void *ptr)
    5038             : {
    5039           1 :   int i, len;
    5040           1 :   char buf[33];
    5041           1 :   const struct {
    5042             :     const char *str;
    5043             :     unsigned int x;
    5044           1 :   } test_data[] = {
    5045             :     {"0", 0},
    5046             :     {"1", 1},
    5047             :     {"1234", 1234},
    5048             :     {"12345678", 12345678},
    5049             :     {"99999999",  99999999},
    5050             :     {"100000000", 100000000},
    5051             :     {"4294967295", 4294967295u},
    5052             : #if UINT_MAX > 0xffffffff
    5053             :     {"18446744073709551615", 18446744073709551615u },
    5054             : #endif
    5055             :     {NULL, 0}
    5056             :   };
    5057             : 
    5058           1 :   (void)ptr;
    5059             : 
    5060           8 :   for (i = 0; test_data[i].str != NULL; ++i) {
    5061           7 :     len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
    5062           7 :     tt_int_op(len,OP_NE, 0);
    5063           7 :     tt_int_op(len,OP_EQ, strlen(buf));
    5064           7 :     tt_str_op(buf,OP_EQ, test_data[i].str);
    5065             : 
    5066          14 :     len = format_dec_number_sigsafe(test_data[i].x, buf,
    5067           7 :                                     (int)(strlen(test_data[i].str) + 1));
    5068           7 :     tt_int_op(len,OP_EQ, strlen(buf));
    5069           7 :     tt_str_op(buf,OP_EQ, test_data[i].str);
    5070             :   }
    5071             : 
    5072           1 :   tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
    5073           1 :   tt_str_op(buf,OP_EQ, "7331");
    5074           1 :   tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
    5075           1 :   tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
    5076           1 :   tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
    5077             : 
    5078           1 :  done:
    5079           1 :   return;
    5080             : }
    5081             : 
    5082             : #define MAX_SPLIT_LINE_COUNT 4
    5083             : struct split_lines_test_t {
    5084             :   const char *orig_line; // Line to be split (may contain \0's)
    5085             :   int orig_length; // Length of orig_line
    5086             :   const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
    5087             : };
    5088             : 
    5089             : static void
    5090           1 : test_util_di_ops(void *arg)
    5091             : {
    5092             : #define LT -1
    5093             : #define GT 1
    5094             : #define EQ 0
    5095           1 :   const struct {
    5096             :     const char *a; int want_sign; const char *b;
    5097           1 :   } examples[] = {
    5098             :     { "Foo", EQ, "Foo" },
    5099             :     { "foo", GT, "bar", },
    5100             :     { "foobar", EQ ,"foobar" },
    5101             :     { "foobar", LT, "foobaw" },
    5102             :     { "foobar", GT, "f00bar" },
    5103             :     { "foobar", GT, "boobar" },
    5104             :     { "", EQ, "" },
    5105             :     { NULL, 0, NULL },
    5106             :   };
    5107             : 
    5108           1 :   int i;
    5109             : 
    5110           1 :   (void)arg;
    5111           8 :   for (i = 0; examples[i].a; ++i) {
    5112           7 :     size_t len = strlen(examples[i].a);
    5113           7 :     int eq1, eq2, neq1, neq2, cmp1, cmp2;
    5114           7 :     tt_int_op(len,OP_EQ, strlen(examples[i].b));
    5115             :     /* We do all of the operations, with operands in both orders. */
    5116           7 :     eq1 = tor_memeq(examples[i].a, examples[i].b, len);
    5117           7 :     eq2 = tor_memeq(examples[i].b, examples[i].a, len);
    5118           7 :     neq1 = tor_memneq(examples[i].a, examples[i].b, len);
    5119           7 :     neq2 = tor_memneq(examples[i].b, examples[i].a, len);
    5120           7 :     cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
    5121           7 :     cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
    5122             : 
    5123             :     /* Check for correctness of cmp1 */
    5124           7 :     if (cmp1 < 0 && examples[i].want_sign != LT)
    5125           0 :       TT_DIE(("Assertion failed."));
    5126           7 :     else if (cmp1 > 0 && examples[i].want_sign != GT)
    5127           0 :       TT_DIE(("Assertion failed."));
    5128           7 :     else if (cmp1 == 0 && examples[i].want_sign != EQ)
    5129           0 :       TT_DIE(("Assertion failed."));
    5130             : 
    5131             :     /* Check for consistency of everything else with cmp1 */
    5132           7 :     tt_int_op(eq1,OP_EQ, eq2);
    5133           7 :     tt_int_op(neq1,OP_EQ, neq2);
    5134           7 :     tt_int_op(cmp1,OP_EQ, -cmp2);
    5135           7 :     tt_int_op(eq1,OP_EQ, cmp1 == 0);
    5136           7 :     tt_int_op(neq1,OP_EQ, !eq1);
    5137             :   }
    5138             : 
    5139             :   {
    5140           1 :     uint8_t zz = 0;
    5141           1 :     uint8_t ii = 0;
    5142           1 :     int z;
    5143             : 
    5144             :     /* exhaustively test tor_memeq and tor_memcmp
    5145             :      * against each possible single-byte numeric difference
    5146             :      * some arithmetic bugs only appear with certain bit patterns */
    5147         257 :     for (z = 0; z < 256; z++) {
    5148       65792 :       for (i = 0; i < 256; i++) {
    5149       65536 :         ii = (uint8_t)i;
    5150       65536 :         zz = (uint8_t)z;
    5151       65536 :         tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
    5152       65536 :         tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
    5153             :                   zz > ii ? GT : EQ);
    5154      131328 :         tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
    5155             :                   ii < zz ? LT : EQ);
    5156             :       }
    5157             :     }
    5158             :   }
    5159             : 
    5160           1 :   tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
    5161           1 :   tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
    5162           1 :   tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
    5163           1 :   tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
    5164           1 :   tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
    5165           1 :   tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
    5166           1 :   tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
    5167           1 :   tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
    5168           1 :   tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
    5169             : 
    5170           1 :  done:
    5171           1 :   ;
    5172           1 : }
    5173             : 
    5174             : static void
    5175           1 : test_util_memcpy_iftrue_timei(void *arg)
    5176             : {
    5177           1 :   (void)arg;
    5178           1 :   char buf1[25];
    5179           1 :   char buf2[25];
    5180           1 :   char buf3[25];
    5181             : 
    5182         101 :   for (int i = 0; i < 100; ++i) {
    5183         100 :     crypto_rand(buf1, sizeof(buf1));
    5184         100 :     crypto_rand(buf2, sizeof(buf2));
    5185         100 :     memcpy(buf3, buf1, sizeof(buf1));
    5186             : 
    5187             :     /* We just copied buf1 into buf3.  Now we're going to copy buf2 into buf2,
    5188             :        iff our coin flip comes up heads. */
    5189         100 :     bool coinflip = crypto_rand_int(2) == 0;
    5190             : 
    5191         100 :     memcpy_if_true_timei(coinflip, buf3, buf2, sizeof(buf3));
    5192             : 
    5193         100 :     if (coinflip) {
    5194          49 :       tt_mem_op(buf3, OP_EQ, buf2, sizeof(buf2));
    5195             :     } else {
    5196         100 :       tt_mem_op(buf3, OP_EQ, buf1, sizeof(buf1));
    5197             :     }
    5198             :   }
    5199           1 :  done:
    5200           1 :   ;
    5201           1 : }
    5202             : 
    5203             : static void
    5204           1 : test_util_di_map(void *arg)
    5205             : {
    5206           1 :   (void)arg;
    5207           1 :   di_digest256_map_t *dimap = NULL;
    5208           1 :   uint8_t key1[] = "Robert Anton Wilson            ";
    5209           1 :   uint8_t key2[] = "Martin Gardner, _Fads&fallacies";
    5210           1 :   uint8_t key3[] = "Tom Lehrer, _Be Prepared_.     ";
    5211           1 :   uint8_t key4[] = "Ursula Le Guin,_A Wizard of... ";
    5212             : 
    5213           1 :   char dflt_entry[] = "'You have made a good beginning', but no more";
    5214             : 
    5215           1 :   tt_int_op(32, OP_EQ, sizeof(key1));
    5216           1 :   tt_int_op(32, OP_EQ, sizeof(key2));
    5217           1 :   tt_int_op(32, OP_EQ, sizeof(key3));
    5218             : 
    5219           1 :   tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry));
    5220             : 
    5221           1 :   char *str1 = tor_strdup("You are precisely as big as what you love"
    5222             :                           " and precisely as small as what you allow"
    5223             :                           " to annoy you.");
    5224           1 :   char *str2 = tor_strdup("Let us hope that Lysenko's success in Russia will"
    5225             :                           " serve for many generations to come as another"
    5226             :                           " reminder to the world of how quickly and easily"
    5227             :                           " a science can be corrupted when ignorant"
    5228             :                           " political leaders deem themselves competent"
    5229             :                           " to arbitrate scientific disputes");
    5230           1 :   char *str3 = tor_strdup("Don't write naughty words on walls "
    5231             :                           "if you can't spell.");
    5232             : 
    5233           1 :   dimap_add_entry(&dimap, key1, str1);
    5234           1 :   dimap_add_entry(&dimap, key2, str2);
    5235           1 :   dimap_add_entry(&dimap, key3, str3);
    5236             : 
    5237           1 :   tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry));
    5238           1 :   tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry));
    5239           1 :   tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry));
    5240           1 :   tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry));
    5241             : 
    5242           1 :  done:
    5243           1 :   dimap_free(dimap, tor_free_);
    5244           1 : }
    5245             : 
    5246             : /**
    5247             :  * Test counting high bits
    5248             :  */
    5249             : static void
    5250           1 : test_util_n_bits_set(void *ptr)
    5251             : {
    5252           1 :   (void)ptr;
    5253           1 :   tt_int_op(0,OP_EQ, n_bits_set_u8(0));
    5254           1 :   tt_int_op(1,OP_EQ, n_bits_set_u8(1));
    5255           1 :   tt_int_op(3,OP_EQ, n_bits_set_u8(7));
    5256           1 :   tt_int_op(1,OP_EQ, n_bits_set_u8(8));
    5257           1 :   tt_int_op(2,OP_EQ, n_bits_set_u8(129));
    5258           1 :   tt_int_op(8,OP_EQ, n_bits_set_u8(255));
    5259           1 :  done:
    5260           1 :   ;
    5261           1 : }
    5262             : 
    5263             : /**
    5264             :  * Test LHS whitespace (and comment) eater
    5265             :  */
    5266             : static void
    5267           1 : test_util_eat_whitespace(void *ptr)
    5268             : {
    5269           1 :   const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
    5270           1 :   char str[80];
    5271           1 :   size_t i;
    5272             : 
    5273           1 :   (void)ptr;
    5274             : 
    5275             :   /* Try one leading ws */
    5276           1 :   strlcpy(str, "fuubaar", sizeof(str));
    5277           5 :   for (i = 0; i < sizeof(ws); ++i) {
    5278           3 :     str[0] = ws[i];
    5279           3 :     tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
    5280           3 :     tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
    5281           3 :     tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
    5282           3 :     tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5283             :   }
    5284           1 :   str[0] = '\n';
    5285           1 :   tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
    5286           1 :   tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
    5287           1 :   tt_ptr_op(str,OP_EQ,     eat_whitespace_no_nl(str));
    5288           1 :   tt_ptr_op(str,OP_EQ,     eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5289             : 
    5290             :   /* Empty string */
    5291           1 :   strlcpy(str, "", sizeof(str));
    5292           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace(str));
    5293           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
    5294           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
    5295           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
    5296             : 
    5297             :   /* Only ws */
    5298           1 :   strlcpy(str, " \t\r\n", sizeof(str));
    5299           1 :   tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
    5300           1 :   tt_ptr_op(str + strlen(str),OP_EQ,
    5301             :             eat_whitespace_eos(str, str + strlen(str)));
    5302           1 :   tt_ptr_op(str + strlen(str) - 1,OP_EQ,
    5303             :               eat_whitespace_no_nl(str));
    5304           1 :   tt_ptr_op(str + strlen(str) - 1,OP_EQ,
    5305             :               eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5306             : 
    5307           1 :   strlcpy(str, " \t\r ", sizeof(str));
    5308           1 :   tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
    5309           1 :   tt_ptr_op(str + strlen(str),OP_EQ,
    5310             :               eat_whitespace_eos(str, str + strlen(str)));
    5311           1 :   tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
    5312           1 :   tt_ptr_op(str + strlen(str),OP_EQ,
    5313             :               eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5314             : 
    5315             :   /* Multiple ws */
    5316           1 :   strlcpy(str, "fuubaar", sizeof(str));
    5317           5 :   for (i = 0; i < sizeof(ws); ++i)
    5318           3 :     str[i] = ws[i];
    5319           1 :   tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
    5320           1 :   tt_ptr_op(str + sizeof(ws),OP_EQ,
    5321             :             eat_whitespace_eos(str, str + strlen(str)));
    5322           1 :   tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
    5323           1 :   tt_ptr_op(str + sizeof(ws),OP_EQ,
    5324             :               eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5325             : 
    5326             :   /* Eat comment */
    5327           1 :   strlcpy(str, "# Comment \n No Comment", sizeof(str));
    5328           1 :   tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
    5329           1 :   tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
    5330           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
    5331           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5332             : 
    5333             :   /* Eat comment & ws mix */
    5334           1 :   strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
    5335           1 :   tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
    5336           1 :   tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
    5337           1 :   tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
    5338           1 :   tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5339             : 
    5340             :   /* Eat entire comment */
    5341           1 :   strlcpy(str, "#Comment", sizeof(str));
    5342           1 :   tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
    5343           1 :   tt_ptr_op(str + strlen(str),OP_EQ,
    5344             :             eat_whitespace_eos(str, str + strlen(str)));
    5345           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
    5346           1 :   tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5347             : 
    5348             :   /* Blank line, then comment */
    5349           1 :   strlcpy(str, " \t\n # Comment", sizeof(str));
    5350           1 :   tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
    5351           1 :   tt_ptr_op(str + strlen(str),OP_EQ,
    5352             :             eat_whitespace_eos(str, str + strlen(str)));
    5353           1 :   tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
    5354           1 :   tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
    5355             : 
    5356           1 :  done:
    5357           1 :   ;
    5358           1 : }
    5359             : 
    5360             : /** Return a newly allocated smartlist containing the lines of text in
    5361             :  * <b>lines</b>.  The returned strings are heap-allocated, and must be
    5362             :  * freed by the caller.
    5363             :  *
    5364             :  * XXXX? Move to container.[hc] ? */
    5365             : static smartlist_t *
    5366           8 : smartlist_new_from_text_lines(const char *lines)
    5367             : {
    5368           8 :   smartlist_t *sl = smartlist_new();
    5369           8 :   char *last_line;
    5370             : 
    5371           8 :   smartlist_split_string(sl, lines, "\n", 0, 0);
    5372             : 
    5373           8 :   last_line = smartlist_pop_last(sl);
    5374           8 :   if (last_line != NULL && *last_line != '\0') {
    5375           2 :     smartlist_add(sl, last_line);
    5376             :   } else {
    5377           6 :     tor_free(last_line);
    5378             :   }
    5379             : 
    5380           8 :   return sl;
    5381             : }
    5382             : 
    5383             : /** Test smartlist_new_from_text_lines */
    5384             : static void
    5385           1 : test_util_sl_new_from_text_lines(void *ptr)
    5386             : {
    5387           1 :   (void)ptr;
    5388             : 
    5389             :   { /* Normal usage */
    5390           1 :     smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
    5391           1 :     int sl_len = smartlist_len(sl);
    5392             : 
    5393           1 :     tt_want_int_op(sl_len, OP_EQ, 3);
    5394             : 
    5395           1 :     if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
    5396           1 :     if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
    5397           1 :     if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
    5398             : 
    5399           4 :     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
    5400           1 :     smartlist_free(sl);
    5401             :   }
    5402             : 
    5403             :   { /* No final newline */
    5404           1 :     smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
    5405           1 :     int sl_len = smartlist_len(sl);
    5406             : 
    5407           1 :     tt_want_int_op(sl_len, OP_EQ, 3);
    5408             : 
    5409           1 :     if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
    5410           1 :     if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
    5411           1 :     if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
    5412             : 
    5413           4 :     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
    5414           1 :     smartlist_free(sl);
    5415             :   }
    5416             : 
    5417             :   { /* No newlines */
    5418           1 :     smartlist_t *sl = smartlist_new_from_text_lines("foo");
    5419           1 :     int sl_len = smartlist_len(sl);
    5420             : 
    5421           1 :     tt_want_int_op(sl_len, OP_EQ, 1);
    5422             : 
    5423           1 :     if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
    5424             : 
    5425           2 :     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
    5426           1 :     smartlist_free(sl);
    5427             :   }
    5428             : 
    5429             :   { /* No text at all */
    5430           1 :     smartlist_t *sl = smartlist_new_from_text_lines("");
    5431           1 :     int sl_len = smartlist_len(sl);
    5432             : 
    5433           1 :     tt_want_int_op(sl_len, OP_EQ, 0);
    5434             : 
    5435           1 :     SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
    5436           1 :     smartlist_free(sl);
    5437             :   }
    5438           1 : }
    5439             : 
    5440             : static void
    5441           1 : test_util_envnames(void *ptr)
    5442             : {
    5443           1 :   (void) ptr;
    5444             : 
    5445           1 :   tt_assert(environment_variable_names_equal("abc", "abc"));
    5446           1 :   tt_assert(environment_variable_names_equal("abc", "abc="));
    5447           1 :   tt_assert(environment_variable_names_equal("abc", "abc=def"));
    5448           1 :   tt_assert(environment_variable_names_equal("abc=def", "abc"));
    5449           1 :   tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
    5450             : 
    5451           1 :   tt_assert(environment_variable_names_equal("abc", "abc"));
    5452           1 :   tt_assert(environment_variable_names_equal("abc", "abc="));
    5453           1 :   tt_assert(environment_variable_names_equal("abc", "abc=def"));
    5454           1 :   tt_assert(environment_variable_names_equal("abc=def", "abc"));
    5455           1 :   tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
    5456             : 
    5457           1 :   tt_assert(!environment_variable_names_equal("abc", "abcd"));
    5458           1 :   tt_assert(!environment_variable_names_equal("abc=", "abcd"));
    5459           1 :   tt_assert(!environment_variable_names_equal("abc=", "abcd"));
    5460           1 :   tt_assert(!environment_variable_names_equal("abc=", "def"));
    5461           1 :   tt_assert(!environment_variable_names_equal("abc=", "def="));
    5462           1 :   tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
    5463             : 
    5464           1 :   tt_assert(!environment_variable_names_equal("", "a=def"));
    5465             :   /* A bit surprising. */
    5466           1 :   tt_assert(environment_variable_names_equal("", "=def"));
    5467           1 :   tt_assert(environment_variable_names_equal("=y", "=x"));
    5468             : 
    5469           1 :  done:
    5470           1 :   ;
    5471           1 : }
    5472             : 
    5473             : /** Test process_environment_make */
    5474             : static void
    5475           1 : test_util_make_environment(void *ptr)
    5476             : {
    5477           1 :   const char *env_vars_string =
    5478             :     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
    5479             :     "HOME=/home/foozer\n";
    5480           1 :   const char expected_windows_env_block[] =
    5481             :     "HOME=/home/foozer\000"
    5482             :     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
    5483             :     "\000";
    5484           1 :   size_t expected_windows_env_block_len =
    5485             :     sizeof(expected_windows_env_block) - 1;
    5486             : 
    5487           1 :   smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
    5488           1 :   smartlist_t *env_vars_sorted = smartlist_new();
    5489           1 :   smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
    5490             : 
    5491           1 :   process_environment_t *env;
    5492             : 
    5493           1 :   (void)ptr;
    5494             : 
    5495           1 :   env = process_environment_make(env_vars);
    5496             : 
    5497             :   /* Check that the Windows environment block is correct. */
    5498           1 :   tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
    5499             :                     expected_windows_env_block_len));
    5500             : 
    5501             :   /* Now for the Unixoid environment block.  We don't care which order
    5502             :    * these environment variables are in, so we sort both lists first. */
    5503             : 
    5504           1 :   smartlist_add_all(env_vars_sorted, env_vars);
    5505             : 
    5506             :   {
    5507           1 :     char **v;
    5508           3 :     for (v = env->unixoid_environment_block; *v; ++v) {
    5509           2 :       smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
    5510             :     }
    5511             :   }
    5512             : 
    5513           1 :   smartlist_sort_strings(env_vars_sorted);
    5514           1 :   smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
    5515             : 
    5516           1 :   tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
    5517             :                  smartlist_len(env_vars_in_unixoid_env_block_sorted));
    5518             :   {
    5519           1 :     int len = smartlist_len(env_vars_sorted);
    5520           1 :     int i;
    5521             : 
    5522           1 :     if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
    5523             :       len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
    5524             :     }
    5525             : 
    5526           3 :     for (i = 0; i < len; ++i) {
    5527           2 :       tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
    5528             :                      smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
    5529             :     }
    5530             :   }
    5531             : 
    5532             :   /* Clean up. */
    5533           1 :   smartlist_free(env_vars_in_unixoid_env_block_sorted);
    5534           1 :   smartlist_free(env_vars_sorted);
    5535             : 
    5536           3 :   SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
    5537           1 :   smartlist_free(env_vars);
    5538             : 
    5539           1 :   process_environment_free(env);
    5540           1 : }
    5541             : 
    5542             : /** Test set_environment_variable_in_smartlist */
    5543             : static void
    5544           1 : test_util_set_env_var_in_sl(void *ptr)
    5545             : {
    5546             :   /* The environment variables in these strings are in arbitrary
    5547             :    * order; we sort the resulting lists before comparing them.
    5548             :    *
    5549             :    * (They *will not* end up in the order shown in
    5550             :    * expected_resulting_env_vars_string.) */
    5551             : 
    5552           1 :   const char *base_env_vars_string =
    5553             :     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
    5554             :     "HOME=/home/foozer\n"
    5555             :     "TERM=xterm\n"
    5556             :     "SHELL=/bin/ksh\n"
    5557             :     "USER=foozer\n"
    5558             :     "LOGNAME=foozer\n"
    5559             :     "USERNAME=foozer\n"
    5560             :     "LANG=en_US.utf8\n"
    5561             :     ;
    5562             : 
    5563           1 :   const char *new_env_vars_string =
    5564             :     "TERM=putty\n"
    5565             :     "DISPLAY=:18.0\n"
    5566             :     ;
    5567             : 
    5568           1 :   const char *expected_resulting_env_vars_string =
    5569             :     "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
    5570             :     "HOME=/home/foozer\n"
    5571             :     "TERM=putty\n"
    5572             :     "SHELL=/bin/ksh\n"
    5573             :     "USER=foozer\n"
    5574             :     "LOGNAME=foozer\n"
    5575             :     "USERNAME=foozer\n"
    5576             :     "LANG=en_US.utf8\n"
    5577             :     "DISPLAY=:18.0\n"
    5578             :     ;
    5579             : 
    5580           2 :   smartlist_t *merged_env_vars =
    5581           1 :     smartlist_new_from_text_lines(base_env_vars_string);
    5582           2 :   smartlist_t *new_env_vars =
    5583           1 :     smartlist_new_from_text_lines(new_env_vars_string);
    5584           2 :   smartlist_t *expected_resulting_env_vars =
    5585           1 :     smartlist_new_from_text_lines(expected_resulting_env_vars_string);
    5586             : 
    5587             :   /* Elements of merged_env_vars are heap-allocated, and must be
    5588             :    * freed.  Some of them are (or should) be freed by
    5589             :    * set_environment_variable_in_smartlist.
    5590             :    *
    5591             :    * Elements of new_env_vars are heap-allocated, but are copied into
    5592             :    * merged_env_vars, so they are not freed separately at the end of
    5593             :    * the function.
    5594             :    *
    5595             :    * Elements of expected_resulting_env_vars are heap-allocated, and
    5596             :    * must be freed. */
    5597             : 
    5598           1 :   (void)ptr;
    5599             : 
    5600           3 :   SMARTLIST_FOREACH(new_env_vars, char *, env_var,
    5601             :                     set_environment_variable_in_smartlist(merged_env_vars,
    5602             :                                                           env_var,
    5603             :                                                           tor_free_,
    5604             :                                                           1));
    5605             : 
    5606           1 :   smartlist_sort_strings(merged_env_vars);
    5607           1 :   smartlist_sort_strings(expected_resulting_env_vars);
    5608             : 
    5609           1 :   tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
    5610             :                  smartlist_len(expected_resulting_env_vars));
    5611             :   {
    5612           1 :     int len = smartlist_len(merged_env_vars);
    5613           1 :     int i;
    5614             : 
    5615           1 :     if (smartlist_len(expected_resulting_env_vars) < len) {
    5616             :       len = smartlist_len(expected_resulting_env_vars);
    5617             :     }
    5618             : 
    5619          10 :     for (i = 0; i < len; ++i) {
    5620           9 :       tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
    5621             :                      smartlist_get(expected_resulting_env_vars, i));
    5622             :     }
    5623             :   }
    5624             : 
    5625             :   /* Clean up. */
    5626          10 :   SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
    5627           1 :   smartlist_free(merged_env_vars);
    5628             : 
    5629           1 :   smartlist_free(new_env_vars);
    5630             : 
    5631          10 :   SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
    5632           1 :   smartlist_free(expected_resulting_env_vars);
    5633           1 : }
    5634             : 
    5635             : static void
    5636           1 : test_util_weak_random(void *arg)
    5637             : {
    5638           1 :   int i, j, n[16];
    5639           1 :   tor_weak_rng_t rng;
    5640           1 :   (void) arg;
    5641             : 
    5642           1 :   tor_init_weak_random(&rng, (unsigned)time(NULL));
    5643             : 
    5644         258 :   for (i = 1; i <= 256; ++i) {
    5645       25856 :     for (j=0;j<100;++j) {
    5646       25600 :       int r = tor_weak_random_range(&rng, i);
    5647       25600 :       tt_int_op(0, OP_LE, r);
    5648       25600 :       tt_int_op(r, OP_LT, i);
    5649             :     }
    5650             :   }
    5651             : 
    5652           1 :   memset(n,0,sizeof(n));
    5653        8193 :   for (j=0;j<8192;++j) {
    5654        8192 :     n[tor_weak_random_range(&rng, 16)]++;
    5655             :   }
    5656             : 
    5657          17 :   for (i=0;i<16;++i)
    5658          16 :     tt_int_op(n[i], OP_GT, 0);
    5659           1 :  done:
    5660           1 :   ;
    5661           1 : }
    5662             : 
    5663             : static void
    5664           1 : test_util_mathlog(void *arg)
    5665             : {
    5666           1 :   double d;
    5667           1 :   (void) arg;
    5668             : 
    5669           1 :   d = tor_mathlog(2.718281828);
    5670           1 :   tt_double_op(fabs(d - 1.0), OP_LT, .000001);
    5671           1 :   d = tor_mathlog(10);
    5672           1 :   tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
    5673           1 :  done:
    5674           1 :   ;
    5675           1 : }
    5676             : 
    5677             : static void
    5678           1 : test_util_fraction(void *arg)
    5679             : {
    5680           1 :   uint64_t a,b;
    5681           1 :   (void)arg;
    5682             : 
    5683           1 :   a = 99; b = 30;
    5684           1 :   simplify_fraction64(&a,&b);
    5685           1 :   tt_u64_op(a, OP_EQ, 33);
    5686           1 :   tt_u64_op(b, OP_EQ, 10);
    5687             : 
    5688           1 :   a = 3000000; b = 10000000;
    5689           1 :   simplify_fraction64(&a,&b);
    5690           1 :   tt_u64_op(a, OP_EQ, 3);
    5691           1 :   tt_u64_op(b, OP_EQ, 10);
    5692             : 
    5693           1 :   a = 0; b = 15;
    5694           1 :   simplify_fraction64(&a,&b);
    5695           1 :   tt_u64_op(a, OP_EQ, 0);
    5696           1 :   tt_u64_op(b, OP_EQ, 1);
    5697             : 
    5698           1 :  done:
    5699           1 :   ;
    5700           1 : }
    5701             : 
    5702             : static void
    5703           1 : test_util_round_to_next_multiple_of(void *arg)
    5704             : {
    5705           1 :   (void)arg;
    5706             : 
    5707           1 :   tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0);
    5708           1 :   tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0);
    5709             : 
    5710           1 :   tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99);
    5711           1 :   tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105);
    5712           1 :   tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99);
    5713             : 
    5714           1 :   tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ,
    5715             :             UINT64_MAX);
    5716             : 
    5717           1 :   tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0);
    5718           1 :   tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0);
    5719             : 
    5720           1 :   tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99);
    5721           1 :   tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105);
    5722           1 :   tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99);
    5723             : 
    5724           1 :   tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ,
    5725             :             UINT32_MAX);
    5726             : 
    5727           1 :   tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0);
    5728           1 :   tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0);
    5729             : 
    5730           1 :   tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99);
    5731           1 :   tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105);
    5732           1 :   tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99);
    5733             : 
    5734           1 :   tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ,
    5735             :             UINT_MAX);
    5736           1 :  done:
    5737           1 :   ;
    5738           1 : }
    5739             : 
    5740             : static void
    5741           1 : test_util_laplace(void *arg)
    5742             : {
    5743             :   /* Sample values produced using Python's SciPy:
    5744             :    *
    5745             :    * >>> from scipy.stats import laplace
    5746             :    * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
    5747             :      ...             loc = 24, scale = 24)
    5748             :    * array([          nan,          -inf,  -69.88855213,   24.        ,
    5749             :    *          24.48486498,  117.88855213,           inf,           nan])
    5750             :    */
    5751           1 :   const double mu = 24.0, b = 24.0;
    5752           1 :   const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
    5753           1 :   (void)arg;
    5754             : 
    5755           1 :   tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0));
    5756           1 :   tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01));
    5757           1 :   tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5));
    5758           1 :   tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51));
    5759           1 :   tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99));
    5760             : 
    5761             :   /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
    5762             :    * ...             loc = 0, scale = 50)
    5763             :    * array([         -inf,  -80.47189562,  -34.65735903,    0.        ,
    5764             :    *          34.65735903,   80.47189562,  195.60115027])
    5765             :    */
    5766           1 :   tt_i64_op(INT64_MIN + 20, OP_EQ,
    5767             :             add_laplace_noise(20, 0.0, delta_f, epsilon));
    5768             : 
    5769           1 :   tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon));
    5770           1 :   tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon));
    5771           1 :   tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon));
    5772           1 :   tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon));
    5773           1 :   tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon));
    5774           1 :   tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon));
    5775             : 
    5776             :   /* Test extreme values of signal with maximally negative values of noise
    5777             :    * 1.0000000000000002 is the smallest number > 1
    5778             :    * 0.0000000000000002 is the double epsilon (error when calculating near 1)
    5779             :    * this is approximately 1/(2^52)
    5780             :    * per https://en.wikipedia.org/wiki/Double_precision
    5781             :    * (let's not descend into the world of subnormals)
    5782             :    * >>> laplace.ppf([0, 0.0000000000000002], loc = 0, scale = 1)
    5783             :    * array([        -inf, -35.45506713])
    5784             :    */
    5785           1 :   const double noscale_df = 1.0, noscale_eps = 1.0;
    5786             : 
    5787           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5788             :             add_laplace_noise(0, 0.0, noscale_df, noscale_eps));
    5789             : 
    5790             :   /* is it clipped to INT64_MIN? */
    5791           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5792             :             add_laplace_noise(-1, 0.0, noscale_df, noscale_eps));
    5793           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5794             :             add_laplace_noise(INT64_MIN, 0.0,
    5795             :                               noscale_df, noscale_eps));
    5796             :   /* ... even when scaled? */
    5797           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5798             :             add_laplace_noise(0, 0.0, delta_f, epsilon));
    5799           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5800             :             add_laplace_noise(0, 0.0,
    5801             :                               DBL_MAX, 1));
    5802           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5803             :             add_laplace_noise(INT64_MIN, 0.0,
    5804             :                               DBL_MAX, 1));
    5805             : 
    5806             :   /* does it play nice with INT64_MAX? */
    5807           1 :   tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
    5808             :             add_laplace_noise(INT64_MAX, 0.0,
    5809             :                               noscale_df, noscale_eps));
    5810             : 
    5811             :   /* do near-zero fractional values work? */
    5812           1 :   const double min_dbl_error = 0.0000000000000002;
    5813             : 
    5814           1 :   tt_i64_op(-35, OP_EQ,
    5815             :             add_laplace_noise(0, min_dbl_error,
    5816             :                               noscale_df, noscale_eps));
    5817           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5818             :             add_laplace_noise(INT64_MIN, min_dbl_error,
    5819             :                               noscale_df, noscale_eps));
    5820           1 :   tt_i64_op((-35 + INT64_MAX), OP_EQ,
    5821             :             add_laplace_noise(INT64_MAX, min_dbl_error,
    5822             :                               noscale_df, noscale_eps));
    5823           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5824             :             add_laplace_noise(0, min_dbl_error,
    5825             :                               DBL_MAX, 1));
    5826           1 :   tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ,
    5827             :             add_laplace_noise(INT64_MAX, min_dbl_error,
    5828             :                               DBL_MAX, 1));
    5829           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5830             :             add_laplace_noise(INT64_MIN, min_dbl_error,
    5831             :                               DBL_MAX, 1));
    5832             : 
    5833             :   /* does it play nice with INT64_MAX? */
    5834           1 :   tt_i64_op((INT64_MAX - 35), OP_EQ,
    5835             :             add_laplace_noise(INT64_MAX, min_dbl_error,
    5836             :                               noscale_df, noscale_eps));
    5837             : 
    5838             :   /* Test extreme values of signal with maximally positive values of noise
    5839             :    * 1.0000000000000002 is the smallest number > 1
    5840             :    * 0.9999999999999998 is the greatest number < 1 by calculation
    5841             :    * per https://en.wikipedia.org/wiki/Double_precision
    5842             :    * >>> laplace.ppf([1.0, 0.9999999999999998], loc = 0, scale = 1)
    5843             :    * array([inf,  35.35050621])
    5844             :    * but the function rejects p == 1.0, so we just use max_dbl_lt_one
    5845             :    */
    5846           1 :   const double max_dbl_lt_one = 0.9999999999999998;
    5847             : 
    5848             :   /* do near-one fractional values work? */
    5849           1 :   tt_i64_op(35, OP_EQ,
    5850             :             add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps));
    5851             : 
    5852             :   /* is it clipped to INT64_MAX? */
    5853           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5854             :             add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one,
    5855             :                               noscale_df, noscale_eps));
    5856           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5857             :             add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one,
    5858             :                               noscale_df, noscale_eps));
    5859           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5860             :             add_laplace_noise(INT64_MAX, max_dbl_lt_one,
    5861             :                               noscale_df, noscale_eps));
    5862             :   /* ... even when scaled? */
    5863           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5864             :             add_laplace_noise(INT64_MAX, max_dbl_lt_one,
    5865             :                               delta_f, epsilon));
    5866           1 :   tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
    5867             :             add_laplace_noise(INT64_MIN, max_dbl_lt_one,
    5868             :                               DBL_MAX, 1));
    5869           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5870             :             add_laplace_noise(INT64_MAX, max_dbl_lt_one,
    5871             :                               DBL_MAX, 1));
    5872             :   /* does it play nice with INT64_MIN? */
    5873           1 :   tt_i64_op((INT64_MIN + 35), OP_EQ,
    5874             :             add_laplace_noise(INT64_MIN, max_dbl_lt_one,
    5875             :                               noscale_df, noscale_eps));
    5876             : 
    5877           1 :  done:
    5878           1 :   ;
    5879           1 : }
    5880             : 
    5881             : static void
    5882           1 : test_util_clamp_double_to_int64(void *arg)
    5883             : {
    5884           1 :   (void)arg;
    5885             : 
    5886           1 :   tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL));
    5887           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5888             :             clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0));
    5889           1 :   tt_i64_op(INT64_MIN, OP_EQ,
    5890             :             clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0));
    5891           1 :   tt_i64_op(((uint64_t) -1) << 53, OP_EQ,
    5892             :             clamp_double_to_int64(-1.0 * pow(2.0, 53.0)));
    5893           1 :   tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ,
    5894             :             clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0));
    5895           1 :   tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0));
    5896           1 :   tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9));
    5897           1 :   tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1));
    5898           1 :   tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0));
    5899           1 :   tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL));
    5900           1 :   tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1));
    5901           1 :   tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9));
    5902           1 :   tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0));
    5903           1 :   tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ,
    5904             :             clamp_double_to_int64(pow(2.0, 53.0) - 1.0));
    5905           1 :   tt_i64_op(((int64_t) 1) << 53, OP_EQ,
    5906             :             clamp_double_to_int64(pow(2.0, 53.0)));
    5907           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5908             :             clamp_double_to_int64(pow(2.0, 63.0)));
    5909           1 :   tt_i64_op(INT64_MAX, OP_EQ,
    5910             :             clamp_double_to_int64(pow(2.0, 64.0)));
    5911           1 :   tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL));
    5912             : 
    5913           1 :  done:
    5914           1 :   ;
    5915           1 : }
    5916             : 
    5917             : #ifdef FD_CLOEXEC
    5918             : #define CAN_CHECK_CLOEXEC
    5919             : static int
    5920          12 : fd_is_cloexec(tor_socket_t fd)
    5921             : {
    5922          12 :   int flags = fcntl(fd, F_GETFD, 0);
    5923          12 :   return (flags & FD_CLOEXEC) != 0;
    5924             : }
    5925             : #endif /* defined(FD_CLOEXEC) */
    5926             : 
    5927             : #ifndef _WIN32
    5928             : #define CAN_CHECK_NONBLOCK
    5929             : static int
    5930          12 : fd_is_nonblocking(tor_socket_t fd)
    5931             : {
    5932          12 :   int flags = fcntl(fd, F_GETFL, 0);
    5933          12 :   return (flags & O_NONBLOCK) != 0;
    5934             : }
    5935             : #endif /* !defined(_WIN32) */
    5936             : 
    5937             : #define ERRNO_IS_EPROTO(e)    (e == SOCK_ERRNO(EPROTONOSUPPORT))
    5938             : #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
    5939             : 
    5940             : /* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
    5941             : static void
    5942           2 : test_util_socket(void *arg)
    5943             : {
    5944           2 :   const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
    5945           2 :   tor_socket_t fd1 = TOR_INVALID_SOCKET;
    5946           2 :   tor_socket_t fd2 = TOR_INVALID_SOCKET;
    5947           2 :   tor_socket_t fd3 = TOR_INVALID_SOCKET;
    5948           2 :   tor_socket_t fd4 = TOR_INVALID_SOCKET;
    5949           2 :   int n = get_n_open_sockets();
    5950             : 
    5951           2 :   TT_BLATHER(("Starting with %d open sockets.", n));
    5952             : 
    5953           2 :   (void)arg;
    5954             : 
    5955           2 :   fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
    5956           2 :   int err = tor_socket_errno(fd1);
    5957           2 :   if (fd1 < 0 && (err == SOCK_ERRNO(EPROTONOSUPPORT) ||
    5958           0 :                   err == SOCK_ERRNO(EAFNOSUPPORT))) {
    5959             :     /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
    5960           0 :     goto done;
    5961             :   }
    5962           2 :   fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
    5963           2 :   tt_assert(SOCKET_OK(fd1));
    5964           2 :   tt_assert(SOCKET_OK(fd2));
    5965           2 :   tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
    5966             :   //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
    5967             :   //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
    5968           2 :   fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
    5969           2 :   fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
    5970           2 :   tt_assert(SOCKET_OK(fd3));
    5971           2 :   tt_assert(SOCKET_OK(fd4));
    5972           2 :   tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
    5973             : 
    5974             : #ifdef CAN_CHECK_CLOEXEC
    5975           2 :   tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
    5976           2 :   tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
    5977           2 :   tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
    5978           2 :   tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
    5979             : #endif /* defined(CAN_CHECK_CLOEXEC) */
    5980             : #ifdef CAN_CHECK_NONBLOCK
    5981           2 :   tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
    5982           2 :   tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
    5983           2 :   tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
    5984           2 :   tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
    5985             : #endif /* defined(CAN_CHECK_NONBLOCK) */
    5986             : 
    5987           2 :   tor_assert(tor_close_socket == tor_close_socket__real);
    5988             : 
    5989             :   /* we use close_socket__real here so that coverity can tell that we are
    5990             :    * really closing these sockets. */
    5991           2 :   tor_close_socket__real(fd1);
    5992           2 :   tor_close_socket__real(fd2);
    5993           2 :   fd1 = fd2 = TOR_INVALID_SOCKET;
    5994           2 :   tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
    5995           2 :   tor_close_socket__real(fd3);
    5996           2 :   tor_close_socket__real(fd4);
    5997           2 :   fd3 = fd4 = TOR_INVALID_SOCKET;
    5998           2 :   tt_int_op(get_n_open_sockets(), OP_EQ, n);
    5999             : 
    6000           2 :  done:
    6001           2 :   if (SOCKET_OK(fd1))
    6002           0 :     tor_close_socket__real(fd1);
    6003           2 :   if (SOCKET_OK(fd2))
    6004           0 :     tor_close_socket__real(fd2);
    6005           2 :   if (SOCKET_OK(fd3))
    6006           0 :     tor_close_socket__real(fd3);
    6007           2 :   if (SOCKET_OK(fd4))
    6008           0 :     tor_close_socket__real(fd4);
    6009           2 : }
    6010             : 
    6011             : #if 0
    6012             : static int
    6013             : is_there_a_localhost(int family)
    6014             : {
    6015             :   tor_socket_t s;
    6016             :   s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP);
    6017             :   tor_assert(SOCKET_OK(s));
    6018             : 
    6019             :   int result = 0;
    6020             :   if (family == AF_INET) {
    6021             :     struct sockaddr_in s_in;
    6022             :     memset(&s_in, 0, sizeof(s_in));
    6023             :     s_in.sin_family = AF_INET;
    6024             :     s_in.sin_addr.s_addr = htonl(0x7f000001);
    6025             :     s_in.sin_port = 0;
    6026             : 
    6027             :     if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) {
    6028             :       result = 1;
    6029             :     }
    6030             :   } else if (family == AF_INET6) {
    6031             :     struct sockaddr_in6 sin6;
    6032             :     memset(&sin6, 0, sizeof(sin6));
    6033             :     sin6.sin6_family = AF_INET6;
    6034             :     sin6.sin6_addr.s6_addr[15] = 1;
    6035             :     sin6.sin6_port = 0;
    6036             :   }
    6037             :   tor_close_socket(s);
    6038             : 
    6039             :   return result;
    6040             : }
    6041             : #endif /* 0 */
    6042             : 
    6043             : /* Test for socketpair and ersatz_socketpair().  We test them both, since
    6044             :  * the latter is a tolerably good way to exercise tor_accept_socket(). */
    6045             : static void
    6046           2 : test_util_socketpair(void *arg)
    6047             : {
    6048           2 :   const int ersatz = !strcmp(arg, "1");
    6049           2 :   int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
    6050             :     ersatz ? tor_ersatz_socketpair : tor_socketpair;
    6051           2 :   int n = get_n_open_sockets();
    6052           2 :   tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
    6053           2 :   const int family = AF_UNIX;
    6054           2 :   int socketpair_result = 0;
    6055             : 
    6056           2 :   socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
    6057             : 
    6058             : #ifdef __FreeBSD__
    6059             :   /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail.
    6060             :    * Otherwise, we risk exposing a socketpair on a routable IP address. (Some
    6061             :    * BSD jails use a routable address for localhost. Fortunately, they have
    6062             :    * the real AF_UNIX socketpair.) */
    6063             :   if (ersatz && socketpair_result < 0) {
    6064             :     /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL.
    6065             :      * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */
    6066             :     tt_skip();
    6067             :   }
    6068             : #endif /* defined(__FreeBSD__) */
    6069             : #ifdef ENETUNREACH
    6070           2 :   if (ersatz && socketpair_result == -ENETUNREACH) {
    6071             :     /* We can also fail with -ENETUNREACH if we have no network stack at
    6072             :      * all. */
    6073           0 :     tt_skip();
    6074             :   }
    6075             : #endif /* defined(ENETUNREACH) */
    6076           2 :   tt_int_op(0, OP_EQ, socketpair_result);
    6077             : 
    6078           2 :   tt_assert(SOCKET_OK(fds[0]));
    6079           2 :   tt_assert(SOCKET_OK(fds[1]));
    6080           2 :   if (ersatz)
    6081           1 :     tt_int_op(get_n_open_sockets(), OP_EQ, n);
    6082             :   else
    6083           1 :     tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
    6084             : #ifdef CAN_CHECK_CLOEXEC
    6085           2 :   tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, !ersatz);
    6086           2 :   tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, !ersatz);
    6087             : #endif
    6088             : #ifdef CAN_CHECK_NONBLOCK
    6089           2 :   tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
    6090           2 :   tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
    6091             : #endif
    6092             : 
    6093           2 :  done:
    6094           2 :   if (ersatz) {
    6095           1 :     if (SOCKET_OK(fds[0]))
    6096           1 :       tor_close_socket_simple(fds[0]);
    6097           1 :     if (SOCKET_OK(fds[1]))
    6098           1 :       tor_close_socket_simple(fds[1]);
    6099             :   } else {
    6100           1 :     if (SOCKET_OK(fds[0]))
    6101           1 :       tor_close_socket(fds[0]);
    6102           1 :     if (SOCKET_OK(fds[1]))
    6103           1 :       tor_close_socket(fds[1]);
    6104             :   }
    6105           2 : }
    6106             : 
    6107             : #undef SOCKET_EPROTO
    6108             : 
    6109             : static void
    6110           1 : test_util_max_mem(void *arg)
    6111             : {
    6112           1 :   size_t memory1, memory2;
    6113           1 :   int r, r2;
    6114           1 :   (void) arg;
    6115             : 
    6116           1 :   r = get_total_system_memory(&memory1);
    6117           1 :   r2 = get_total_system_memory(&memory2);
    6118           1 :   tt_int_op(r, OP_EQ, r2);
    6119           1 :   tt_uint_op(memory2, OP_EQ, memory1);
    6120             : 
    6121           1 :   TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1)));
    6122             : 
    6123           1 :   if (r==0) {
    6124             :     /* You have at least a megabyte. */
    6125           1 :     tt_uint_op(memory1, OP_GT, (1<<20));
    6126             :   } else {
    6127             :     /* You do not have a petabyte. */
    6128             : #if SIZEOF_SIZE_T >= 8
    6129           0 :     tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50));
    6130             : #endif
    6131             :   }
    6132             : 
    6133           0 :  done:
    6134           1 :   ;
    6135           1 : }
    6136             : 
    6137             : static void
    6138           1 : test_util_dest_validation_edgecase(void *arg)
    6139             : {
    6140           1 :   (void)arg;
    6141             : 
    6142           1 :   tt_assert(!string_is_valid_dest(NULL));
    6143           1 :   tt_assert(!string_is_valid_dest(""));
    6144             : 
    6145           1 :   done:
    6146           1 :   return;
    6147             : }
    6148             : 
    6149             : static void
    6150           1 : test_util_hostname_validation(void *arg)
    6151             : {
    6152           1 :   (void)arg;
    6153             : 
    6154             :   // Lets try valid hostnames first.
    6155           1 :   tt_assert(string_is_valid_nonrfc_hostname("torproject.org"));
    6156           1 :   tt_assert(string_is_valid_nonrfc_hostname("ocw.mit.edu"));
    6157           1 :   tt_assert(string_is_valid_nonrfc_hostname("i.4cdn.org"));
    6158           1 :   tt_assert(string_is_valid_nonrfc_hostname("stanford.edu"));
    6159           1 :   tt_assert(string_is_valid_nonrfc_hostname("multiple-words-with-hypens.jp"));
    6160             : 
    6161             :   // Subdomain name cannot start with '-' or '_'.
    6162           1 :   tt_assert(!string_is_valid_nonrfc_hostname("-torproject.org"));
    6163           1 :   tt_assert(!string_is_valid_nonrfc_hostname("subdomain.-domain.org"));
    6164           1 :   tt_assert(!string_is_valid_nonrfc_hostname("-subdomain.domain.org"));
    6165           1 :   tt_assert(!string_is_valid_nonrfc_hostname("___abc.org"));
    6166             : 
    6167             :   // Hostnames cannot contain non-alphanumeric characters.
    6168           1 :   tt_assert(!string_is_valid_nonrfc_hostname("%%domain.\\org."));
    6169           1 :   tt_assert(!string_is_valid_nonrfc_hostname("***x.net"));
    6170           1 :   tt_assert(!string_is_valid_nonrfc_hostname("\xff\xffxyz.org"));
    6171           1 :   tt_assert(!string_is_valid_nonrfc_hostname("word1 word2.net"));
    6172             : 
    6173             :   // Test workaround for nytimes.com stupidity, technically invalid,
    6174             :   // but we allow it since they are big, even though they are failing to
    6175             :   // comply with a ~30 year old standard.
    6176           1 :   tt_assert(string_is_valid_nonrfc_hostname("core3_euw1.fabrik.nytimes.com"));
    6177             : 
    6178             :   // Firefox passes FQDNs with trailing '.'s  directly to the SOCKS proxy,
    6179             :   // which is redundant since the spec states DOMAINNAME addresses are fully
    6180             :   // qualified.  While unusual, this should be tollerated.
    6181           1 :   tt_assert(string_is_valid_nonrfc_hostname("core9_euw1.fabrik.nytimes.com."));
    6182           1 :   tt_assert(!string_is_valid_nonrfc_hostname(
    6183             :                                          "..washingtonpost.is.better.com"));
    6184           1 :   tt_assert(!string_is_valid_nonrfc_hostname("so.is..ft.com"));
    6185           1 :   tt_assert(!string_is_valid_nonrfc_hostname("..."));
    6186             : 
    6187             :   // XXX: do we allow single-label DNS names?
    6188             :   // We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
    6189             :   // but only test pathologically malformed trailing '.' cases for now.
    6190           1 :   tt_assert(!string_is_valid_nonrfc_hostname("."));
    6191           1 :   tt_assert(!string_is_valid_nonrfc_hostname(".."));
    6192             : 
    6193             :   // IP address strings are not hostnames.
    6194           1 :   tt_assert(!string_is_valid_nonrfc_hostname("8.8.8.8"));
    6195           1 :   tt_assert(!string_is_valid_nonrfc_hostname("[2a00:1450:401b:800::200e]"));
    6196           1 :   tt_assert(!string_is_valid_nonrfc_hostname("2a00:1450:401b:800::200e"));
    6197             : 
    6198             :   // We allow alphanumeric TLDs. For discussion, see ticket #25055.
    6199           1 :   tt_assert(string_is_valid_nonrfc_hostname("lucky.13"));
    6200           1 :   tt_assert(string_is_valid_nonrfc_hostname("luck.y13"));
    6201           1 :   tt_assert(string_is_valid_nonrfc_hostname("luck.y13."));
    6202             : 
    6203             :   // We allow punycode TLDs. For examples, see
    6204             :   // https://data.iana.org/TLD/tlds-alpha-by-domain.txt
    6205           1 :   tt_assert(string_is_valid_nonrfc_hostname("example.xn--l1acc"));
    6206             : 
    6207           1 :   done:
    6208           1 :   return;
    6209             : }
    6210             : 
    6211             : static void
    6212           1 : test_util_ipv4_validation(void *arg)
    6213             : {
    6214           1 :   (void)arg;
    6215             : 
    6216           1 :   tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
    6217           1 :   tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
    6218             : 
    6219           1 :   tt_assert(!string_is_valid_ipv4_address("abcd"));
    6220           1 :   tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
    6221           1 :   tt_assert(!string_is_valid_ipv4_address("8.8."));
    6222             : 
    6223           1 :   done:
    6224           1 :   return;
    6225             : }
    6226             : 
    6227             : static void
    6228           1 : test_util_ipv6_validation(void *arg)
    6229             : {
    6230           1 :   (void)arg;
    6231             : 
    6232           1 :   tt_assert(string_is_valid_ipv6_address("2a00:1450:401b:800::200e"));
    6233           1 :   tt_assert(!string_is_valid_ipv6_address("11:22::33:44:"));
    6234             : 
    6235           1 :   done:
    6236           1 :   return;
    6237             : }
    6238             : 
    6239             : static void
    6240           1 : test_util_writepid(void *arg)
    6241             : {
    6242           1 :   (void) arg;
    6243             : 
    6244           1 :   char *contents = NULL;
    6245           1 :   const char *fname = get_fname("tmp_pid");
    6246           1 :   unsigned long pid;
    6247           1 :   char c;
    6248             : 
    6249           1 :   write_pidfile(fname);
    6250             : 
    6251           1 :   contents = read_file_to_str(fname, 0, NULL);
    6252           1 :   tt_assert(contents);
    6253             : 
    6254           1 :   int n = tor_sscanf(contents, "%lu\n%c", &pid, &c);
    6255           1 :   tt_int_op(n, OP_EQ, 1);
    6256             : 
    6257             : #ifdef _WIN32
    6258             :   tt_uint_op(pid, OP_EQ, _getpid());
    6259             : #else
    6260           1 :   tt_uint_op(pid, OP_EQ, getpid());
    6261             : #endif
    6262             : 
    6263           1 :  done:
    6264           1 :   tor_free(contents);
    6265           1 : }
    6266             : 
    6267             : static void
    6268           1 : test_util_get_avail_disk_space(void *arg)
    6269             : {
    6270           1 :   (void) arg;
    6271           1 :   int64_t val;
    6272             : 
    6273             :   /* No answer for nonexistent directory */
    6274           1 :   val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa");
    6275           1 :   tt_i64_op(val, OP_EQ, -1);
    6276             : 
    6277             :   /* Try the current directory */
    6278           1 :   val = tor_get_avail_disk_space(".");
    6279             : 
    6280             : #if !defined(HAVE_STATVFS) && !defined(_WIN32)
    6281             :   tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */
    6282             : #else
    6283           1 :   tt_i64_op(val, OP_GT, 0); /* You have some space. */
    6284           1 :   tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */
    6285             : #endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */
    6286             : 
    6287           1 :  done:
    6288           1 :   ;
    6289           1 : }
    6290             : 
    6291             : /** Helper: Change the atime and mtime of a file. */
    6292             : static void
    6293           2 : set_file_mtime(const char *fname, time_t when)
    6294             : {
    6295           2 :   struct utimbuf u = { when, when };
    6296           2 :   struct stat st;
    6297           2 :   tt_int_op(0, OP_EQ, utime(fname, &u));
    6298           2 :   tt_int_op(0, OP_EQ, stat(fname, &st));
    6299             :   /* Let's hope that utime/stat give the same second as a round-trip? */
    6300           2 :   tt_i64_op(st.st_mtime, OP_EQ, when);
    6301           2 : done:
    6302           2 :   ;
    6303           2 : }
    6304             : 
    6305             : static void
    6306           1 : test_util_touch_file(void *arg)
    6307             : {
    6308           1 :   (void) arg;
    6309           1 :   const char *fname = get_fname("touch");
    6310             : 
    6311           1 :   const time_t now = time(NULL);
    6312           1 :   struct stat st;
    6313           1 :   write_bytes_to_file(fname, "abc", 3, 1);
    6314           1 :   tt_int_op(0, OP_EQ, stat(fname, &st));
    6315             :   /* A subtle point: the filesystem time is not necessarily equal to the
    6316             :    * system clock time, since one can be using a monotonic clock, or coarse
    6317             :    * monotonic clock, or whatever.  So we might wind up with an mtime a few
    6318             :    * microseconds ago.  Let's just give it a lot of wiggle room. */
    6319           1 :   tt_i64_op(st.st_mtime, OP_GE, now - 1);
    6320             : 
    6321           1 :   const time_t five_sec_ago = now - 5;
    6322           1 :   set_file_mtime(fname, five_sec_ago);
    6323             : 
    6324             :   /* Finally we can touch the file */
    6325           1 :   tt_int_op(0, OP_EQ, touch_file(fname));
    6326           1 :   tt_int_op(0, OP_EQ, stat(fname, &st));
    6327           1 :   tt_i64_op(st.st_mtime, OP_GE, now-1);
    6328             : 
    6329           1 :  done:
    6330           1 :   ;
    6331           1 : }
    6332             : 
    6333             : #ifndef DISABLE_PWDB_TESTS
    6334             : static void
    6335           1 : test_util_pwdb(void *arg)
    6336             : {
    6337           1 :   (void) arg;
    6338           1 :   const struct passwd *me = NULL, *me2, *me3;
    6339           1 :   char *name = NULL;
    6340           1 :   char *dir = NULL;
    6341             : 
    6342             :   /* Uncached case. */
    6343             :   /* Let's assume that we exist. */
    6344           1 :   me = tor_getpwuid(getuid());
    6345           1 :   tt_ptr_op(me, OP_NE, NULL);
    6346           1 :   name = tor_strdup(me->pw_name);
    6347             : 
    6348             :   /* Uncached case */
    6349           1 :   me2 = tor_getpwnam(name);
    6350           1 :   tt_ptr_op(me2, OP_NE, NULL);
    6351           1 :   tt_int_op(me2->pw_uid, OP_EQ, getuid());
    6352             : 
    6353             :   /* Cached case */
    6354           1 :   me3 = tor_getpwuid(getuid());
    6355           1 :   tt_ptr_op(me3, OP_NE, NULL);
    6356           1 :   tt_str_op(me3->pw_name, OP_EQ, name);
    6357             : 
    6358           1 :   me3 = tor_getpwnam(name);
    6359           1 :   tt_ptr_op(me3, OP_NE, NULL);
    6360           1 :   tt_int_op(me3->pw_uid, OP_EQ, getuid());
    6361             : 
    6362           1 :   dir = get_user_homedir(name);
    6363           1 :   tt_ptr_op(dir, OP_NE, NULL);
    6364             : 
    6365             :   /* Try failing cases.  First find a user that doesn't exist by name */
    6366             :   char randbytes[4];
    6367             :   char badname[9];
    6368           1 :   int i, found=0;
    6369           1 :   for (i = 0; i < 100; ++i) {
    6370           1 :     crypto_rand(randbytes, sizeof(randbytes));
    6371           1 :     base16_encode(badname, sizeof(badname), randbytes, sizeof(randbytes));
    6372           1 :     if (tor_getpwnam(badname) == NULL) {
    6373             :       found = 1;
    6374             :       break;
    6375             :     }
    6376             :   }
    6377           1 :   tt_assert(found);
    6378           1 :   tor_free(dir);
    6379             : 
    6380             :   /* We should do a LOG_ERR */
    6381           1 :   setup_full_capture_of_logs(LOG_ERR);
    6382           1 :   dir = get_user_homedir(badname);
    6383           1 :   tt_ptr_op(dir, OP_EQ, NULL);
    6384           1 :   expect_log_msg_containing("not found");
    6385           1 :   tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1);
    6386           1 :   teardown_capture_of_logs();
    6387             : 
    6388             :   /* Now try to find a user that doesn't exist by ID. */
    6389           1 :   found = 0;
    6390           2 :   for (i = 0; i < 1000; ++i) {
    6391           1 :     uid_t u;
    6392           1 :     crypto_rand((char*)&u, sizeof(u));
    6393           1 :     if (tor_getpwuid(u) == NULL) {
    6394           1 :       found = 1;
    6395           1 :       break;
    6396             :     }
    6397             :   }
    6398           1 :   tt_assert(found);
    6399             : 
    6400           1 :  done:
    6401           1 :   tor_free(name);
    6402           1 :   tor_free(dir);
    6403           1 :   teardown_capture_of_logs();
    6404           1 : }
    6405             : #endif /* !defined(DISABLE_PWDB_TESTS) */
    6406             : 
    6407             : static void
    6408           1 : test_util_calloc_check(void *arg)
    6409             : {
    6410           1 :   (void) arg;
    6411             :   /* Easy cases that are good. */
    6412           1 :   tt_assert(size_mul_check(0,0));
    6413           1 :   tt_assert(size_mul_check(0,100));
    6414           1 :   tt_assert(size_mul_check(100,0));
    6415           1 :   tt_assert(size_mul_check(100,100));
    6416             : 
    6417             :   /* Harder cases that are still good. */
    6418           1 :   tt_assert(size_mul_check(SIZE_MAX, 1));
    6419           1 :   tt_assert(size_mul_check(1, SIZE_MAX));
    6420           1 :   tt_assert(size_mul_check(SIZE_MAX / 10, 9));
    6421           1 :   tt_assert(size_mul_check(11, SIZE_MAX / 12));
    6422           1 :   const size_t sqrt_size_max_p1 = ((size_t)1) << (sizeof(size_t) * 4);
    6423           1 :   tt_assert(size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1 - 1));
    6424             : 
    6425             :   /* Cases that overflow */
    6426           1 :   tt_assert(! size_mul_check(SIZE_MAX, 2));
    6427           1 :   tt_assert(! size_mul_check(2, SIZE_MAX));
    6428           1 :   tt_assert(! size_mul_check(SIZE_MAX / 10, 11));
    6429           1 :   tt_assert(! size_mul_check(11, SIZE_MAX / 10));
    6430           1 :   tt_assert(! size_mul_check(SIZE_MAX / 8, 9));
    6431           1 :   tt_assert(! size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1));
    6432             : 
    6433           1 :  done:
    6434           1 :   ;
    6435           1 : }
    6436             : 
    6437             : static void
    6438           1 : test_util_monotonic_time(void *arg)
    6439             : {
    6440           1 :   (void)arg;
    6441             : 
    6442           1 :   monotime_t mt1, mt2;
    6443           1 :   monotime_coarse_t mtc1, mtc2;
    6444           1 :   uint64_t nsec1, nsec2, usec1, msec1;
    6445           1 :   uint64_t nsecc1, nsecc2, usecc1, msecc1;
    6446           1 :   uint32_t stamp1, stamp2;
    6447             : 
    6448           1 :   monotime_init();
    6449             : 
    6450           1 :   monotime_get(&mt1);
    6451           1 :   monotime_coarse_get(&mtc1);
    6452           1 :   nsec1 = monotime_absolute_nsec();
    6453           1 :   usec1 = monotime_absolute_usec();
    6454           1 :   msec1 = monotime_absolute_msec();
    6455           1 :   nsecc1 = monotime_coarse_absolute_nsec();
    6456           1 :   usecc1 = monotime_coarse_absolute_usec();
    6457           1 :   msecc1 = monotime_coarse_absolute_msec();
    6458           1 :   stamp1 = monotime_coarse_to_stamp(&mtc1);
    6459             : 
    6460           1 :   tor_sleep_msec(200);
    6461             : 
    6462           1 :   monotime_get(&mt2);
    6463           1 :   monotime_coarse_get(&mtc2);
    6464           1 :   nsec2 = monotime_absolute_nsec();
    6465           1 :   nsecc2 = monotime_coarse_absolute_nsec();
    6466           1 :   stamp2 = monotime_coarse_to_stamp(&mtc2);
    6467             : 
    6468             :   /* We need to be a little careful here since we don't know the system load.
    6469             :    */
    6470           1 :   tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_GE, 175);
    6471           1 :   tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_LT, 1000);
    6472           1 :   tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_GE, 125);
    6473           1 :   tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_LT, 1000);
    6474           1 :   tt_u64_op(nsec2-nsec1, OP_GE, 175000000);
    6475           1 :   tt_u64_op(nsec2-nsec1, OP_LT, 1000000000);
    6476           1 :   tt_u64_op(nsecc2-nsecc1, OP_GE, 125000000);
    6477           1 :   tt_u64_op(nsecc2-nsecc1, OP_LT, 1000000000);
    6478             : 
    6479           1 :   tt_u64_op(msec1, OP_GE, nsec1 / 1000000);
    6480           1 :   tt_u64_op(usec1, OP_GE, nsec1 / 1000);
    6481           1 :   tt_u64_op(msecc1, OP_GE, nsecc1 / 1000000);
    6482           1 :   tt_u64_op(usecc1, OP_GE, nsecc1 / 1000);
    6483           1 :   tt_u64_op(msec1, OP_LE, nsec1 / 1000000 + 10);
    6484           1 :   tt_u64_op(usec1, OP_LE, nsec1 / 1000 + 10000);
    6485           1 :   tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 10);
    6486           1 :   tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 10000);
    6487             : 
    6488           1 :   uint64_t coarse_stamp_diff =
    6489           1 :     monotime_coarse_stamp_units_to_approx_msec(stamp2-stamp1);
    6490           1 :   tt_u64_op(coarse_stamp_diff, OP_GE, 120);
    6491           1 :   tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
    6492             : 
    6493             :   {
    6494           1 :     uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
    6495           1 :     uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
    6496           1 :     tt_u64_op(ms, OP_GE, 4950);
    6497           1 :     tt_u64_op(ms, OP_LT, 5050);
    6498             :   }
    6499             : 
    6500           1 :  done:
    6501           1 :   ;
    6502           1 : }
    6503             : 
    6504             : static void
    6505           1 : test_util_monotonic_time_ratchet(void *arg)
    6506             : {
    6507           1 :   (void)arg;
    6508           1 :   monotime_init();
    6509           1 :   monotime_reset_ratchets_for_testing();
    6510             : 
    6511             :   /* win32, performance counter ratchet. */
    6512           1 :   tt_i64_op(100, OP_EQ, ratchet_performance_counter(100));
    6513           1 :   tt_i64_op(101, OP_EQ, ratchet_performance_counter(101));
    6514           1 :   tt_i64_op(2000, OP_EQ, ratchet_performance_counter(2000));
    6515           1 :   tt_i64_op(2000, OP_EQ, ratchet_performance_counter(100));
    6516           1 :   tt_i64_op(2005, OP_EQ, ratchet_performance_counter(105));
    6517           1 :   tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1105));
    6518           1 :   tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1000));
    6519           1 :   tt_i64_op(3010, OP_EQ, ratchet_performance_counter(1005));
    6520             : 
    6521             :   /* win32, GetTickCounts32 ratchet-and-rollover-detector. */
    6522           1 :   const int64_t R = ((int64_t)1) << 32;
    6523           1 :   tt_i64_op(5, OP_EQ, ratchet_coarse_performance_counter(5));
    6524           1 :   tt_i64_op(1000, OP_EQ, ratchet_coarse_performance_counter(1000));
    6525           1 :   tt_i64_op(5+R, OP_EQ, ratchet_coarse_performance_counter(5));
    6526           1 :   tt_i64_op(10+R, OP_EQ, ratchet_coarse_performance_counter(10));
    6527           1 :   tt_i64_op(4+R*2, OP_EQ, ratchet_coarse_performance_counter(4));
    6528             : 
    6529             :   /* gettimeofday regular ratchet. */
    6530           1 :   struct timeval tv_in = {0,0}, tv_out;
    6531           1 :   tv_in.tv_usec = 9000;
    6532             : 
    6533           1 :   ratchet_timeval(&tv_in, &tv_out);
    6534           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 9000);
    6535           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 0);
    6536             : 
    6537           1 :   tv_in.tv_sec = 1337;
    6538           1 :   tv_in.tv_usec = 0;
    6539           1 :   ratchet_timeval(&tv_in, &tv_out);
    6540           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 0);
    6541           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
    6542             : 
    6543           1 :   tv_in.tv_sec = 1336;
    6544           1 :   tv_in.tv_usec = 500000;
    6545           1 :   ratchet_timeval(&tv_in, &tv_out);
    6546           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 0);
    6547           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
    6548             : 
    6549           1 :   tv_in.tv_sec = 1337;
    6550           1 :   tv_in.tv_usec = 0;
    6551           1 :   ratchet_timeval(&tv_in, &tv_out);
    6552           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 500000);
    6553           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
    6554             : 
    6555           1 :   tv_in.tv_sec = 1337;
    6556           1 :   tv_in.tv_usec = 600000;
    6557           1 :   ratchet_timeval(&tv_in, &tv_out);
    6558           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
    6559           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
    6560             : 
    6561           1 :   tv_in.tv_sec = 1000;
    6562           1 :   tv_in.tv_usec = 1000;
    6563           1 :   ratchet_timeval(&tv_in, &tv_out);
    6564           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
    6565           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
    6566             : 
    6567           1 :   tv_in.tv_sec = 2000;
    6568           1 :   tv_in.tv_usec = 2000;
    6569           1 :   ratchet_timeval(&tv_in, &tv_out);
    6570           1 :   tt_int_op(tv_out.tv_usec, OP_EQ, 101000);
    6571           1 :   tt_i64_op(tv_out.tv_sec, OP_EQ, 2338);
    6572             : 
    6573           1 :  done:
    6574           1 :   ;
    6575           1 : }
    6576             : 
    6577             : static void
    6578           1 : test_util_monotonic_time_zero(void *arg)
    6579             : {
    6580           1 :   (void) arg;
    6581           1 :   monotime_t t1;
    6582           1 :   monotime_coarse_t ct1;
    6583           1 :   monotime_init();
    6584             :   /* Check 1: The current time is not zero. */
    6585           1 :   monotime_get(&t1);
    6586           1 :   monotime_coarse_get(&ct1);
    6587           1 :   tt_assert(!monotime_is_zero(&t1));
    6588           1 :   tt_assert(!monotime_coarse_is_zero(&ct1));
    6589             : 
    6590             :   /* Check 2: The _zero() makes the time zero. */
    6591           1 :   monotime_zero(&t1);
    6592           1 :   monotime_coarse_zero(&ct1);
    6593           1 :   tt_assert(monotime_is_zero(&t1));
    6594           1 :   tt_assert(monotime_coarse_is_zero(&ct1));
    6595           1 :  done:
    6596           1 :   ;
    6597           1 : }
    6598             : 
    6599             : static void
    6600           1 : test_util_monotonic_time_add_msec(void *arg)
    6601             : {
    6602           1 :   (void) arg;
    6603           1 :   monotime_t t1, t2;
    6604           1 :   monotime_coarse_t ct1, ct2;
    6605           1 :   monotime_init();
    6606             : 
    6607           1 :   monotime_get(&t1);
    6608           1 :   monotime_coarse_get(&ct1);
    6609             : 
    6610             :   /* adding zero does nothing */
    6611           1 :   monotime_add_msec(&t2, &t1, 0);
    6612           1 :   monotime_coarse_add_msec(&ct2, &ct1, 0);
    6613           1 :   tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 0);
    6614           1 :   tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 0);
    6615             : 
    6616             :   /* Add 1337 msec; see if the diff function agree */
    6617           1 :   monotime_add_msec(&t2, &t1, 1337);
    6618           1 :   monotime_coarse_add_msec(&ct2, &ct1, 1337);
    6619           1 :   tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
    6620           1 :   tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
    6621             :   // The 32-bit variant must be within 1% of the regular one.
    6622           1 :   tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
    6623           1 :   tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
    6624             : 
    6625             :   /* Add 1337 msec twice more; make sure that any second rollover issues
    6626             :    * worked. */
    6627           1 :   monotime_add_msec(&t2, &t2, 1337);
    6628           1 :   monotime_coarse_add_msec(&ct2, &ct2, 1337);
    6629           1 :   monotime_add_msec(&t2, &t2, 1337);
    6630           1 :   monotime_coarse_add_msec(&ct2, &ct2, 1337);
    6631           1 :   tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
    6632           1 :   tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
    6633           1 :   tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
    6634           1 :   tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
    6635             : 
    6636           1 :  done:
    6637           1 :   ;
    6638           1 : }
    6639             : 
    6640             : static void
    6641           1 : test_util_nowrap_math(void *arg)
    6642             : {
    6643           1 :   (void)arg;
    6644             : 
    6645           1 :   tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
    6646           1 :   tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
    6647           1 :   tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
    6648           1 :   tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
    6649           1 :   tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
    6650           1 :   tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
    6651           1 :   tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
    6652             : 
    6653           1 :   tt_u64_op(0, OP_EQ, tor_mul_u64_nowrap(0, 0));
    6654           1 :   tt_u64_op(1, OP_EQ, tor_mul_u64_nowrap(1, 1));
    6655           1 :   tt_u64_op(2, OP_EQ, tor_mul_u64_nowrap(2, 1));
    6656           1 :   tt_u64_op(4, OP_EQ, tor_mul_u64_nowrap(2, 2));
    6657           1 :   tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, 1));
    6658           1 :   tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(2, UINT64_MAX));
    6659           1 :   tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, UINT64_MAX));
    6660             : 
    6661           1 :  done:
    6662           1 :   ;
    6663           1 : }
    6664             : 
    6665             : static void
    6666           1 : test_util_htonll(void *arg)
    6667             : {
    6668           1 :   (void)arg;
    6669             : #ifdef WORDS_BIGENDIAN
    6670             :   const uint64_t res_be = 0x8877665544332211;
    6671             : #else
    6672           1 :   const uint64_t res_le = 0x1122334455667788;
    6673             : #endif
    6674             : 
    6675           1 :   tt_u64_op(0, OP_EQ, tor_htonll(0));
    6676           1 :   tt_u64_op(0, OP_EQ, tor_ntohll(0));
    6677           1 :   tt_u64_op(UINT64_MAX, OP_EQ, tor_htonll(UINT64_MAX));
    6678           1 :   tt_u64_op(UINT64_MAX, OP_EQ, tor_ntohll(UINT64_MAX));
    6679             : 
    6680             : #ifdef WORDS_BIGENDIAN
    6681             :   tt_u64_op(res_be, OP_EQ, tor_htonll(0x8877665544332211));
    6682             :   tt_u64_op(res_be, OP_EQ, tor_ntohll(0x8877665544332211));
    6683             : #else
    6684           1 :   tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211));
    6685           1 :   tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211));
    6686             : #endif /* defined(WORDS_BIGENDIAN) */
    6687             : 
    6688           1 :  done:
    6689           1 :   ;
    6690           1 : }
    6691             : 
    6692             : static void
    6693           1 : test_util_get_unquoted_path(void *arg)
    6694             : {
    6695           1 :   (void)arg;
    6696             : 
    6697           1 :   char *r = NULL;
    6698             : 
    6699           1 :   r = get_unquoted_path("\""); // "
    6700           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6701           1 :   tor_free(r);
    6702             : 
    6703           1 :   r = get_unquoted_path("\"\"\""); // """
    6704           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6705           1 :   tor_free(r);
    6706             : 
    6707           1 :   r = get_unquoted_path("\\\""); // \"
    6708           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6709           1 :   tor_free(r);
    6710             : 
    6711           1 :   r = get_unquoted_path("\\\"\\\""); // \"\"
    6712           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6713           1 :   tor_free(r);
    6714             : 
    6715           1 :   r = get_unquoted_path("A\\B\\C\""); // A\B\C"
    6716           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6717           1 :   tor_free(r);
    6718             : 
    6719           1 :   r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
    6720           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6721           1 :   tor_free(r);
    6722             : 
    6723           1 :   r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
    6724           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6725           1 :   tor_free(r);
    6726             : 
    6727           1 :   r = get_unquoted_path("A\\B\"C"); // A\B"C
    6728           1 :   tt_ptr_op(r, OP_EQ, NULL);
    6729           1 :   tor_free(r);
    6730             : 
    6731           1 :   r = get_unquoted_path("");
    6732           1 :   tt_str_op(r, OP_EQ, "");
    6733           1 :   tor_free(r);
    6734             : 
    6735           1 :   r = get_unquoted_path("\"\""); // ""
    6736           1 :   tt_str_op(r, OP_EQ, "");
    6737           1 :   tor_free(r);
    6738             : 
    6739           1 :   r = get_unquoted_path("A\\B\\C"); // A\B\C
    6740           1 :   tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
    6741           1 :   tor_free(r);
    6742             : 
    6743           1 :   r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
    6744           1 :   tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
    6745           1 :   tor_free(r);
    6746             : 
    6747           1 :   r = get_unquoted_path("\"\\\""); // "\"
    6748           1 :   tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
    6749           1 :   tor_free(r);
    6750             : 
    6751           1 :   r = get_unquoted_path("\"\\\"\""); // "\""
    6752           1 :   tt_str_op(r, OP_EQ, "\""); // "
    6753           1 :   tor_free(r);
    6754             : 
    6755           1 :   r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
    6756           1 :   tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
    6757           1 :   tor_free(r);
    6758             : 
    6759           1 :   r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
    6760           1 :   tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
    6761           1 :   tor_free(r);
    6762             : 
    6763           1 :   r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
    6764           1 :   tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
    6765             : 
    6766           1 :  done:
    6767           1 :   tor_free(r);
    6768           1 : }
    6769             : 
    6770             : static void
    6771           1 : test_util_map_anon(void *arg)
    6772             : {
    6773           1 :   (void)arg;
    6774           1 :   char *ptr = NULL;
    6775           1 :   size_t sz = 16384;
    6776           1 :   unsigned inherit=0;
    6777             : 
    6778             :   /* Basic checks. */
    6779           1 :   ptr = tor_mmap_anonymous(sz, 0, &inherit);
    6780           1 :   tt_ptr_op(ptr, OP_NE, 0);
    6781           1 :   tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
    6782           1 :   ptr[sz-1] = 3;
    6783           1 :   tt_int_op(ptr[0], OP_EQ, 0);
    6784           1 :   tt_int_op(ptr[sz-2], OP_EQ, 0);
    6785           1 :   tt_int_op(ptr[sz-1], OP_EQ, 3);
    6786             : 
    6787             :   /* Try again, with a private (non-swappable) mapping. */
    6788           1 :   tor_munmap_anonymous(ptr, sz);
    6789           1 :   ptr = tor_mmap_anonymous(sz, ANONMAP_PRIVATE, &inherit);
    6790           1 :   tt_ptr_op(ptr, OP_NE, 0);
    6791           1 :   tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
    6792           1 :   ptr[sz-1] = 10;
    6793           1 :   tt_int_op(ptr[0], OP_EQ, 0);
    6794           1 :   tt_int_op(ptr[sz/2], OP_EQ, 0);
    6795           1 :   tt_int_op(ptr[sz-1], OP_EQ, 10);
    6796             : 
    6797             :   /* Now let's test a drop-on-fork mapping. */
    6798           1 :   tor_munmap_anonymous(ptr, sz);
    6799           1 :   ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT, &inherit);
    6800           1 :   tt_ptr_op(ptr, OP_NE, 0);
    6801           1 :   ptr[sz-1] = 10;
    6802           1 :   tt_int_op(ptr[0], OP_EQ, 0);
    6803           1 :   tt_int_op(ptr[sz/2], OP_EQ, 0);
    6804           1 :   tt_int_op(ptr[sz-1], OP_EQ, 10);
    6805             : 
    6806           1 :  done:
    6807           1 :   tor_munmap_anonymous(ptr, sz);
    6808           1 : }
    6809             : 
    6810             : static void
    6811           1 : test_util_map_anon_nofork(void *arg)
    6812             : {
    6813           1 :   (void)arg;
    6814             : #ifdef _WIN32
    6815             :   /* The operating system doesn't support forking. */
    6816             :   tt_skip();
    6817             :  done:
    6818             :   ;
    6819             : #else /* !defined(_WIN32) */
    6820             :   /* We have the right OS support.  We're going to try marking the buffer as
    6821             :    * either zero-on-fork or as drop-on-fork, whichever is supported.  Then we
    6822             :    * will fork and send a byte back to the parent process.  This will either
    6823             :    * crash, or send zero. */
    6824             : 
    6825           1 :   char *ptr = NULL;
    6826           1 :   const char TEST_VALUE = 0xd0;
    6827           1 :   size_t sz = 16384;
    6828           1 :   int pipefd[2] = {-1, -1};
    6829           1 :   unsigned inherit=0;
    6830             : 
    6831           1 :   tor_munmap_anonymous(ptr, sz);
    6832           1 :   ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT, &inherit);
    6833           1 :   tt_ptr_op(ptr, OP_NE, 0);
    6834           1 :   memset(ptr, (uint8_t)TEST_VALUE, sz);
    6835             : 
    6836           1 :   tt_int_op(0, OP_EQ, pipe(pipefd));
    6837           1 :   pid_t child = fork();
    6838           2 :   if (child == 0) {
    6839             :     /* We're in the child. */
    6840           1 :     close(pipefd[0]);
    6841           1 :     ssize_t r = write(pipefd[1], &ptr[sz-1], 1); /* This may crash. */
    6842           1 :     close(pipefd[1]);
    6843           1 :     if (r < 0)
    6844           0 :       exit(1);
    6845           1 :     exit(0);
    6846             :   }
    6847           1 :   tt_int_op(child, OP_GT, 0);
    6848             :   /* In the parent. */
    6849           1 :   close(pipefd[1]);
    6850           1 :   pipefd[1] = -1;
    6851           1 :   char buf[1];
    6852           1 :   ssize_t r = read(pipefd[0], buf, 1);
    6853             : 
    6854           1 :   if (inherit == INHERIT_RES_ZERO) {
    6855             :     // We should be seeing clear-on-fork behavior.
    6856           1 :     tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
    6857           1 :     tt_int_op(buf[0], OP_EQ, 0); // that byte should be zero.
    6858           0 :   } else if (inherit == INHERIT_RES_DROP) {
    6859             :     // We should be seeing noinherit behavior.
    6860           0 :     tt_int_op(r, OP_LE, 0); // child said nothing; it should have crashed.
    6861             :   } else {
    6862             :     // noinherit isn't implemented.
    6863           0 :     tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
    6864           0 :     tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
    6865           0 :     tt_int_op(buf[0], OP_EQ, TEST_VALUE); // that byte should be TEST_VALUE.
    6866             :   }
    6867             : 
    6868           1 :   int ws;
    6869           1 :   waitpid(child, &ws, 0);
    6870             : 
    6871             : #ifndef NOINHERIT_CAN_FAIL
    6872             :   /* Only if NOINHERIT_CAN_FAIL should it be possible for us to get
    6873             :    * INHERIT_KEEP behavior in this case. */
    6874             :   tt_int_op(inherit, OP_NE, INHERIT_RES_KEEP);
    6875             : #else
    6876           1 :   if (inherit == INHERIT_RES_KEEP) {
    6877             :     /* Call this test "skipped", not "passed", since noinherit wasn't
    6878             :      * implemented. */
    6879           0 :     tt_skip();
    6880             :   }
    6881             : #endif /* !defined(NOINHERIT_CAN_FAIL) */
    6882             : 
    6883           1 :  done:
    6884           1 :   tor_munmap_anonymous(ptr, sz);
    6885           1 :   if (pipefd[0] >= 0) {
    6886           1 :     close(pipefd[0]);
    6887             :   }
    6888           1 :   if (pipefd[1] >= 0) {
    6889           0 :     close(pipefd[1]);
    6890             :   }
    6891             : #endif /* defined(_WIN32) */
    6892           1 : }
    6893             : 
    6894             : #ifndef COCCI
    6895             : #define UTIL_LEGACY(name)                                               \
    6896             :   { (#name), test_util_ ## name , 0, NULL, NULL }
    6897             : 
    6898             : #define UTIL_TEST(name, flags)                          \
    6899             :   { (#name), test_util_ ## name, flags, NULL, NULL }
    6900             : 
    6901             : #define COMPRESS(name, identifier)              \
    6902             :   { ("compress/" #name), test_util_compress, 0, &compress_setup,        \
    6903             :     (char*)(identifier) }
    6904             : 
    6905             : #define COMPRESS_CONCAT(name, identifier)                               \
    6906             :   { ("compress_concat/" #name), test_util_decompress_concatenated, 0,   \
    6907             :     &compress_setup,                                                    \
    6908             :     (char*)(identifier) }
    6909             : 
    6910             : #define COMPRESS_JUNK(name, identifier)                                 \
    6911             :   { ("compress_junk/" #name), test_util_decompress_junk, 0,             \
    6912             :     &compress_setup,                                                    \
    6913             :     (char*)(identifier) }
    6914             : 
    6915             : #define COMPRESS_DOS(name, identifier)                                  \
    6916             :   { ("compress_dos/" #name), test_util_decompress_dos, 0,               \
    6917             :     &compress_setup,                                                    \
    6918             :     (char*)(identifier) }
    6919             : 
    6920             : #ifdef _WIN32
    6921             : #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
    6922             : #else
    6923             : #define UTIL_TEST_WIN_ONLY(n, f) { (#n), NULL, TT_SKIP, NULL, NULL }
    6924             : #endif
    6925             : 
    6926             : #ifdef DISABLE_PWDB_TESTS
    6927             : #define UTIL_TEST_PWDB(n, f) { (#n), NULL, TT_SKIP, NULL, NULL }
    6928             : #else
    6929             : #define UTIL_TEST_PWDB(n, f) UTIL_TEST(n, (f))
    6930             : #endif
    6931             : #endif /* !defined(COCCI) */
    6932             : 
    6933             : struct testcase_t util_tests[] = {
    6934             :   UTIL_LEGACY(time),
    6935             :   UTIL_TEST(parse_http_time, 0),
    6936             :   UTIL_LEGACY(config_line),
    6937             :   UTIL_LEGACY(config_line_quotes),
    6938             :   UTIL_LEGACY(config_line_comment_character),
    6939             :   UTIL_LEGACY(config_line_escaped_content),
    6940             :   UTIL_LEGACY(config_line_crlf),
    6941             :   UTIL_TEST(config_line_partition, 0),
    6942             :   UTIL_TEST_PWDB(expand_filename, 0),
    6943             :   UTIL_LEGACY(escape_string_socks),
    6944             :   UTIL_LEGACY(string_is_key_value),
    6945             :   UTIL_LEGACY(strmisc),
    6946             :   UTIL_TEST(parse_integer, 0),
    6947             :   UTIL_LEGACY(pow2),
    6948             :   COMPRESS(zlib, "deflate"),
    6949             :   COMPRESS(gzip, "gzip"),
    6950             :   COMPRESS(lzma, "x-tor-lzma"),
    6951             :   COMPRESS(zstd, "x-zstd"),
    6952             :   COMPRESS(zstd_nostatic, "x-zstd:nostatic"),
    6953             :   COMPRESS(none, "identity"),
    6954             :   COMPRESS_CONCAT(zlib, "deflate"),
    6955             :   COMPRESS_CONCAT(gzip, "gzip"),
    6956             :   COMPRESS_CONCAT(lzma, "x-tor-lzma"),
    6957             :   COMPRESS_CONCAT(zstd, "x-zstd"),
    6958             :   COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"),
    6959             :   COMPRESS_CONCAT(none, "identity"),
    6960             :   COMPRESS_JUNK(zlib, "deflate"),
    6961             :   COMPRESS_JUNK(gzip, "gzip"),
    6962             :   COMPRESS_JUNK(lzma, "x-tor-lzma"),
    6963             :   COMPRESS_DOS(zlib, "deflate"),
    6964             :   COMPRESS_DOS(gzip, "gzip"),
    6965             :   COMPRESS_DOS(lzma, "x-tor-lzma"),
    6966             :   COMPRESS_DOS(zstd, "x-zstd"),
    6967             :   COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"),
    6968             :   UTIL_TEST(gzip_compression_bomb, TT_FORK),
    6969             :   UTIL_LEGACY(datadir),
    6970             :   UTIL_LEGACY(memarea),
    6971             :   UTIL_LEGACY(control_formats),
    6972             :   UTIL_LEGACY(mmap),
    6973             :   UTIL_TEST(sscanf, TT_FORK),
    6974             :   UTIL_LEGACY(format_time_interval),
    6975             :   UTIL_LEGACY(path_is_relative),
    6976             :   UTIL_LEGACY(strtok),
    6977             :   UTIL_LEGACY(di_ops),
    6978             :   UTIL_TEST(memcpy_iftrue_timei, 0),
    6979             :   UTIL_TEST(di_map, 0),
    6980             :   UTIL_TEST(round_to_next_multiple_of, 0),
    6981             :   UTIL_TEST(laplace, 0),
    6982             :   UTIL_TEST(clamp_double_to_int64, 0),
    6983             :   UTIL_TEST(find_str_at_start_of_line, 0),
    6984             :   UTIL_TEST(tor_strreplacechar, 0),
    6985             :   UTIL_TEST(string_is_C_identifier, 0),
    6986             :   UTIL_TEST(string_is_utf8, 0),
    6987             :   UTIL_TEST(asprintf, 0),
    6988             :   UTIL_TEST(listdir, 0),
    6989             :   UTIL_TEST(glob, 0),
    6990             :   UTIL_TEST(get_glob_opened_files, 0),
    6991             :   UTIL_TEST(parent_dir, 0),
    6992             :   UTIL_TEST(ftruncate, 0),
    6993             :   UTIL_TEST(nowrap_math, 0),
    6994             :   UTIL_TEST(num_cpus, 0),
    6995             :   UTIL_TEST_WIN_ONLY(load_win_lib, 0),
    6996             :   UTIL_TEST(format_hex_number, 0),
    6997             :   UTIL_TEST(format_dec_number, 0),
    6998             :   UTIL_TEST(n_bits_set, 0),
    6999             :   UTIL_TEST(eat_whitespace, 0),
    7000             :   UTIL_TEST(sl_new_from_text_lines, 0),
    7001             :   UTIL_TEST(envnames, 0),
    7002             :   UTIL_TEST(make_environment, 0),
    7003             :   UTIL_TEST(set_env_var_in_sl, 0),
    7004             :   UTIL_TEST(read_file_eof_tiny_limit, 0),
    7005             :   UTIL_TEST(read_file_eof_one_loop_a, 0),
    7006             :   UTIL_TEST(read_file_eof_one_loop_b, 0),
    7007             :   UTIL_TEST(read_file_eof_two_loops, 0),
    7008             :   UTIL_TEST(read_file_eof_two_loops_b, 0),
    7009             :   UTIL_TEST(read_file_eof_zero_bytes, 0),
    7010             :   UTIL_TEST(read_file_endlines, 0),
    7011             :   UTIL_TEST(write_chunks_to_file, 0),
    7012             :   UTIL_TEST(write_str_if_changed, 0),
    7013             :   UTIL_TEST(mathlog, 0),
    7014             :   UTIL_TEST(fraction, 0),
    7015             :   UTIL_TEST(weak_random, 0),
    7016             :   { "tor_isinf", test_tor_isinf, TT_FORK, NULL, NULL },
    7017             :   { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
    7018             :     (void*)"4" },
    7019             :   { "socket_ipv6", test_util_socket, TT_FORK,
    7020             :     &passthrough_setup, (void*)"6" },
    7021             :   { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
    7022             :     (void*)"0" },
    7023             :   { "socketpair_ersatz", test_util_socketpair, TT_FORK,
    7024             :     &passthrough_setup, (void*)"1" },
    7025             :   UTIL_TEST(max_mem, 0),
    7026             :   UTIL_TEST(hostname_validation, 0),
    7027             :   UTIL_TEST(dest_validation_edgecase, 0),
    7028             :   UTIL_TEST(ipv4_validation, 0),
    7029             :   UTIL_TEST(ipv6_validation, 0),
    7030             :   UTIL_TEST(writepid, 0),
    7031             :   UTIL_TEST(get_avail_disk_space, 0),
    7032             :   UTIL_TEST(touch_file, 0),
    7033             :   UTIL_TEST_PWDB(pwdb, TT_FORK),
    7034             :   UTIL_TEST(calloc_check, 0),
    7035             :   UTIL_TEST(monotonic_time, 0),
    7036             :   UTIL_TEST(monotonic_time_ratchet, TT_FORK),
    7037             :   UTIL_TEST(monotonic_time_zero, 0),
    7038             :   UTIL_TEST(monotonic_time_add_msec, 0),
    7039             :   UTIL_TEST(htonll, 0),
    7040             :   UTIL_TEST(get_unquoted_path, 0),
    7041             :   UTIL_TEST(map_anon, 0),
    7042             :   UTIL_TEST(map_anon_nofork, 0),
    7043             :   END_OF_TESTCASES
    7044             : };

Generated by: LCOV version 1.14