fix typos from #28614
[tor.git] / src / test / test_util.c
blob913c5e289dde159e8304697867606fe61fb3bbc7
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "orconfig.h"
7 #define COMPAT_PRIVATE
8 #define COMPAT_TIME_PRIVATE
9 #define CONTROL_PRIVATE
10 #define UTIL_PRIVATE
11 #define UTIL_MALLOC_PRIVATE
12 #define SOCKET_PRIVATE
13 #define PROCESS_WIN32_PRIVATE
14 #include "lib/testsupport/testsupport.h"
15 #include "core/or/or.h"
16 #include "lib/buf/buffers.h"
17 #include "app/config/config.h"
18 #include "feature/control/control.h"
19 #include "feature/client/transports.h"
20 #include "lib/crypt_ops/crypto_format.h"
21 #include "lib/crypt_ops/crypto_rand.h"
22 #include "lib/defs/time.h"
23 #include "test/test.h"
24 #include "lib/memarea/memarea.h"
25 #include "lib/process/waitpid.h"
26 #include "lib/process/process_win32.h"
27 #include "test/log_test_helpers.h"
28 #include "lib/compress/compress.h"
29 #include "lib/compress/compress_zstd.h"
30 #include "lib/encoding/keyval.h"
31 #include "lib/fdio/fdio.h"
32 #include "lib/fs/winlib.h"
33 #include "lib/process/env.h"
34 #include "lib/process/pidfile.h"
35 #include "lib/intmath/weakrng.h"
36 #include "lib/thread/numcpus.h"
37 #include "lib/math/fp.h"
38 #include "lib/math/laplace.h"
39 #include "lib/meminfo/meminfo.h"
40 #include "lib/time/tvdiff.h"
41 #include "lib/encoding/confline.h"
42 #include "lib/net/socketpair.h"
43 #include "lib/malloc/map_anon.h"
45 #ifdef HAVE_PWD_H
46 #include <pwd.h>
47 #endif
48 #ifdef HAVE_SYS_UTIME_H
49 #include <sys/utime.h>
50 #endif
51 #ifdef HAVE_UTIME_H
52 #include <utime.h>
53 #endif
54 #ifdef HAVE_SYS_STAT_H
55 #include <sys/stat.h>
56 #endif
57 #ifdef HAVE_FCNTL_H
58 #include <fcntl.h>
59 #endif
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63 #ifdef HAVE_SYS_MMAN_H
64 #include <sys/mman.h>
65 #endif
66 #ifdef HAVE_SYS_WAIT_H
67 #include <sys/wait.h>
68 #endif
70 #ifdef _WIN32
71 #include <tchar.h>
72 #endif
73 #include <math.h>
74 #include <ctype.h>
75 #include <float.h>
77 #define INFINITY_DBL ((double)INFINITY)
78 #define NAN_DBL ((double)NAN)
80 /** Test the tor_isinf() wrapper */
81 static void
82 test_tor_isinf(void *arg)
84 (void) arg;
86 tt_assert(tor_isinf(INFINITY_DBL));
88 tt_assert(!tor_isinf(NAN_DBL));
89 tt_assert(!tor_isinf(DBL_EPSILON));
90 tt_assert(!tor_isinf(DBL_MAX));
91 tt_assert(!tor_isinf(DBL_MIN));
93 tt_assert(!tor_isinf(0.0));
94 tt_assert(!tor_isinf(0.1));
95 tt_assert(!tor_isinf(3));
96 tt_assert(!tor_isinf(3.14));
98 done:
102 /* XXXX this is a minimal wrapper to make the unit tests compile with the
103 * changed tor_timegm interface. */
104 static time_t
105 tor_timegm_wrapper(const struct tm *tm)
107 time_t t;
108 if (tor_timegm(tm, &t) < 0)
109 return -1;
110 return t;
113 #define tor_timegm tor_timegm_wrapper
115 static void
116 test_util_read_until_eof_impl(const char *fname, size_t file_len,
117 size_t read_limit)
119 char *fifo_name = NULL;
120 char *test_str = NULL;
121 char *str = NULL;
122 size_t sz = 9999999;
123 int fd = -1;
124 int r;
126 fifo_name = tor_strdup(get_fname(fname));
127 test_str = tor_malloc(file_len);
128 crypto_rand(test_str, file_len);
130 r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
131 tt_int_op(r, OP_EQ, 0);
133 fd = open(fifo_name, O_RDONLY|O_BINARY);
134 tt_int_op(fd, OP_GE, 0);
135 str = read_file_to_str_until_eof(fd, read_limit, &sz);
136 tt_ptr_op(str, OP_NE, NULL);
138 if (read_limit < file_len)
139 tt_int_op(sz, OP_EQ, read_limit);
140 else
141 tt_int_op(sz, OP_EQ, file_len);
143 tt_mem_op(test_str, OP_EQ, str, sz);
144 tt_int_op(str[sz], OP_EQ, '\0');
146 done:
147 unlink(fifo_name);
148 tor_free(fifo_name);
149 tor_free(test_str);
150 tor_free(str);
151 if (fd >= 0)
152 close(fd);
155 static void
156 test_util_read_file_eof_tiny_limit(void *arg)
158 (void)arg;
159 // purposely set limit shorter than what we wrote to the FIFO to
160 // test the maximum, and that it puts the NUL in the right spot
162 test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
165 static void
166 test_util_read_file_eof_one_loop_a(void *arg)
168 (void)arg;
169 test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
172 static void
173 test_util_read_file_eof_one_loop_b(void *arg)
175 (void)arg;
176 test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
179 static void
180 test_util_read_file_eof_two_loops(void *arg)
182 (void)arg;
183 // write more than 1024 bytes to the FIFO to test two passes through
184 // the loop in the method; if the re-alloc size is changed this
185 // should be updated as well.
187 test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
190 static void
191 test_util_read_file_eof_two_loops_b(void *arg)
193 (void)arg;
195 test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
198 static void
199 test_util_read_file_eof_zero_bytes(void *arg)
201 (void)arg;
202 // zero-byte fifo
203 test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
206 /* Test the basic expected behaviour for write_chunks_to_file.
207 * NOTE: This will need to be updated if we ever change the tempfile location
208 * or extension */
209 static void
210 test_util_write_chunks_to_file(void *arg)
212 char *fname = NULL;
213 char *tempname = NULL;
214 char *str = NULL;
215 int r;
216 struct stat st;
218 /* These should be two different sizes to ensure the data is different
219 * between the data file and the temp file's 'known string' */
220 int temp_str_len = 1024;
221 int data_str_len = 512;
222 char *data_str = tor_malloc(data_str_len);
223 char *temp_str = tor_malloc(temp_str_len);
225 smartlist_t *chunks = smartlist_new();
226 sized_chunk_t c = {data_str, data_str_len/2};
227 sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
228 (void)arg;
230 crypto_rand(temp_str, temp_str_len);
231 crypto_rand(data_str, data_str_len);
233 // Ensure it can write multiple chunks
235 smartlist_add(chunks, &c);
236 smartlist_add(chunks, &c2);
239 * Check if it writes using a tempfile
241 fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
242 tor_asprintf(&tempname, "%s.tmp", fname);
244 // write a known string to a file where the tempfile will be
245 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
246 tt_int_op(r, OP_EQ, 0);
248 // call write_chunks_to_file
249 r = write_chunks_to_file(fname, chunks, 1, 0);
250 tt_int_op(r, OP_EQ, 0);
252 // assert the file has been written (expected size)
253 str = read_file_to_str(fname, RFTS_BIN, &st);
254 tt_assert(str != NULL);
255 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
256 tt_mem_op(data_str, OP_EQ, str, data_str_len);
257 tor_free(str);
259 // assert that the tempfile is removed (should not leave artifacts)
260 str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
261 tt_assert(str == NULL);
263 // Remove old testfile for second test
264 r = unlink(fname);
265 tt_int_op(r, OP_EQ, 0);
266 tor_free(fname);
267 tor_free(tempname);
270 * Check if it skips using a tempfile with flags
272 fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
273 tor_asprintf(&tempname, "%s.tmp", fname);
275 // write a known string to a file where the tempfile will be
276 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
277 tt_int_op(r, OP_EQ, 0);
279 // call write_chunks_to_file with no_tempfile = true
280 r = write_chunks_to_file(fname, chunks, 1, 1);
281 tt_int_op(r, OP_EQ, 0);
283 // assert the file has been written (expected size)
284 str = read_file_to_str(fname, RFTS_BIN, &st);
285 tt_assert(str != NULL);
286 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
287 tt_mem_op(data_str, OP_EQ, str, data_str_len);
288 tor_free(str);
290 // assert the tempfile still contains the known string
291 str = read_file_to_str(tempname, RFTS_BIN, &st);
292 tt_assert(str != NULL);
293 tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
294 tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
296 done:
297 unlink(fname);
298 unlink(tempname);
299 smartlist_free(chunks);
300 tor_free(fname);
301 tor_free(tempname);
302 tor_free(str);
303 tor_free(data_str);
304 tor_free(temp_str);
307 #define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
308 /** test the minimum set of struct tm fields needed for a unique epoch value
309 * this is also the set we use to test tor_timegm */
310 #define TM_EQUAL(a, b) \
311 TT_STMT_BEGIN \
312 _TFE(a, b, tm_year); \
313 _TFE(a, b, tm_mon ); \
314 _TFE(a, b, tm_mday); \
315 _TFE(a, b, tm_hour); \
316 _TFE(a, b, tm_min ); \
317 _TFE(a, b, tm_sec ); \
318 TT_STMT_END
320 static void
321 test_util_time(void *arg)
323 struct timeval start, end;
324 struct tm a_time, b_time;
325 char timestr[128];
326 time_t t_res;
327 int i;
328 struct timeval tv;
330 /* Test tv_udiff and tv_mdiff */
332 (void)arg;
333 start.tv_sec = 5;
334 start.tv_usec = 5000;
336 end.tv_sec = 5;
337 end.tv_usec = 5000;
339 tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
340 tt_int_op(0L,OP_EQ, tv_mdiff(&start, &end));
341 tt_int_op(0L,OP_EQ, tv_udiff(&end, &start));
342 tt_int_op(0L,OP_EQ, tv_mdiff(&end, &start));
344 end.tv_usec = 7000;
346 tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
347 tt_int_op(2L,OP_EQ, tv_mdiff(&start, &end));
348 tt_int_op(-2000L,OP_EQ, tv_udiff(&end, &start));
349 tt_int_op(-2L,OP_EQ, tv_mdiff(&end, &start));
351 end.tv_sec = 6;
353 tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
354 tt_int_op(1002L,OP_EQ, tv_mdiff(&start, &end));
355 tt_int_op(-1002000L,OP_EQ, tv_udiff(&end, &start));
356 tt_int_op(-1002L,OP_EQ, tv_mdiff(&end, &start));
358 end.tv_usec = 0;
360 tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
361 tt_int_op(995L,OP_EQ, tv_mdiff(&start, &end));
362 tt_int_op(-995000L,OP_EQ, tv_udiff(&end, &start));
363 tt_int_op(-995L,OP_EQ, tv_mdiff(&end, &start));
365 end.tv_sec = 4;
367 tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
368 tt_int_op(-1005L,OP_EQ, tv_mdiff(&start, &end));
369 tt_int_op(1005000L,OP_EQ, tv_udiff(&end, &start));
370 tt_int_op(1005L,OP_EQ, tv_mdiff(&end, &start));
372 /* Negative tv_sec values, these will break on platforms where tv_sec is
373 * unsigned */
375 end.tv_sec = -10;
377 tt_int_op(-15005000L,OP_EQ, tv_udiff(&start, &end));
378 tt_int_op(-15005L,OP_EQ, tv_mdiff(&start, &end));
379 tt_int_op(15005000L,OP_EQ, tv_udiff(&end, &start));
380 tt_int_op(15005L,OP_EQ, tv_mdiff(&end, &start));
382 start.tv_sec = -100;
384 tt_int_op(89995000L,OP_EQ, tv_udiff(&start, &end));
385 tt_int_op(89995L,OP_EQ, tv_mdiff(&start, &end));
386 tt_int_op(-89995000L,OP_EQ, tv_udiff(&end, &start));
387 tt_int_op(-89995L,OP_EQ, tv_mdiff(&end, &start));
389 /* Test that tv_usec values round away from zero when converted to msec */
390 start.tv_sec = 0;
391 start.tv_usec = 0;
392 end.tv_sec = 10;
393 end.tv_usec = 499;
395 tt_int_op(10000499L, OP_EQ, tv_udiff(&start, &end));
396 tt_int_op(10000L, OP_EQ, tv_mdiff(&start, &end));
397 tt_int_op(-10000499L, OP_EQ, tv_udiff(&end, &start));
398 tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
400 start.tv_sec = 0;
401 start.tv_usec = 0;
402 end.tv_sec = 10;
403 end.tv_usec = 500;
405 tt_int_op(10000500L, OP_EQ, tv_udiff(&start, &end));
406 tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
407 tt_int_op(-10000500L, OP_EQ, tv_udiff(&end, &start));
408 tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
410 start.tv_sec = 0;
411 start.tv_usec = 0;
412 end.tv_sec = 10;
413 end.tv_usec = 501;
415 tt_int_op(10000501L, OP_EQ, tv_udiff(&start, &end));
416 tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
417 tt_int_op(-10000501L, OP_EQ, tv_udiff(&end, &start));
418 tt_int_op(-10001L, OP_EQ, tv_mdiff(&end, &start));
420 /* Overflow conditions */
422 #ifdef _WIN32
423 /* Would you believe that tv_sec is a long on windows? Of course you would.*/
424 #define TV_SEC_MAX LONG_MAX
425 #define TV_SEC_MIN LONG_MIN
426 #else
427 /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
428 * Which means TIME_MAX is not actually the maximum value of tv_sec.
429 * But that's ok for the moment, because the code correctly performs 64-bit
430 * calculations internally, then catches the overflow. */
431 #define TV_SEC_MAX TIME_MAX
432 #define TV_SEC_MIN TIME_MIN
433 #endif /* defined(_WIN32) */
435 /* Assume tv_usec is an unsigned integer until proven otherwise */
436 #define TV_USEC_MAX UINT_MAX
438 /* Overflows in the result type */
440 /* All comparisons work */
441 start.tv_sec = 0;
442 start.tv_usec = 0;
443 end.tv_sec = LONG_MAX/1000 - 2;
444 end.tv_usec = 0;
446 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
447 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
448 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
449 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
451 start.tv_sec = 0;
452 start.tv_usec = 0;
453 end.tv_sec = LONG_MAX/1000000 - 1;
454 end.tv_usec = 0;
456 tt_int_op(end.tv_sec*1000000L, OP_EQ, tv_udiff(&start, &end));
457 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
458 tt_int_op(-end.tv_sec*1000000L, OP_EQ, tv_udiff(&end, &start));
459 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
461 /* No comparisons work */
462 start.tv_sec = 0;
463 start.tv_usec = 0;
464 end.tv_sec = LONG_MAX/1000 + 1;
465 end.tv_usec = 0;
467 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
468 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
469 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
470 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
472 start.tv_sec = 0;
473 start.tv_usec = 0;
474 end.tv_sec = LONG_MAX/1000000 + 1;
475 end.tv_usec = 0;
477 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
478 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
479 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
480 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
482 start.tv_sec = 0;
483 start.tv_usec = 0;
484 end.tv_sec = LONG_MAX/1000;
485 end.tv_usec = TOR_USEC_PER_SEC;
487 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
488 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
489 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
490 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
492 start.tv_sec = 0;
493 start.tv_usec = 0;
494 end.tv_sec = LONG_MAX/1000000;
495 end.tv_usec = TOR_USEC_PER_SEC;
497 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
498 tt_int_op((end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&start, &end));
499 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
500 tt_int_op(-(end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&end, &start));
502 /* Overflows on comparison to zero */
504 start.tv_sec = 0;
505 start.tv_usec = 0;
507 end.tv_sec = TV_SEC_MAX;
508 end.tv_usec = 0;
510 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
511 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
512 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
513 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
515 end.tv_sec = TV_SEC_MAX;
516 end.tv_usec = TOR_USEC_PER_SEC;
518 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
519 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
520 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
521 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
523 end.tv_sec = 0;
524 end.tv_usec = TV_USEC_MAX;
526 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
527 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
528 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
529 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
531 end.tv_sec = TV_SEC_MAX;
532 end.tv_usec = TV_USEC_MAX;
534 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
535 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
536 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
537 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
539 end.tv_sec = 0;
540 end.tv_usec = 0;
542 start.tv_sec = TV_SEC_MIN;
543 start.tv_usec = 0;
545 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
546 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
547 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
548 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
550 start.tv_sec = TV_SEC_MIN;
551 start.tv_usec = TOR_USEC_PER_SEC;
553 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
554 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
555 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
556 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
558 start.tv_sec = TV_SEC_MIN;
559 start.tv_usec = TV_USEC_MAX;
561 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
562 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
563 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
564 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
566 /* overflows on comparison to maxima / minima */
568 start.tv_sec = TV_SEC_MIN;
569 start.tv_usec = 0;
571 end.tv_sec = TV_SEC_MAX;
572 end.tv_usec = 0;
574 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
575 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
576 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
577 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
579 end.tv_sec = TV_SEC_MAX;
580 end.tv_usec = TOR_USEC_PER_SEC;
582 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
583 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
584 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
585 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
587 end.tv_sec = TV_SEC_MAX;
588 end.tv_usec = 0;
590 start.tv_sec = TV_SEC_MIN;
591 start.tv_usec = 0;
593 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
594 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
595 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
596 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
598 start.tv_sec = TV_SEC_MIN;
599 start.tv_usec = TOR_USEC_PER_SEC;
601 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
602 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
603 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
604 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
606 /* overflows on comparison to maxima / minima with extra usec */
608 start.tv_sec = TV_SEC_MIN;
609 start.tv_usec = TOR_USEC_PER_SEC;
611 end.tv_sec = TV_SEC_MAX;
612 end.tv_usec = 0;
614 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
615 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
616 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
617 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
619 end.tv_sec = TV_SEC_MAX;
620 end.tv_usec = TOR_USEC_PER_SEC;
622 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
623 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
624 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
625 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
627 end.tv_sec = TV_SEC_MAX;
628 end.tv_usec = TOR_USEC_PER_SEC;
630 start.tv_sec = TV_SEC_MIN;
631 start.tv_usec = 0;
633 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
634 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
635 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
636 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
638 start.tv_sec = TV_SEC_MIN;
639 start.tv_usec = TOR_USEC_PER_SEC;
641 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
642 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
643 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
644 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
646 /* Test tor_timegm & tor_gmtime_r */
648 /* The test values here are confirmed to be correct on a platform
649 * with a working timegm & gmtime_r. */
651 /* Start with known-zero a_time and b_time.
652 * This avoids passing uninitialised values to TM_EQUAL in a_time.
653 * Zeroing may not be needed for b_time, as long as tor_gmtime_r
654 * never reads the existing values in the structure.
655 * But we really don't want intermittently failing tests. */
656 memset(&a_time, 0, sizeof(struct tm));
657 memset(&b_time, 0, sizeof(struct tm));
659 a_time.tm_year = 2003-1900;
660 a_time.tm_mon = 7;
661 a_time.tm_mday = 30;
662 a_time.tm_hour = 6;
663 a_time.tm_min = 14;
664 a_time.tm_sec = 55;
665 t_res = 1062224095UL;
666 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
667 tor_gmtime_r(&t_res, &b_time);
668 TM_EQUAL(a_time, b_time);
670 a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
671 t_res = 1093846495UL;
672 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
673 tor_gmtime_r(&t_res, &b_time);
674 TM_EQUAL(a_time, b_time);
676 a_time.tm_mon = 1; /* Try a leap year, in feb. */
677 a_time.tm_mday = 10;
678 t_res = 1076393695UL;
679 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
680 tor_gmtime_r(&t_res, &b_time);
681 TM_EQUAL(a_time, b_time);
683 a_time.tm_mon = 0;
684 t_res = 1073715295UL;
685 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
686 tor_gmtime_r(&t_res, &b_time);
687 TM_EQUAL(a_time, b_time);
689 /* This value is in range with 32 bit and 64 bit time_t */
690 a_time.tm_year = 2037-1900;
691 t_res = 2115180895UL;
692 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
693 tor_gmtime_r(&t_res, &b_time);
694 TM_EQUAL(a_time, b_time);
696 /* This value is out of range with 32 bit time_t, but in range for 64 bit
697 * time_t */
698 a_time.tm_year = 2039-1900;
699 #if SIZEOF_TIME_T == 4
700 setup_full_capture_of_logs(LOG_WARN);
701 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
702 expect_single_log_msg_containing("Result does not fit in tor_timegm");
703 teardown_capture_of_logs();
704 #elif SIZEOF_TIME_T == 8
705 t_res = 2178252895UL;
706 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
707 tor_gmtime_r(&t_res, &b_time);
708 TM_EQUAL(a_time, b_time);
709 #endif /* SIZEOF_TIME_T == 4 || ... */
711 /* Test tor_timegm out of range */
713 /* The below tests will all cause a BUG message, so we capture, suppress,
714 * and detect. */
715 #define CAPTURE() do { \
716 setup_full_capture_of_logs(LOG_WARN); \
717 } while (0)
718 #define CHECK_TIMEGM_WARNING(msg) do { \
719 expect_single_log_msg_containing(msg); \
720 teardown_capture_of_logs(); \
721 } while (0)
722 #define CHECK_POSSIBLE_EINVAL() do { \
723 if (mock_saved_log_n_entries()) { \
724 expect_single_log_msg_containing("Invalid argument"); \
726 teardown_capture_of_logs(); \
727 } while (0)
729 #define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
730 CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")
732 /* year */
734 /* Wrong year < 1970 */
735 a_time.tm_year = 1969-1900;
736 CAPTURE();
737 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
738 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
740 a_time.tm_year = -1-1900;
741 CAPTURE();
742 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
743 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
745 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
746 a_time.tm_year = -1*(1 << 16);
747 CAPTURE();
748 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
749 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
751 /* one of the smallest tm_year values my 64 bit system supports:
752 * t_res = -9223372036854775LL without clamping */
753 a_time.tm_year = -292275055-1900;
754 CAPTURE();
755 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
756 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
758 a_time.tm_year = INT32_MIN;
759 CAPTURE();
760 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
761 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
762 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
764 #if SIZEOF_INT == 8
765 a_time.tm_year = -1*(1 << 48);
766 CAPTURE();
767 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
768 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
770 /* while unlikely, the system's gmtime(_r) could return
771 * a "correct" retrospective gregorian negative year value,
772 * which I'm pretty sure is:
773 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
774 * 730485 is the number of days in two millennia, including leap days */
775 a_time.tm_year = -292277022657-1900;
776 CAPTURE();
777 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
778 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
780 a_time.tm_year = INT64_MIN;
781 CAPTURE();
782 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
783 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
784 #endif /* SIZEOF_INT == 8 */
786 /* Wrong year >= INT32_MAX - 1900 */
787 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
788 a_time.tm_year = INT32_MAX-1900;
789 CAPTURE();
790 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
791 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
793 a_time.tm_year = INT32_MAX;
794 CAPTURE();
795 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
796 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
797 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
799 #if SIZEOF_INT == 8
800 /* one of the largest tm_year values my 64 bit system supports */
801 a_time.tm_year = 292278994-1900;
802 CAPTURE();
803 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
804 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
806 /* while unlikely, the system's gmtime(_r) could return
807 * a "correct" proleptic gregorian year value,
808 * which I'm pretty sure is:
809 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
810 * 730485 is the number of days in two millennia, including leap days */
811 a_time.tm_year = 292277026596-1900;
812 CAPTURE();
813 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
814 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
816 a_time.tm_year = INT64_MAX-1900;
817 CAPTURE();
818 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
819 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
821 a_time.tm_year = INT64_MAX;
822 CAPTURE();
823 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
824 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
825 #endif /* SIZEOF_INT == 8 */
827 /* month */
828 a_time.tm_year = 2007-1900; /* restore valid year */
830 a_time.tm_mon = 12; /* Wrong month, it's 0-based */
831 CAPTURE();
832 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
833 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
835 a_time.tm_mon = -1; /* Wrong month */
836 CAPTURE();
837 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
838 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
840 /* day */
841 a_time.tm_mon = 6; /* Try July */
842 a_time.tm_mday = 32; /* Wrong day */
843 CAPTURE();
844 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
845 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
847 a_time.tm_mon = 5; /* Try June */
848 a_time.tm_mday = 31; /* Wrong day */
849 CAPTURE();
850 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
851 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
853 a_time.tm_year = 2008-1900; /* Try a leap year */
854 a_time.tm_mon = 1; /* in feb. */
855 a_time.tm_mday = 30; /* Wrong day */
856 CAPTURE();
857 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
858 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
860 a_time.tm_year = 2011-1900; /* Try a non-leap year */
861 a_time.tm_mon = 1; /* in feb. */
862 a_time.tm_mday = 29; /* Wrong day */
863 CAPTURE();
864 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
865 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
867 a_time.tm_mday = 0; /* Wrong day, it's 1-based (to be different) */
868 CAPTURE();
869 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
870 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
872 /* hour */
873 a_time.tm_mday = 3; /* restore valid month day */
875 a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
876 CAPTURE();
877 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
878 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
880 a_time.tm_hour = -1; /* Wrong hour */
881 CAPTURE();
882 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
883 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
885 /* minute */
886 a_time.tm_hour = 22; /* restore valid hour */
888 a_time.tm_min = 60; /* Wrong minute, it's 0-based */
889 CAPTURE();
890 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
891 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
893 a_time.tm_min = -1; /* Wrong minute */
894 CAPTURE();
895 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
896 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
898 /* second */
899 a_time.tm_min = 37; /* restore valid minute */
901 a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
902 CAPTURE();
903 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
904 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
906 a_time.tm_sec = -1; /* Wrong second */
907 CAPTURE();
908 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
909 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
911 /* Test tor_gmtime_r out of range */
913 /* time_t < 0 yields a year clamped to 1 or 1970,
914 * depending on whether the implementation of the system gmtime(_r)
915 * sets struct tm (1) or not (1970) */
916 t_res = -1;
917 tor_gmtime_r(&t_res, &b_time);
918 tt_assert(b_time.tm_year == (1970-1900) ||
919 b_time.tm_year == (1969-1900));
921 if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
922 t_res = -1*(1 << 30);
923 CAPTURE();
924 tor_gmtime_r(&t_res, &b_time);
925 CHECK_POSSIBLE_EINVAL();
926 tt_assert(b_time.tm_year == (1970-1900) ||
927 b_time.tm_year == (1935-1900));
929 t_res = INT32_MIN;
930 CAPTURE();
931 tor_gmtime_r(&t_res, &b_time);
932 CHECK_POSSIBLE_EINVAL();
933 tt_assert(b_time.tm_year == (1970-1900) ||
934 b_time.tm_year == (1901-1900));
937 #if SIZEOF_TIME_T == 8
939 /* one of the smallest tm_year values my 64 bit system supports:
940 * b_time.tm_year == (-292275055LL-1900LL) without clamping */
941 t_res = -9223372036854775LL;
942 CAPTURE();
943 tor_gmtime_r(&t_res, &b_time);
944 CHECK_POSSIBLE_EINVAL();
945 tt_assert(b_time.tm_year == (1970-1900) ||
946 b_time.tm_year == (1-1900));
948 /* while unlikely, the system's gmtime(_r) could return
949 * a "correct" retrospective gregorian negative year value,
950 * which I'm pretty sure is:
951 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
952 * 730485 is the number of days in two millennia, including leap days
953 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
954 t_res = INT64_MIN;
955 CAPTURE();
956 tor_gmtime_r(&t_res, &b_time);
957 if (! (b_time.tm_year == (1970-1900) ||
958 b_time.tm_year == (1-1900))) {
959 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
961 if (b_time.tm_year != 1970-1900) {
962 CHECK_TIMEGM_WARNING("Rounding up to ");
963 } else {
964 teardown_capture_of_logs();
968 /* As above, but with localtime. */
969 t_res = -9223372036854775LL;
970 CAPTURE();
971 tor_localtime_r(&t_res, &b_time);
972 CHECK_POSSIBLE_EINVAL();
973 tt_assert(b_time.tm_year == (1970-1900) ||
974 b_time.tm_year == (1-1900));
976 /* while unlikely, the system's gmtime(_r) could return
977 * a "correct" retrospective gregorian negative year value,
978 * which I'm pretty sure is:
979 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
980 * 730485 is the number of days in two millennia, including leap days
981 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
982 t_res = INT64_MIN;
983 CAPTURE();
984 tor_localtime_r(&t_res, &b_time);
985 if (! (b_time.tm_year == (1970-1900) ||
986 b_time.tm_year == (1-1900))) {
987 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
989 if (b_time.tm_year != 1970-1900) {
990 CHECK_TIMEGM_WARNING("Rounding up to ");
991 } else {
992 teardown_capture_of_logs();
995 #endif /* SIZEOF_TIME_T == 8 */
997 /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
998 * depending on whether the implementation of the system gmtime(_r)
999 * sets struct tm (9999) or not (2037) */
1000 #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
1002 t_res = 3*(1 << 29);
1003 tor_gmtime_r(&t_res, &b_time);
1004 tt_assert(b_time.tm_year == (2021-1900));
1006 t_res = INT32_MAX;
1007 tor_gmtime_r(&t_res, &b_time);
1008 tt_assert(b_time.tm_year == (2037-1900) ||
1009 b_time.tm_year == (2038-1900));
1012 /* as above but with localtime. */
1013 t_res = 3*(1 << 29);
1014 tor_localtime_r(&t_res, &b_time);
1015 tt_assert(b_time.tm_year == (2021-1900));
1017 t_res = INT32_MAX;
1018 tor_localtime_r(&t_res, &b_time);
1019 tt_assert(b_time.tm_year == (2037-1900) ||
1020 b_time.tm_year == (2038-1900));
1022 #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */
1024 #if SIZEOF_TIME_T == 8
1026 /* one of the largest tm_year values my 64 bit system supports:
1027 * b_time.tm_year == (292278994L-1900L) without clamping */
1028 t_res = 9223372036854775LL;
1029 CAPTURE();
1030 tor_gmtime_r(&t_res, &b_time);
1031 CHECK_POSSIBLE_EINVAL();
1032 tt_assert(b_time.tm_year == (2037-1900) ||
1033 b_time.tm_year == (9999-1900));
1035 /* while unlikely, the system's gmtime(_r) could return
1036 * a "correct" proleptic gregorian year value,
1037 * which I'm pretty sure is:
1038 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1039 * 730485 is the number of days in two millennia, including leap days
1040 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1041 t_res = INT64_MAX;
1042 CAPTURE();
1043 tor_gmtime_r(&t_res, &b_time);
1044 CHECK_TIMEGM_WARNING("Rounding down to ");
1046 tt_assert(b_time.tm_year == (2037-1900) ||
1047 b_time.tm_year == (9999-1900));
1050 /* As above but with localtime. */
1051 t_res = 9223372036854775LL;
1052 CAPTURE();
1053 tor_localtime_r(&t_res, &b_time);
1054 CHECK_POSSIBLE_EINVAL();
1055 tt_assert(b_time.tm_year == (2037-1900) ||
1056 b_time.tm_year == (9999-1900));
1058 /* while unlikely, the system's gmtime(_r) could return
1059 * a "correct" proleptic gregorian year value,
1060 * which I'm pretty sure is:
1061 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1062 * 730485 is the number of days in two millennia, including leap days
1063 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1064 t_res = INT64_MAX;
1065 CAPTURE();
1066 tor_localtime_r(&t_res, &b_time);
1067 CHECK_TIMEGM_WARNING("Rounding down to ");
1069 tt_assert(b_time.tm_year == (2037-1900) ||
1070 b_time.tm_year == (9999-1900));
1072 #endif /* SIZEOF_TIME_T == 8 */
1074 /* Test {format,parse}_rfc1123_time */
1076 format_rfc1123_time(timestr, 0);
1077 tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
1078 format_rfc1123_time(timestr, (time_t)1091580502UL);
1079 tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
1081 t_res = 0;
1082 i = parse_rfc1123_time(timestr, &t_res);
1083 tt_int_op(0,OP_EQ, i);
1084 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1086 /* This value is in range with 32 bit and 64 bit time_t */
1087 format_rfc1123_time(timestr, (time_t)2080000000UL);
1088 tt_str_op("Fri, 30 Nov 2035 01:46:40 GMT",OP_EQ, timestr);
1090 t_res = 0;
1091 i = parse_rfc1123_time(timestr, &t_res);
1092 tt_int_op(0,OP_EQ, i);
1093 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1095 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1096 * time_t */
1097 CAPTURE();
1098 format_rfc1123_time(timestr, (time_t)2150000000UL);
1099 CHECK_POSSIBLE_EINVAL();
1101 #if SIZEOF_TIME_T == 4
1102 #if 0
1103 /* Wrapping around will have made it this. */
1104 /* On windows, at least, this is clipped to 1 Jan 1970. ??? */
1105 tt_str_op("Sat, 11 Jan 1902 23:45:04 GMT",OP_EQ, timestr);
1106 #endif
1107 /* Make sure that the right date doesn't parse. */
1108 strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr));
1110 t_res = 0;
1111 CAPTURE();
1112 i = parse_rfc1123_time(timestr, &t_res);
1113 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1114 tt_int_op(-1,OP_EQ, i);
1115 #elif SIZEOF_TIME_T == 8
1116 tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr);
1118 t_res = 0;
1119 i = parse_rfc1123_time(timestr, &t_res);
1120 tt_int_op(0,OP_EQ, i);
1121 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1122 #endif /* SIZEOF_TIME_T == 4 || ... */
1124 /* The timezone doesn't matter */
1125 t_res = 0;
1126 tt_int_op(0,OP_EQ,
1127 parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
1128 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1129 tt_int_op(-1,OP_EQ,
1130 parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
1131 tt_int_op(-1,OP_EQ,
1132 parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
1133 tt_int_op(-1,OP_EQ,
1134 parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
1135 tt_int_op(-1,OP_EQ,
1136 parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
1137 tt_int_op(-1,OP_EQ,
1138 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
1139 tt_int_op(-1,OP_EQ,
1140 parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
1141 tt_int_op(-1,OP_EQ,
1142 parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
1143 tt_int_op(-1,OP_EQ,
1144 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
1145 tt_int_op(-1,OP_EQ,
1146 parse_rfc1123_time("Wed, 30 Mar 1900 23:59:59 GMT", &t_res));
1148 /* Leap year. */
1149 tt_int_op(-1,OP_EQ,
1150 parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
1151 tt_int_op(0,OP_EQ,
1152 parse_rfc1123_time("Wed, 29 Feb 2012 16:00:00 GMT", &t_res));
1154 /* Leap second plus one */
1155 tt_int_op(-1,OP_EQ,
1156 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
1158 /* Test parse_iso_time */
1160 t_res = 0;
1161 i = parse_iso_time("", &t_res);
1162 tt_int_op(-1,OP_EQ, i);
1163 t_res = 0;
1164 i = parse_iso_time("2004-08-32 00:48:22", &t_res);
1165 tt_int_op(-1,OP_EQ, i);
1166 t_res = 0;
1167 i = parse_iso_time("1969-08-03 00:48:22", &t_res);
1168 tt_int_op(-1,OP_EQ, i);
1170 t_res = 0;
1171 i = parse_iso_time("2004-08-04 00:48:22", &t_res);
1172 tt_int_op(0,OP_EQ, i);
1173 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1174 t_res = 0;
1175 i = parse_iso_time("2004-8-4 0:48:22", &t_res);
1176 tt_int_op(0,OP_EQ, i);
1177 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1179 /* This value is in range with 32 bit and 64 bit time_t */
1180 t_res = 0;
1181 i = parse_iso_time("2035-11-30 01:46:40", &t_res);
1182 tt_int_op(0,OP_EQ, i);
1183 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1185 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1186 * time_t */
1187 t_res = 0;
1188 #if SIZEOF_TIME_T == 4
1189 CAPTURE();
1190 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1191 tt_int_op(-1,OP_EQ, i);
1192 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1193 #elif SIZEOF_TIME_T == 8
1194 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1195 tt_int_op(0,OP_EQ, i);
1196 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1197 #endif /* SIZEOF_TIME_T == 4 || ... */
1199 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
1200 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
1201 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
1202 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
1203 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
1204 tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
1205 tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
1206 tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
1207 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
1208 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
1209 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
1211 /* but... that _is_ acceptable if we aren't being strict. */
1212 t_res = 0;
1213 i = parse_iso_time_("2004-08-04 00:48:22XYZ", &t_res, 0, 0);
1214 tt_int_op(0,OP_EQ, i);
1215 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1217 /* try nospace variant. */
1218 t_res = 0;
1219 i = parse_iso_time_nospace("2004-08-04T00:48:22", &t_res);
1220 tt_int_op(0,OP_EQ, i);
1221 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1223 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04T00:48:22", &t_res));
1224 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04 00:48:22", &t_res));
1225 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04x00:48:22", &t_res));
1226 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04x00:48:22", &t_res));
1228 /* Test tor_gettimeofday */
1230 end.tv_sec = 4;
1231 end.tv_usec = 999990;
1232 start.tv_sec = 1;
1233 start.tv_usec = 500;
1235 tor_gettimeofday(&start);
1236 /* now make sure time works. */
1237 tor_gettimeofday(&end);
1238 /* We might've timewarped a little. */
1239 tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
1241 /* Test format_iso_time */
1243 tv.tv_sec = (time_t)1326296338UL;
1244 tv.tv_usec = 3060;
1245 format_iso_time(timestr, (time_t)tv.tv_sec);
1246 tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
1247 /* The output of format_local_iso_time will vary by timezone, and setting
1248 our timezone for testing purposes would be a nontrivial flaky pain.
1249 Skip this test for now.
1250 format_local_iso_time(timestr, tv.tv_sec);
1251 test_streq("2012-01-11 10:38:58", timestr);
1253 format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
1254 tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
1255 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
1256 format_iso_time_nospace_usec(timestr, &tv);
1257 tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
1258 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
1260 tv.tv_usec = 0;
1261 /* This value is in range with 32 bit and 64 bit time_t */
1262 tv.tv_sec = (time_t)2080000000UL;
1263 format_iso_time(timestr, (time_t)tv.tv_sec);
1264 tt_str_op("2035-11-30 01:46:40",OP_EQ, timestr);
1266 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1267 * time_t */
1268 tv.tv_sec = (time_t)2150000000UL;
1269 CAPTURE();
1270 format_iso_time(timestr, (time_t)tv.tv_sec);
1271 CHECK_POSSIBLE_EINVAL();
1272 #if SIZEOF_TIME_T == 4
1273 /* format_iso_time should indicate failure on overflow, but it doesn't yet.
1274 * Hopefully #18480 will improve the failure semantics in this case.
1275 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1277 #elif SIZEOF_TIME_T == 8
1278 #ifndef _WIN32
1279 /* This SHOULD work on windows too; see bug #18665 */
1280 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1281 #endif
1282 #endif /* SIZEOF_TIME_T == 4 || ... */
1284 #undef CAPTURE
1285 #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE
1286 #undef CHECK_POSSIBLE_EINVAL
1288 done:
1289 teardown_capture_of_logs();
1292 static void
1293 test_util_parse_http_time(void *arg)
1295 struct tm a_time;
1296 char b[ISO_TIME_LEN+1];
1297 (void)arg;
1299 #define T(s) do { \
1300 format_iso_time(b, tor_timegm(&a_time)); \
1301 tt_str_op(b, OP_EQ, (s)); \
1302 b[0]='\0'; \
1303 } while (0)
1305 /* Test parse_http_time */
1307 tt_int_op(-1,OP_EQ,
1308 parse_http_time("", &a_time));
1309 tt_int_op(-1,OP_EQ,
1310 parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
1311 tt_int_op(-1,OP_EQ,
1312 parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
1313 tt_int_op(-1,OP_EQ,
1314 parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
1315 tt_int_op(-1,OP_EQ,
1316 parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
1317 tt_int_op(-1,OP_EQ,
1318 parse_http_time("Sunday, August the third", &a_time));
1319 tt_int_op(-1,OP_EQ,
1320 parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
1322 tt_int_op(0,OP_EQ,
1323 parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
1324 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1325 T("1994-08-04 00:48:22");
1326 tt_int_op(0,OP_EQ,
1327 parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
1328 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1329 T("1994-08-04 00:48:22");
1330 tt_int_op(0,OP_EQ,
1331 parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
1332 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1333 T("1994-08-04 00:48:22");
1334 tt_int_op(0,OP_EQ,
1335 parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
1336 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1337 T("1994-08-04 00:48:22");
1338 tt_int_op(0,OP_EQ,
1339 parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
1340 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1341 T("1994-08-04 00:48:22");
1342 tt_int_op(0,OP_EQ,
1343 parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
1344 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1345 T("1994-08-04 00:48:22");
1346 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
1347 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1348 T("1994-08-04 00:48:22");
1349 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
1350 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1351 T("1994-08-04 00:48:22");
1352 tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
1353 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1354 T("1994-08-04 00:48:22");
1355 tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
1356 tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
1357 T("2012-01-01 00:00:00");
1358 tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
1359 tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
1360 T("2012-12-31 00:00:00");
1362 /* This value is in range with 32 bit and 64 bit time_t */
1363 tt_int_op(0,OP_EQ,parse_http_time("Fri, 30 Nov 2035 01:46:40 GMT", &a_time));
1364 tt_int_op((time_t)2080000000UL,OP_EQ, tor_timegm(&a_time));
1365 T("2035-11-30 01:46:40");
1367 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1368 * time_t */
1369 #if SIZEOF_TIME_T == 4
1370 /* parse_http_time should indicate failure on overflow, but it doesn't yet.
1371 * Hopefully #18480 will improve the failure semantics in this case. */
1372 setup_full_capture_of_logs(LOG_WARN);
1373 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1374 tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time));
1375 expect_single_log_msg_containing("does not fit in tor_timegm");
1376 teardown_capture_of_logs();
1377 #elif SIZEOF_TIME_T == 8
1378 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1379 tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time));
1380 T("2038-02-17 06:13:20");
1381 #endif /* SIZEOF_TIME_T == 4 || ... */
1383 tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
1384 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
1385 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
1386 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
1387 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
1388 tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
1389 tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
1390 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
1392 #undef T
1393 done:
1394 teardown_capture_of_logs();
1397 static void
1398 test_util_config_line(void *arg)
1400 char buf[1024];
1401 char *k=NULL, *v=NULL;
1402 const char *str;
1404 /* Test parse_config_line_from_str */
1405 (void)arg;
1406 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
1407 "k2\n"
1408 "k3 \n" "\n" " \n" "#comment\n"
1409 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
1410 "kseven \"a quoted 'string\"\n"
1411 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
1412 "k9 a line that\\\n spans two lines.\n\n"
1413 "k10 more than\\\n one contin\\\nuation\n"
1414 "k11 \\\ncontinuation at the start\n"
1415 "k12 line with a\\\n#comment\n embedded\n"
1416 "k13\\\ncontinuation at the very start\n"
1417 "k14 a line that has a comment and # ends with a slash \\\n"
1418 "k15 this should be the next new line\n"
1419 "k16 a line that has a comment and # ends without a slash \n"
1420 "k17 this should be the next new line\n"
1421 , sizeof(buf));
1422 str = buf;
1424 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1425 tt_str_op(k,OP_EQ, "k");
1426 tt_str_op(v,OP_EQ, "v");
1427 tor_free(k); tor_free(v);
1428 tt_assert(!strcmpstart(str, "key value with"));
1430 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1431 tt_str_op(k,OP_EQ, "key");
1432 tt_str_op(v,OP_EQ, "value with spaces");
1433 tor_free(k); tor_free(v);
1434 tt_assert(!strcmpstart(str, "keykey"));
1436 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1437 tt_str_op(k,OP_EQ, "keykey");
1438 tt_str_op(v,OP_EQ, "val");
1439 tor_free(k); tor_free(v);
1440 tt_assert(!strcmpstart(str, "k2\n"));
1442 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1443 tt_str_op(k,OP_EQ, "k2");
1444 tt_str_op(v,OP_EQ, "");
1445 tor_free(k); tor_free(v);
1446 tt_assert(!strcmpstart(str, "k3 \n"));
1448 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1449 tt_str_op(k,OP_EQ, "k3");
1450 tt_str_op(v,OP_EQ, "");
1451 tor_free(k); tor_free(v);
1452 tt_assert(!strcmpstart(str, "#comment"));
1454 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1455 tt_str_op(k,OP_EQ, "k4");
1456 tt_str_op(v,OP_EQ, "");
1457 tor_free(k); tor_free(v);
1458 tt_assert(!strcmpstart(str, "k5#abc"));
1460 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1461 tt_str_op(k,OP_EQ, "k5");
1462 tt_str_op(v,OP_EQ, "");
1463 tor_free(k); tor_free(v);
1464 tt_assert(!strcmpstart(str, "k6"));
1466 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1467 tt_str_op(k,OP_EQ, "k6");
1468 tt_str_op(v,OP_EQ, "val");
1469 tor_free(k); tor_free(v);
1470 tt_assert(!strcmpstart(str, "kseven"));
1472 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1473 tt_str_op(k,OP_EQ, "kseven");
1474 tt_str_op(v,OP_EQ, "a quoted \'string");
1475 tor_free(k); tor_free(v);
1476 tt_assert(!strcmpstart(str, "k8 "));
1478 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1479 tt_str_op(k,OP_EQ, "k8");
1480 tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
1481 tor_free(k); tor_free(v);
1483 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1484 tt_str_op(k,OP_EQ, "k9");
1485 tt_str_op(v,OP_EQ, "a line that spans two lines.");
1486 tor_free(k); tor_free(v);
1488 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1489 tt_str_op(k,OP_EQ, "k10");
1490 tt_str_op(v,OP_EQ, "more than one continuation");
1491 tor_free(k); tor_free(v);
1493 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1494 tt_str_op(k,OP_EQ, "k11");
1495 tt_str_op(v,OP_EQ, "continuation at the start");
1496 tor_free(k); tor_free(v);
1498 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1499 tt_str_op(k,OP_EQ, "k12");
1500 tt_str_op(v,OP_EQ, "line with a embedded");
1501 tor_free(k); tor_free(v);
1503 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1504 tt_str_op(k,OP_EQ, "k13");
1505 tt_str_op(v,OP_EQ, "continuation at the very start");
1506 tor_free(k); tor_free(v);
1508 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1509 tt_str_op(k,OP_EQ, "k14");
1510 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1511 tor_free(k); tor_free(v);
1513 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1514 tt_str_op(k,OP_EQ, "k15");
1515 tt_str_op(v,OP_EQ, "this should be the next new line");
1516 tor_free(k); tor_free(v);
1518 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1519 tt_str_op(k,OP_EQ, "k16");
1520 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1521 tor_free(k); tor_free(v);
1523 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1524 tt_str_op(k,OP_EQ, "k17");
1525 tt_str_op(v,OP_EQ, "this should be the next new line");
1526 tor_free(k); tor_free(v);
1528 tt_str_op(str,OP_EQ, "");
1530 done:
1531 tor_free(k);
1532 tor_free(v);
1535 static void
1536 test_util_config_line_quotes(void *arg)
1538 char buf1[1024];
1539 char buf2[128];
1540 char buf3[128];
1541 char buf4[128];
1542 char *k=NULL, *v=NULL;
1543 const char *str;
1545 /* Test parse_config_line_from_str */
1546 (void)arg;
1547 strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
1548 "kTrailingGarbage \"quoted value\"trailing garbage\n"
1549 , sizeof(buf1));
1550 strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
1551 , sizeof(buf2));
1552 strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
1553 , sizeof(buf3));
1554 strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
1555 , sizeof(buf4));
1556 str = buf1;
1558 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1559 tt_str_op(k,OP_EQ, "kTrailingSpace");
1560 tt_str_op(v,OP_EQ, "quoted value");
1561 tor_free(k); tor_free(v);
1563 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1564 tt_ptr_op(str,OP_EQ, NULL);
1565 tor_free(k); tor_free(v);
1567 str = buf2;
1569 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1570 tt_ptr_op(str,OP_EQ, NULL);
1571 tor_free(k); tor_free(v);
1573 str = buf3;
1575 const char *err = NULL;
1576 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1577 tt_ptr_op(str,OP_EQ, NULL);
1578 tor_free(k); tor_free(v);
1579 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1581 str = buf4;
1583 err = NULL;
1584 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1585 tt_ptr_op(str,OP_EQ, NULL);
1586 tor_free(k); tor_free(v);
1587 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1589 done:
1590 tor_free(k);
1591 tor_free(v);
1594 static void
1595 test_util_config_line_comment_character(void *arg)
1597 char buf[1024];
1598 char *k=NULL, *v=NULL;
1599 const char *str;
1601 /* Test parse_config_line_from_str */
1602 (void)arg;
1603 strlcpy(buf, "k1 \"# in quotes\"\n"
1604 "k2 some value # some comment\n"
1605 "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
1606 , sizeof(buf));
1607 str = buf;
1609 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1610 tt_str_op(k,OP_EQ, "k1");
1611 tt_str_op(v,OP_EQ, "# in quotes");
1612 tor_free(k); tor_free(v);
1614 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1615 tt_str_op(k,OP_EQ, "k2");
1616 tt_str_op(v,OP_EQ, "some value");
1617 tor_free(k); tor_free(v);
1619 tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
1621 #if 0
1622 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1623 test_streq(k, "k3");
1624 test_streq(v, "/home/user/myTorNetwork#2");
1625 tor_free(k); tor_free(v);
1627 test_streq(str, "");
1628 #endif /* 0 */
1630 done:
1631 tor_free(k);
1632 tor_free(v);
1635 static void
1636 test_util_config_line_escaped_content(void *arg)
1638 char buf1[1024];
1639 char buf2[128];
1640 char buf3[128];
1641 char buf4[128];
1642 char buf5[128];
1643 char buf6[128];
1644 char *k=NULL, *v=NULL;
1645 const char *str;
1647 /* Test parse_config_line_from_str */
1648 (void)arg;
1649 strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
1650 "HexadecimalUpper \"\\x2A\"\n"
1651 "HexadecimalUpperX \"\\X2A\"\n"
1652 "Octal \"\\52\"\n"
1653 "Newline \"\\n\"\n"
1654 "Tab \"\\t\"\n"
1655 "CarriageReturn \"\\r\"\n"
1656 "DoubleQuote \"\\\"\"\n"
1657 "SimpleQuote \"\\'\"\n"
1658 "Backslash \"\\\\\"\n"
1659 "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
1660 , sizeof(buf1));
1662 strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
1663 , sizeof(buf2));
1665 strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
1666 , sizeof(buf3));
1668 strlcpy(buf4, "BrokenOctal \"\\8\"\n"
1669 , sizeof(buf4));
1671 strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
1672 , sizeof(buf5));
1674 strlcpy(buf6, "BrokenEscape \"\\"
1675 , sizeof(buf6));
1677 str = buf1;
1679 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1680 tt_str_op(k,OP_EQ, "HexadecimalLower");
1681 tt_str_op(v,OP_EQ, "*");
1682 tor_free(k); tor_free(v);
1684 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1685 tt_str_op(k,OP_EQ, "HexadecimalUpper");
1686 tt_str_op(v,OP_EQ, "*");
1687 tor_free(k); tor_free(v);
1689 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1690 tt_str_op(k,OP_EQ, "HexadecimalUpperX");
1691 tt_str_op(v,OP_EQ, "*");
1692 tor_free(k); tor_free(v);
1694 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1695 tt_str_op(k,OP_EQ, "Octal");
1696 tt_str_op(v,OP_EQ, "*");
1697 tor_free(k); tor_free(v);
1699 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1700 tt_str_op(k,OP_EQ, "Newline");
1701 tt_str_op(v,OP_EQ, "\n");
1702 tor_free(k); tor_free(v);
1704 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1705 tt_str_op(k,OP_EQ, "Tab");
1706 tt_str_op(v,OP_EQ, "\t");
1707 tor_free(k); tor_free(v);
1709 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1710 tt_str_op(k,OP_EQ, "CarriageReturn");
1711 tt_str_op(v,OP_EQ, "\r");
1712 tor_free(k); tor_free(v);
1714 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1715 tt_str_op(k,OP_EQ, "DoubleQuote");
1716 tt_str_op(v,OP_EQ, "\"");
1717 tor_free(k); tor_free(v);
1719 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1720 tt_str_op(k,OP_EQ, "SimpleQuote");
1721 tt_str_op(v,OP_EQ, "'");
1722 tor_free(k); tor_free(v);
1724 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1725 tt_str_op(k,OP_EQ, "Backslash");
1726 tt_str_op(v,OP_EQ, "\\");
1727 tor_free(k); tor_free(v);
1729 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1730 tt_str_op(k,OP_EQ, "Mix");
1731 tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
1732 tor_free(k); tor_free(v);
1733 tt_str_op(str,OP_EQ, "");
1735 str = buf2;
1737 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1738 tt_ptr_op(str,OP_EQ, NULL);
1739 tor_free(k); tor_free(v);
1741 str = buf3;
1743 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1744 tt_ptr_op(str,OP_EQ, NULL);
1745 tor_free(k); tor_free(v);
1747 str = buf4;
1749 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1750 tt_ptr_op(str,OP_EQ, NULL);
1751 tor_free(k); tor_free(v);
1753 #if 0
1754 str = buf5;
1756 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1757 tt_ptr_op(str, OP_EQ, NULL);
1758 tor_free(k); tor_free(v);
1759 #endif /* 0 */
1761 str = buf6;
1763 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1764 tt_ptr_op(str,OP_EQ, NULL);
1765 tor_free(k); tor_free(v);
1767 /* more things to try. */
1768 /* Bad hex: */
1769 strlcpy(buf1, "Foo \"\\x9g\"\n", sizeof(buf1));
1770 strlcpy(buf2, "Foo \"\\xg0\"\n", sizeof(buf2));
1771 strlcpy(buf3, "Foo \"\\xf\"\n", sizeof(buf3));
1772 /* bad escape */
1773 strlcpy(buf4, "Foo \"\\q\"\n", sizeof(buf4));
1774 /* missing endquote */
1775 strlcpy(buf5, "Foo \"hello\n", sizeof(buf5));
1776 /* extra stuff */
1777 strlcpy(buf6, "Foo \"hello\" world\n", sizeof(buf6));
1779 str=buf1;
1780 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1781 tt_ptr_op(str,OP_EQ, NULL);
1782 tor_free(k); tor_free(v);
1784 str=buf2;
1785 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1786 tt_ptr_op(str,OP_EQ, NULL);
1787 tor_free(k); tor_free(v);
1789 str=buf3;
1790 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1791 tt_ptr_op(str,OP_EQ, NULL);
1792 tor_free(k); tor_free(v);
1794 str=buf4;
1795 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1796 tt_ptr_op(str,OP_EQ, NULL);
1797 tor_free(k); tor_free(v);
1799 str=buf5;
1801 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1802 tt_ptr_op(str,OP_EQ, NULL);
1803 tor_free(k); tor_free(v);
1805 str=buf6;
1806 const char *err = NULL;
1807 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1808 tt_ptr_op(str,OP_EQ, NULL);
1809 tor_free(k); tor_free(v);
1810 tt_str_op(err,OP_EQ, "Excess data after quoted string");
1812 done:
1813 tor_free(k);
1814 tor_free(v);
1817 static void
1818 test_util_config_line_crlf(void *arg)
1820 char *k=NULL, *v=NULL;
1821 const char *err = NULL;
1822 (void)arg;
1823 const char *str =
1824 "Hello world\r\n"
1825 "Hello \"nice big world\"\r\n";
1827 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1828 tt_assert(str);
1829 tt_str_op(k,OP_EQ,"Hello");
1830 tt_str_op(v,OP_EQ,"world");
1831 tt_ptr_op(err, OP_EQ, NULL);
1832 tor_free(k); tor_free(v);
1834 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1835 tt_assert(str);
1836 tt_str_op(k,OP_EQ,"Hello");
1837 tt_str_op(v,OP_EQ,"nice big world");
1838 tt_ptr_op(err, OP_EQ, NULL);
1839 tor_free(k); tor_free(v);
1840 tt_str_op(str,OP_EQ, "");
1842 done:
1843 tor_free(k); tor_free(v);
1846 #ifndef _WIN32
1847 static void
1848 test_util_expand_filename(void *arg)
1850 char *str;
1852 (void)arg;
1853 setenv("HOME", "/home/itv", 1); /* For "internal test value" */
1855 str = expand_filename("");
1856 tt_str_op("",OP_EQ, str);
1857 tor_free(str);
1859 str = expand_filename("/normal/path");
1860 tt_str_op("/normal/path",OP_EQ, str);
1861 tor_free(str);
1863 str = expand_filename("/normal/trailing/path/");
1864 tt_str_op("/normal/trailing/path/",OP_EQ, str);
1865 tor_free(str);
1867 str = expand_filename("~");
1868 tt_str_op("/home/itv/",OP_EQ, str);
1869 tor_free(str);
1871 str = expand_filename("$HOME/nodice");
1872 tt_str_op("$HOME/nodice",OP_EQ, str);
1873 tor_free(str);
1875 str = expand_filename("~/");
1876 tt_str_op("/home/itv/",OP_EQ, str);
1877 tor_free(str);
1879 str = expand_filename("~/foobarqux");
1880 tt_str_op("/home/itv/foobarqux",OP_EQ, str);
1881 tor_free(str);
1883 str = expand_filename("~/../../etc/passwd");
1884 tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
1885 tor_free(str);
1887 str = expand_filename("~/trailing/");
1888 tt_str_op("/home/itv/trailing/",OP_EQ, str);
1889 tor_free(str);
1890 /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
1891 have to somehow inject/fake the get_user_homedir call) */
1893 /* $HOME ending in a trailing slash */
1894 setenv("HOME", "/home/itv/", 1);
1896 str = expand_filename("~");
1897 tt_str_op("/home/itv/",OP_EQ, str);
1898 tor_free(str);
1900 str = expand_filename("~/");
1901 tt_str_op("/home/itv/",OP_EQ, str);
1902 tor_free(str);
1904 str = expand_filename("~/foo");
1905 tt_str_op("/home/itv/foo",OP_EQ, str);
1906 tor_free(str);
1908 /* Try with empty $HOME */
1910 setenv("HOME", "", 1);
1912 str = expand_filename("~");
1913 tt_str_op("/",OP_EQ, str);
1914 tor_free(str);
1916 str = expand_filename("~/");
1917 tt_str_op("/",OP_EQ, str);
1918 tor_free(str);
1920 str = expand_filename("~/foobar");
1921 tt_str_op("/foobar",OP_EQ, str);
1922 tor_free(str);
1924 /* Try with $HOME unset */
1926 unsetenv("HOME");
1928 str = expand_filename("~");
1929 tt_str_op("/",OP_EQ, str);
1930 tor_free(str);
1932 str = expand_filename("~/");
1933 tt_str_op("/",OP_EQ, str);
1934 tor_free(str);
1936 str = expand_filename("~/foobar");
1937 tt_str_op("/foobar",OP_EQ, str);
1938 tor_free(str);
1940 done:
1941 tor_free(str);
1943 #endif /* !defined(_WIN32) */
1945 /** Test tor_escape_str_for_pt_args(). */
1946 static void
1947 test_util_escape_string_socks(void *arg)
1949 char *escaped_string = NULL;
1951 /** Simple backslash escape. */
1952 (void)arg;
1953 escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
1954 tt_assert(escaped_string);
1955 tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
1956 tor_free(escaped_string);
1958 /** Simple semicolon escape. */
1959 escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
1960 tt_assert(escaped_string);
1961 tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
1962 tor_free(escaped_string);
1964 /** Empty string. */
1965 escaped_string = tor_escape_str_for_pt_args("", ";\\");
1966 tt_assert(escaped_string);
1967 tt_str_op(escaped_string,OP_EQ, "");
1968 tor_free(escaped_string);
1970 /** Escape all characters. */
1971 escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
1972 tt_assert(escaped_string);
1973 tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
1974 tor_free(escaped_string);
1976 escaped_string = tor_escape_str_for_pt_args(";", ";\\");
1977 tt_assert(escaped_string);
1978 tt_str_op(escaped_string,OP_EQ, "\\;");
1979 tor_free(escaped_string);
1981 done:
1982 tor_free(escaped_string);
1985 static void
1986 test_util_string_is_key_value(void *ptr)
1988 (void)ptr;
1989 tt_assert(string_is_key_value(LOG_WARN, "key=value"));
1990 tt_assert(string_is_key_value(LOG_WARN, "k=v"));
1991 tt_assert(string_is_key_value(LOG_WARN, "key="));
1992 tt_assert(string_is_key_value(LOG_WARN, "x="));
1993 tt_assert(string_is_key_value(LOG_WARN, "xx="));
1994 tt_assert(!string_is_key_value(LOG_WARN, "=value"));
1995 tt_assert(!string_is_key_value(LOG_WARN, "=x"));
1996 tt_assert(!string_is_key_value(LOG_WARN, "="));
1998 /* ??? */
1999 /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
2000 done:
2004 /** Test basic string functionality. */
2005 static void
2006 test_util_strmisc(void *arg)
2008 char buf[1024];
2009 char *cp_tmp = NULL;
2011 /* Test strl operations */
2012 (void)arg;
2013 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
2014 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
2015 tt_str_op(buf,OP_EQ, "Hello");
2016 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
2017 tt_str_op(buf,OP_EQ, "Hello");
2018 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
2019 tt_str_op(buf,OP_EQ, "Hell");
2020 strlcpy(buf, "Hello", sizeof(buf));
2021 tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
2023 /* Test strstrip() */
2024 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
2025 tor_strstrip(buf, ",!");
2026 tt_str_op(buf,OP_EQ, "Testing 1 2 3");
2027 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
2028 tor_strstrip(buf, "!? ");
2029 tt_str_op(buf,OP_EQ, "Testing123");
2030 strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
2031 tor_strstrip(buf, "!? ");
2032 tt_str_op(buf,OP_EQ, "Testing123");
2034 /* Test snprintf */
2035 /* Returning -1 when there's not enough room in the output buffer */
2036 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
2037 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
2038 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
2039 tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
2040 /* Always NUL-terminate the output */
2041 tor_snprintf(buf, 5, "abcdef");
2042 tt_int_op(0,OP_EQ, buf[4]);
2043 tor_snprintf(buf, 10, "abcdef");
2044 tt_int_op(0,OP_EQ, buf[6]);
2045 /* uint64 */
2046 tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x",
2047 (UINT64_C(12345678901)));
2048 tt_str_op("x!12345678901!x",OP_EQ, buf);
2050 /* Test str{,case}cmpstart */
2051 tt_assert(strcmpstart("abcdef", "abcdef")==0);
2052 tt_assert(strcmpstart("abcdef", "abc")==0);
2053 tt_assert(strcmpstart("abcdef", "abd")<0);
2054 tt_assert(strcmpstart("abcdef", "abb")>0);
2055 tt_assert(strcmpstart("ab", "abb")<0);
2056 tt_assert(strcmpstart("ab", "")==0);
2057 tt_assert(strcmpstart("ab", "ab ")<0);
2058 tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
2059 tt_assert(strcasecmpstart("abcDeF", "abc")==0);
2060 tt_assert(strcasecmpstart("abcdef", "Abd")<0);
2061 tt_assert(strcasecmpstart("Abcdef", "abb")>0);
2062 tt_assert(strcasecmpstart("ab", "Abb")<0);
2063 tt_assert(strcasecmpstart("ab", "")==0);
2064 tt_assert(strcasecmpstart("ab", "ab ")<0);
2066 /* Test str{,case}cmpend */
2067 tt_assert(strcmpend("abcdef", "abcdef")==0);
2068 tt_assert(strcmpend("abcdef", "def")==0);
2069 tt_assert(strcmpend("abcdef", "deg")<0);
2070 tt_assert(strcmpend("abcdef", "dee")>0);
2071 tt_assert(strcmpend("ab", "aab")>0);
2072 tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
2073 tt_assert(strcasecmpend("abcdef", "dEF")==0);
2074 tt_assert(strcasecmpend("abcdef", "Deg")<0);
2075 tt_assert(strcasecmpend("abcDef", "dee")>0);
2076 tt_assert(strcasecmpend("AB", "abb")<0);
2078 /* Test digest_is_zero */
2079 memset(buf,0,20);
2080 buf[20] = 'x';
2081 tt_assert(tor_digest_is_zero(buf));
2082 buf[19] = 'x';
2083 tt_assert(!tor_digest_is_zero(buf));
2085 /* Test mem_is_zero */
2086 memset(buf,0,128);
2087 buf[128] = 'x';
2088 tt_assert(tor_mem_is_zero(buf, 10));
2089 tt_assert(tor_mem_is_zero(buf, 20));
2090 tt_assert(tor_mem_is_zero(buf, 128));
2091 tt_assert(!tor_mem_is_zero(buf, 129));
2092 buf[60] = (char)255;
2093 tt_assert(!tor_mem_is_zero(buf, 128));
2094 buf[0] = (char)1;
2095 tt_assert(!tor_mem_is_zero(buf, 10));
2097 /* Test 'escaped' */
2098 tt_ptr_op(escaped(NULL), OP_EQ, NULL);
2099 tt_str_op("\"\"",OP_EQ, escaped(""));
2100 tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
2101 tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
2102 tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
2103 escaped("unnecessary \'backslashes\'"));
2104 /* Non-printable characters appear as octal */
2105 tt_str_op("\"z\\001abc\\277d\"",OP_EQ, escaped("z\001abc\277d"));
2106 tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
2108 /* Other cases of esc_for_log{,_len} */
2109 cp_tmp = esc_for_log(NULL);
2110 tt_str_op(cp_tmp, OP_EQ, "(null)");
2111 tor_free(cp_tmp);
2112 cp_tmp = esc_for_log_len("abcdefg", 3);
2113 tt_str_op(cp_tmp, OP_EQ, "\"abc\"");
2114 tor_free(cp_tmp);
2115 cp_tmp = esc_for_log_len("abcdefg", 100);
2116 tt_str_op(cp_tmp, OP_EQ, "\"abcdefg\"");
2117 tor_free(cp_tmp);
2119 /* Test strndup and memdup */
2121 const char *s = "abcdefghijklmnopqrstuvwxyz";
2122 cp_tmp = tor_strndup(s, 30);
2123 tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
2124 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2125 tor_free(cp_tmp);
2127 cp_tmp = tor_strndup(s, 5);
2128 tt_str_op(cp_tmp,OP_EQ, "abcde");
2129 tor_free(cp_tmp);
2131 s = "a\0b\0c\0d\0e\0";
2132 cp_tmp = tor_memdup(s,10);
2133 tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
2134 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2135 tor_free(cp_tmp);
2138 /* Test str-foo functions */
2139 cp_tmp = tor_strdup("abcdef");
2140 tt_assert(tor_strisnonupper(cp_tmp));
2141 cp_tmp[3] = 'D';
2142 tt_assert(!tor_strisnonupper(cp_tmp));
2143 tor_strupper(cp_tmp);
2144 tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
2145 tor_strlower(cp_tmp);
2146 tt_str_op(cp_tmp,OP_EQ, "abcdef");
2147 tt_assert(tor_strisnonupper(cp_tmp));
2148 tt_assert(tor_strisprint(cp_tmp));
2149 cp_tmp[3] = 3;
2150 tt_assert(!tor_strisprint(cp_tmp));
2151 tor_free(cp_tmp);
2153 /* Test memmem and memstr */
2155 const char *haystack = "abcde";
2156 tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL);
2157 tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
2158 tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
2159 tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL);
2160 haystack = "ababcad";
2161 tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
2162 tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
2163 tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
2164 tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL);
2165 tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL);
2166 /* memstr */
2167 tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
2168 tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
2169 tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL);
2170 tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL);
2171 tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL);
2172 tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL);
2175 /* Test hex_str */
2177 char binary_data[68];
2178 size_t idx;
2179 for (idx = 0; idx < sizeof(binary_data); ++idx)
2180 binary_data[idx] = idx;
2181 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2182 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2183 tt_str_op(hex_str(binary_data, 17),OP_EQ,
2184 "000102030405060708090A0B0C0D0E0F10");
2185 tt_str_op(hex_str(binary_data, 32),OP_EQ,
2186 "000102030405060708090A0B0C0D0E0F"
2187 "101112131415161718191A1B1C1D1E1F");
2188 tt_str_op(hex_str(binary_data, 34),OP_EQ,
2189 "000102030405060708090A0B0C0D0E0F"
2190 "101112131415161718191A1B1C1D1E1F");
2191 /* Repeat these tests for shorter strings after longer strings
2192 have been tried, to make sure we're correctly terminating strings */
2193 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2194 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2197 /* Test strcmp_opt */
2198 tt_int_op(strcmp_opt("", "foo"), OP_LT, 0);
2199 tt_int_op(strcmp_opt("", ""), OP_EQ, 0);
2200 tt_int_op(strcmp_opt("foo", ""), OP_GT, 0);
2202 tt_int_op(strcmp_opt(NULL, ""), OP_LT, 0);
2203 tt_int_op(strcmp_opt(NULL, NULL), OP_EQ, 0);
2204 tt_int_op(strcmp_opt("", NULL), OP_GT, 0);
2206 tt_int_op(strcmp_opt(NULL, "foo"), OP_LT, 0);
2207 tt_int_op(strcmp_opt("foo", NULL), OP_GT, 0);
2209 done:
2210 tor_free(cp_tmp);
2213 static void
2214 test_util_parse_integer(void *arg)
2216 (void)arg;
2217 int i;
2218 char *cp;
2220 /* Test parse_long */
2221 /* Empty/zero input */
2222 tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
2223 tt_int_op(0,OP_EQ, i);
2224 tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
2225 tt_int_op(1,OP_EQ, i);
2226 /* Normal cases */
2227 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
2228 tt_int_op(1,OP_EQ, i);
2229 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
2230 tt_int_op(1,OP_EQ, i);
2231 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
2232 tt_int_op(1,OP_EQ, i);
2233 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
2234 tt_int_op(1,OP_EQ, i);
2235 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
2236 tt_int_op(1,OP_EQ, i);
2237 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
2238 tt_int_op(1,OP_EQ, i);
2239 /* Extra garbage */
2240 tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
2241 tt_int_op(0,OP_EQ, i);
2242 tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
2243 tt_int_op(0,OP_EQ, i);
2244 tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
2245 tt_int_op(1,OP_EQ, i);
2246 tt_str_op(cp,OP_EQ, "m");
2247 tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
2248 tt_int_op(1,OP_EQ, i);
2249 tt_str_op(cp,OP_EQ, " plus garbage");
2250 /* Illogical min max */
2251 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL));
2252 tt_int_op(0,OP_EQ, i);
2253 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL));
2254 tt_int_op(0,OP_EQ, i);
2255 /* Out of bounds */
2256 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
2257 tt_int_op(0,OP_EQ, i);
2258 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,0,100,&i,NULL));
2259 tt_int_op(0,OP_EQ, i);
2260 /* Base different than 10 */
2261 tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL));
2262 tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
2263 tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
2264 tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
2265 tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
2266 tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
2267 tt_int_op(i,OP_EQ, 0);
2269 /* Test parse_ulong */
2270 tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
2271 tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
2272 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
2273 tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
2274 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
2275 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
2276 tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
2277 tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
2278 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
2279 tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
2280 tt_int_op(0,OP_EQ, i);
2281 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
2282 tt_int_op(0,OP_EQ, i);
2284 /* Test parse_uint64 */
2285 tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
2286 tt_int_op(1,OP_EQ, i);
2287 tt_str_op(cp,OP_EQ, " x");
2288 tt_assert(UINT64_C(12345678901) ==
2289 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
2290 tt_int_op(1,OP_EQ, i);
2291 tt_str_op(cp,OP_EQ, "");
2292 tt_assert(UINT64_C(0) ==
2293 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
2294 tt_int_op(0,OP_EQ, i);
2295 tt_assert(UINT64_C(0) ==
2296 tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
2297 tt_int_op(0,OP_EQ, i);
2300 /* Test parse_double */
2301 double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
2302 tt_int_op(1,OP_EQ, i);
2303 tt_assert(((uint64_t)d) == 10);
2304 d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
2305 tt_int_op(1,OP_EQ, i);
2306 tt_assert(((uint64_t)d) == 0);
2307 d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
2308 tt_double_op(fabs(d), OP_LT, 1e-10);
2309 tt_int_op(0,OP_EQ, i);
2310 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL);
2311 tt_double_op(fabs(d), OP_LT, 1e-10);
2312 tt_int_op(0,OP_EQ, i);
2313 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp);
2314 tt_double_op(fabs(d), OP_LT, 1e-10);
2315 tt_int_op(1,OP_EQ, i);
2316 d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
2317 tt_int_op(1,OP_EQ, i);
2318 tt_assert(((uint64_t)d) == 0);
2319 d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
2320 tt_int_op(1,OP_EQ, i);
2321 tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
2325 /* Test tor_parse_* where we overflow/underflow the underlying type. */
2326 /* This string should overflow 64-bit ints. */
2327 #define TOOBIG "100000000000000000000000000"
2328 tt_int_op(0L, OP_EQ,
2329 tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2330 tt_int_op(i,OP_EQ, 0);
2331 tt_int_op(0L,OP_EQ,
2332 tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2333 tt_int_op(i,OP_EQ, 0);
2334 tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
2335 tt_int_op(i,OP_EQ, 0);
2336 tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
2337 0, UINT64_MAX, &i, NULL));
2338 tt_int_op(i,OP_EQ, 0);
2340 done:
2344 static void
2345 test_util_pow2(void *arg)
2347 /* Test tor_log2(). */
2348 (void)arg;
2349 tt_int_op(tor_log2(64),OP_EQ, 6);
2350 tt_int_op(tor_log2(65),OP_EQ, 6);
2351 tt_int_op(tor_log2(63),OP_EQ, 5);
2352 /* incorrect mathematically, but as specified: */
2353 tt_int_op(tor_log2(0),OP_EQ, 0);
2354 tt_int_op(tor_log2(1),OP_EQ, 0);
2355 tt_int_op(tor_log2(2),OP_EQ, 1);
2356 tt_int_op(tor_log2(3),OP_EQ, 1);
2357 tt_int_op(tor_log2(4),OP_EQ, 2);
2358 tt_int_op(tor_log2(5),OP_EQ, 2);
2359 tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55);
2360 tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
2362 /* Test round_to_power_of_2 */
2363 tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
2364 tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
2365 tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
2366 tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ,
2367 UINT64_C(1)<<55);
2368 tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ,
2369 UINT64_C(1)<<63);
2370 tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
2371 tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
2372 tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
2373 tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
2374 tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
2375 tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
2376 tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
2377 tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
2379 done:
2383 static void
2384 test_util_compress_impl(compress_method_t method)
2386 char *buf1=NULL, *buf2=NULL, *buf3=NULL;
2387 size_t len1, len2;
2389 tt_assert(tor_compress_supports_method(method));
2391 if (method != NO_METHOD) {
2392 tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
2393 tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
2396 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
2397 tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
2399 tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
2400 tt_ptr_op(buf2, OP_NE, NULL);
2401 if (method == NO_METHOD) {
2402 // The identity transform doesn't actually compress, and it isn't
2403 // detectable as "the identity transform."
2404 tt_int_op(len1, OP_EQ, strlen(buf1)+1);
2405 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
2406 } else {
2407 tt_int_op(len1, OP_LT, strlen(buf1));
2408 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
2411 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
2412 tt_ptr_op(buf3, OP_NE, NULL);
2413 tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
2414 tt_str_op(buf1, OP_EQ, buf3);
2415 tt_int_op(buf3[len2], OP_EQ, 0);
2417 /* Check whether we can uncompress concatenated, compressed strings. */
2418 tor_free(buf3);
2419 buf2 = tor_reallocarray(buf2, len1, 2);
2420 memcpy(buf2+len1, buf2, len1);
2421 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
2422 tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
2423 tt_mem_op(buf3, OP_EQ,
2424 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
2425 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
2426 (strlen(buf1)+1)*2);
2427 tt_int_op(buf3[len2], OP_EQ, 0);
2429 /* Check whether we can uncompress partial strings */
2431 tor_free(buf1);
2432 tor_free(buf2);
2433 tor_free(buf3);
2435 size_t b1len = 1<<10;
2436 if (method == ZSTD_METHOD) {
2437 // zstd needs a big input before it starts generating output that it
2438 // can partially decompress.
2439 b1len = 1<<18;
2441 buf1 = tor_malloc(b1len);
2442 crypto_rand(buf1, b1len);
2443 tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
2444 tt_int_op(len1, OP_GT, 16);
2445 /* when we allow an incomplete output we should succeed.*/
2446 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
2447 method, 0, LOG_INFO));
2448 tt_int_op(len2, OP_GT, 5);
2449 tt_int_op(len2, OP_LE, len1);
2450 tt_assert(fast_memeq(buf1, buf3, len2));
2451 tt_int_op(buf3[len2], OP_EQ, 0);
2453 /* when we demand a complete output from a real compression method, this
2454 * must fail. */
2455 tor_free(buf3);
2456 if (method != NO_METHOD) {
2457 tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
2458 method, 1, LOG_INFO));
2459 tt_ptr_op(buf3, OP_EQ, NULL);
2462 done:
2463 tor_free(buf1);
2464 tor_free(buf2);
2465 tor_free(buf3);
2468 static void
2469 test_util_compress_stream_impl(compress_method_t method,
2470 compression_level_t level)
2472 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
2473 const char *ccp2;
2474 size_t len1, len2;
2476 tor_compress_state_t *state = NULL;
2477 state = tor_compress_new(1, method, level);
2478 tt_assert(state);
2479 cp1 = buf1 = tor_malloc(1024);
2480 len1 = 1024;
2481 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
2482 len2 = 21;
2483 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
2484 OP_EQ, TOR_COMPRESS_OK);
2485 tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
2486 tt_assert(cp1 > buf1);
2488 len2 = 0;
2489 cp2 = cp1;
2490 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
2491 OP_EQ, TOR_COMPRESS_DONE);
2492 tt_int_op(0, OP_EQ, len2);
2493 if (method == NO_METHOD) {
2494 tt_ptr_op(cp1, OP_EQ, cp2);
2495 } else {
2496 tt_assert(cp1 > cp2); /* Make sure we really added something. */
2499 tt_int_op(tor_compress_state_size(state), OP_GT, 0);
2501 tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
2502 method, 1, LOG_WARN));
2503 /* Make sure it compressed right. */
2504 tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
2505 tt_int_op(21, OP_EQ, len2);
2507 done:
2508 if (state)
2509 tor_compress_free(state);
2510 tor_free(buf1);
2511 tor_free(buf2);
2512 tor_free(buf3);
2515 /** Setup function for compression tests: handles x-zstd:nostatic
2517 static void *
2518 compression_test_setup(const struct testcase_t *testcase)
2520 tor_assert(testcase->setup_data);
2521 tor_assert(testcase->setup_data != (void*)TT_SKIP);
2522 const char *methodname = testcase->setup_data;
2524 if (!strcmp(methodname, "x-zstd:nostatic")) {
2525 methodname = "x-zstd";
2526 tor_zstd_set_static_apis_disabled_for_testing(1);
2529 return (void *)methodname;
2532 /** Cleanup for compression tests: disables nostatic */
2533 static int
2534 compression_test_cleanup(const struct testcase_t *testcase, void *ptr)
2536 (void)testcase;
2537 (void)ptr;
2538 tor_zstd_set_static_apis_disabled_for_testing(0);
2539 return 1;
2542 static const struct testcase_setup_t compress_setup = {
2543 compression_test_setup, compression_test_cleanup
2546 /** Run unit tests for compression functions */
2547 static void
2548 test_util_compress(void *arg)
2550 const char *methodname = arg;
2551 tt_assert(methodname);
2553 compress_method_t method = compression_method_get_by_name(methodname);
2554 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2556 if (! tor_compress_supports_method(method)) {
2557 tt_skip();
2560 compression_level_t levels[] = {
2561 BEST_COMPRESSION,
2562 HIGH_COMPRESSION,
2563 MEDIUM_COMPRESSION,
2564 LOW_COMPRESSION
2567 test_util_compress_impl(method);
2569 for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
2570 compression_level_t level = levels[l];
2571 test_util_compress_stream_impl(method, level);
2573 done:
2577 static void
2578 test_util_decompress_concatenated_impl(compress_method_t method)
2580 char input[4096];
2581 char *c1 = NULL, *c2 = NULL, *c3 = NULL;
2582 char *result = NULL;
2583 size_t sz1, sz2, sz3, szr;
2584 int r;
2586 crypto_rand(input, sizeof(input));
2588 /* Compress the input in two chunks. */
2589 r = tor_compress(&c1, &sz1, input, 2048, method);
2590 tt_int_op(r, OP_EQ, 0);
2591 r = tor_compress(&c2, &sz2, input+2048, 2048, method);
2592 tt_int_op(r, OP_EQ, 0);
2594 /* concatenate the chunks. */
2595 sz3 = sz1 + sz2;
2596 c3 = tor_malloc(sz3);
2597 memcpy(c3, c1, sz1);
2598 memcpy(c3+sz1, c2, sz2);
2600 /* decompress the concatenated result */
2601 r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
2602 tt_int_op(r, OP_EQ, 0);
2603 tt_int_op(szr, OP_EQ, sizeof(input));
2604 tt_mem_op(result, OP_EQ, input, sizeof(input));
2606 done:
2607 tor_free(c1);
2608 tor_free(c2);
2609 tor_free(c3);
2610 tor_free(result);
2613 static void
2614 test_util_decompress_concatenated(void *arg)
2616 const char *methodname = arg;
2617 tt_assert(methodname);
2619 compress_method_t method = compression_method_get_by_name(methodname);
2620 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2621 if (! tor_compress_supports_method(method)) {
2622 tt_skip();
2625 test_util_decompress_concatenated_impl(method);
2626 done:
2630 static void
2631 test_util_decompress_junk_impl(compress_method_t method)
2633 char input[4096];
2634 char *result = NULL, *result2 = NULL;
2635 size_t szr, szr2, sz;
2636 int r;
2638 /* This shouldn't be a compressed string according to any method. */
2639 strlcpy(input, "This shouldn't be a compressed string by any means.",
2640 sizeof(input));
2641 sz = strlen(input);
2642 setup_capture_of_logs(LOG_WARN);
2643 r = tor_uncompress(&result, &szr, input, sz, method, 0, LOG_WARN);
2644 tt_int_op(r, OP_EQ, -1);
2645 tt_ptr_op(result, OP_EQ, NULL);
2646 expect_log_msg_containing("Error while uncompressing data: bad input?");
2647 mock_clean_saved_logs();
2649 /* Now try again, with a compressed object that starts out good and turns to
2650 junk. */
2651 crypto_rand(input, sizeof(input));
2652 r = tor_compress(&result, &szr, input, sizeof(input), method);
2653 tt_int_op(r, OP_EQ, 0);
2654 crypto_rand(result+szr/2, szr-(szr/2)); // trash the 2nd half of the result
2655 r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2656 tt_int_op(r, OP_EQ, -1);
2657 expect_log_msg_containing("Error while uncompressing data: bad input?");
2659 done:
2660 teardown_capture_of_logs();
2661 tor_free(result);
2662 tor_free(result2);
2665 static void
2666 test_util_decompress_junk(void *arg)
2668 const char *methodname = arg;
2669 tt_assert(methodname);
2671 compress_method_t method = compression_method_get_by_name(methodname);
2672 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2673 if (! tor_compress_supports_method(method)) {
2674 tt_skip();
2677 test_util_decompress_junk_impl(method);
2678 done:
2682 /* mock replacement for tor_compress_is_compression_bomb that doesn't
2683 * believe in compression bombs. */
2684 static int
2685 mock_is_never_compression_bomb(size_t in, size_t out)
2687 (void)in;
2688 (void) out;
2689 return 0;
2692 static void
2693 test_util_decompress_dos_impl(compress_method_t method)
2695 char *input;
2696 char *result = NULL, *result2 = NULL;
2697 size_t szr, szr2;
2698 int r;
2700 const size_t big = 1024*1024;
2701 /* one megabyte of 0s. */
2702 input = tor_malloc_zero(big);
2704 /* Compress it into "result": it should fail. */
2705 setup_full_capture_of_logs(LOG_WARN);
2706 r = tor_compress(&result, &szr, input, big, method);
2707 tt_int_op(r, OP_EQ, -1);
2708 expect_log_msg_containing(
2709 "other Tors would think this was a compression bomb");
2710 teardown_capture_of_logs();
2712 /* Try again, but this time suppress compression-bomb detection */
2713 MOCK(tor_compress_is_compression_bomb, mock_is_never_compression_bomb);
2714 r = tor_compress(&result, &szr, input, big, method);
2715 UNMOCK(tor_compress_is_compression_bomb);
2716 tt_int_op(r, OP_EQ, 0);
2717 tt_ptr_op(result, OP_NE, NULL);
2719 /* We should refuse to uncomrpess it again, since it looks like a
2720 * compression bomb. */
2721 setup_capture_of_logs(LOG_WARN);
2722 r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2723 tt_int_op(r, OP_EQ, -1);
2724 expect_log_msg_containing("bomb; abandoning stream");
2726 done:
2727 teardown_capture_of_logs();
2728 tor_free(input);
2729 tor_free(result);
2730 tor_free(result2);
2733 static void
2734 test_util_decompress_dos(void *arg)
2736 const char *methodname = arg;
2737 tt_assert(methodname);
2739 compress_method_t method = compression_method_get_by_name(methodname);
2740 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2741 if (! tor_compress_supports_method(method)) {
2742 tt_skip();
2745 test_util_decompress_dos_impl(method);
2746 done:
2750 static void
2751 test_util_gzip_compression_bomb(void *arg)
2753 /* A 'compression bomb' is a very small object that uncompresses to a huge
2754 * one. Most compression formats support them, but they can be a DOS vector.
2755 * In Tor we try not to generate them, and we don't accept them.
2757 (void) arg;
2758 size_t one_million = 1<<20;
2759 char *one_mb = tor_malloc_zero(one_million);
2760 char *result = NULL;
2761 size_t result_len = 0;
2762 tor_compress_state_t *state = NULL;
2764 /* Make sure we can't produce a compression bomb */
2765 setup_full_capture_of_logs(LOG_WARN);
2766 tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
2767 one_mb, one_million,
2768 ZLIB_METHOD));
2769 expect_single_log_msg_containing(
2770 "We compressed something and got an insanely high "
2771 "compression factor; other Tors would think this "
2772 "was a compression bomb.");
2773 teardown_capture_of_logs();
2775 /* Here's a compression bomb that we made manually. */
2776 const char compression_bomb[1039] =
2777 { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
2778 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
2779 tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
2780 compression_bomb, 1039,
2781 ZLIB_METHOD, 0, LOG_WARN));
2783 /* Now try streaming that. */
2784 state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
2785 tor_compress_output_t r;
2786 const char *inp = compression_bomb;
2787 size_t inlen = 1039;
2788 do {
2789 char *outp = one_mb;
2790 size_t outleft = 4096; /* small on purpose */
2791 r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
2792 tt_int_op(inlen, OP_NE, 0);
2793 } while (r == TOR_COMPRESS_BUFFER_FULL);
2795 tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
2797 done:
2798 tor_free(one_mb);
2799 tor_compress_free(state);
2802 /** Run unit tests for mmap() wrapper functionality. */
2803 static void
2804 test_util_mmap(void *arg)
2806 char *fname1 = tor_strdup(get_fname("mapped_1"));
2807 char *fname2 = tor_strdup(get_fname("mapped_2"));
2808 char *fname3 = tor_strdup(get_fname("mapped_3"));
2809 const size_t buflen = 17000;
2810 char *buf = tor_malloc(17000);
2811 tor_mmap_t *mapping = NULL;
2813 (void)arg;
2814 crypto_rand(buf, buflen);
2816 mapping = tor_mmap_file(fname1);
2817 tt_ptr_op(mapping, OP_EQ, NULL);
2819 write_str_to_file(fname1, "Short file.", 1);
2821 mapping = tor_mmap_file(fname1);
2822 tt_assert(mapping);
2823 tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
2824 tt_str_op(mapping->data,OP_EQ, "Short file.");
2825 #ifdef _WIN32
2826 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2827 mapping = NULL;
2828 tt_assert(unlink(fname1) == 0);
2829 #else
2830 /* make sure we can unlink. */
2831 tt_assert(unlink(fname1) == 0);
2832 tt_str_op(mapping->data,OP_EQ, "Short file.");
2833 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2834 mapping = NULL;
2835 #endif /* defined(_WIN32) */
2837 /* Now a zero-length file. */
2838 write_str_to_file(fname1, "", 1);
2839 mapping = tor_mmap_file(fname1);
2840 tt_ptr_op(mapping,OP_EQ, NULL);
2841 tt_int_op(ERANGE,OP_EQ, errno);
2842 unlink(fname1);
2844 /* Make sure that we fail to map a no-longer-existent file. */
2845 mapping = tor_mmap_file(fname1);
2846 tt_ptr_op(mapping, OP_EQ, NULL);
2848 /* Now try a big file that stretches across a few pages and isn't aligned */
2849 write_bytes_to_file(fname2, buf, buflen, 1);
2850 mapping = tor_mmap_file(fname2);
2851 tt_assert(mapping);
2852 tt_int_op(mapping->size,OP_EQ, buflen);
2853 tt_mem_op(mapping->data,OP_EQ, buf, buflen);
2854 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2855 mapping = NULL;
2857 /* Now try a big aligned file. */
2858 write_bytes_to_file(fname3, buf, 16384, 1);
2859 mapping = tor_mmap_file(fname3);
2860 tt_assert(mapping);
2861 tt_int_op(mapping->size,OP_EQ, 16384);
2862 tt_mem_op(mapping->data,OP_EQ, buf, 16384);
2863 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2864 mapping = NULL;
2866 done:
2867 unlink(fname1);
2868 unlink(fname2);
2869 unlink(fname3);
2871 tor_free(fname1);
2872 tor_free(fname2);
2873 tor_free(fname3);
2874 tor_free(buf);
2876 tor_munmap_file(mapping);
2879 /** Run unit tests for escaping/unescaping data for use by controllers. */
2880 static void
2881 test_util_control_formats(void *arg)
2883 char *out = NULL;
2884 const char *inp =
2885 "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
2886 size_t sz;
2888 (void)arg;
2889 sz = read_escaped_data(inp, strlen(inp), &out);
2890 tt_str_op(out,OP_EQ,
2891 ".This is a test\nof the emergency \n.system.\n\rZ.\n");
2892 tt_int_op(sz,OP_EQ, strlen(out));
2894 done:
2895 tor_free(out);
2898 #define test_feq(value1,value2) do { \
2899 double v1 = (value1), v2=(value2); \
2900 double tf_diff = v1-v2; \
2901 double tf_tolerance = ((v1+v2)/2.0)/1e8; \
2902 if (tf_diff<0) tf_diff=-tf_diff; \
2903 if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
2904 if (tf_diff<tf_tolerance) { \
2905 TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
2906 } else { \
2907 TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
2909 } while (0)
2911 static void
2912 test_util_sscanf(void *arg)
2914 unsigned u1, u2, u3;
2915 unsigned long ulng;
2916 char s1[20], s2[10], s3[10], ch, *huge = NULL;
2917 int r;
2918 long lng1,lng2;
2919 int int1, int2;
2920 double d1,d2,d3,d4;
2922 /* Simple tests (malformed patterns, literal matching, ...) */
2923 (void)arg;
2924 tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
2925 tt_int_op(-1,OP_EQ,
2926 tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
2927 tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
2928 /* this will fail because we don't allow widths longer than 9999 */
2930 huge = tor_malloc(1000000);
2931 r = tor_sscanf("prettylongstring", "%99999s", huge);
2932 tor_free(huge);
2933 tt_int_op(-1,OP_EQ, r);
2935 #if 0
2936 /* GCC thinks these two are illegal. */
2937 test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
2938 test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
2939 #endif
2940 /* No '%'-strings: always "success" */
2941 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
2942 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
2943 /* Excess data */
2944 tt_int_op(0,OP_EQ,
2945 tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
2946 tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
2947 tt_int_op(0,OP_EQ,
2948 tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
2949 tt_int_op(1,OP_EQ,
2950 tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
2952 /* Numbers (ie. %u) */
2953 tt_int_op(0,OP_EQ,
2954 tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
2955 tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
2956 tt_int_op(12345u,OP_EQ, u1);
2957 tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
2958 tt_int_op(12346u,OP_EQ, u1);
2959 tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
2960 tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
2961 tt_int_op(12348u,OP_EQ, u1);
2962 tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
2963 tt_int_op(0u,OP_EQ, u1);
2964 tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
2965 tt_int_op(0u,OP_EQ, u2);
2966 tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
2967 tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
2968 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
2970 /* Numbers with size (eg. %2u) */
2971 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
2972 tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
2973 tt_int_op(12u,OP_EQ, u1);
2974 tt_int_op(3456u,OP_EQ, u2);
2975 tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
2976 tt_int_op(123456u,OP_EQ, u1);
2977 tt_int_op(1,OP_EQ, tor_sscanf("123457 ", "%8u", &u1));
2978 tt_int_op(123457u,OP_EQ, u1);
2979 tt_int_op(0,OP_EQ, tor_sscanf(" 123456", "%8u", &u1));
2980 tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
2981 tt_int_op(12u,OP_EQ, u1);
2982 tt_int_op(3u,OP_EQ, u2);
2983 tt_int_op(456u,OP_EQ, u3);
2984 tt_int_op(3,OP_EQ,
2985 tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
2986 tt_int_op(67u,OP_EQ, u1);
2987 tt_int_op(8u,OP_EQ, u2);
2988 tt_int_op(99u,OP_EQ, u3);
2989 /* %u does not match space.*/
2990 tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
2991 tt_int_op(12u,OP_EQ, u1);
2992 tt_int_op(3u,OP_EQ, u2);
2993 /* %u does not match negative numbers. */
2994 tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
2995 tt_int_op(67u,OP_EQ, u1);
2996 tt_int_op(8u,OP_EQ, u2);
2997 /* Arbitrary amounts of 0-padding are okay */
2998 tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
2999 &u1, &u2, &u3));
3000 tt_int_op(12u,OP_EQ, u1);
3001 tt_int_op(3u,OP_EQ, u2);
3002 tt_int_op(99u,OP_EQ, u3);
3004 /* Hex (ie. %x) */
3005 tt_int_op(3,OP_EQ,
3006 tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
3007 tt_int_op(0x1234,OP_EQ, u1);
3008 tt_int_op(0x2ABCDEF,OP_EQ, u2);
3009 tt_int_op(0xFF,OP_EQ, u3);
3010 /* Width works on %x */
3011 tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
3012 tt_int_op(0xf00d,OP_EQ, u1);
3013 tt_int_op(0xcafe,OP_EQ, u2);
3014 tt_int_op(444,OP_EQ, u3);
3016 /* Literal '%' (ie. '%%') */
3017 tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
3018 tt_int_op(99,OP_EQ, u1);
3019 tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
3020 tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
3021 tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
3022 tt_int_op(99,OP_EQ, u1);
3023 tt_str_op(s1,OP_EQ, "fresh");
3024 tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
3025 tt_str_op("boo",OP_EQ, s1);
3027 /* Strings (ie. %s) */
3028 tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
3029 tt_str_op(s1,OP_EQ, "hel");
3030 tt_str_op(s2,OP_EQ, "lo");
3031 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
3032 tt_str_op(s3,OP_EQ, "WD");
3033 tt_int_op(40,OP_EQ, u1);
3034 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
3035 tt_str_op(s3,OP_EQ, "WD4");
3036 tt_int_op(0,OP_EQ, u1);
3037 tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
3038 tt_int_op(76,OP_EQ, u1);
3039 tt_str_op(s1,OP_EQ, "trombones");
3041 huge = tor_malloc(1000);
3042 r = tor_sscanf("prettylongstring", "%999s", huge);
3043 tt_int_op(1,OP_EQ, r);
3044 tt_str_op(huge,OP_EQ, "prettylongstring");
3045 tor_free(huge);
3047 /* %s doesn't eat spaces */
3048 tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
3049 tt_str_op(s1,OP_EQ, "hello");
3050 tt_str_op(s2,OP_EQ, "world");
3051 tt_int_op(2,OP_EQ, tor_sscanf("bye world?", "%9s %9s", s1, s2));
3052 tt_str_op(s1,OP_EQ, "bye");
3053 tt_str_op(s2,OP_EQ, "");
3054 tt_int_op(3,OP_EQ,
3055 tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
3056 tt_str_op(s1,OP_EQ, "hi");
3057 tt_str_op(s2,OP_EQ, "");
3058 tt_str_op(s3,OP_EQ, "");
3060 tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3061 tt_int_op(4,OP_EQ,
3062 tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3063 tt_int_op(' ',OP_EQ, ch);
3065 r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
3066 tt_int_op(r,OP_EQ, 3);
3067 tt_int_op(int1,OP_EQ, 12345);
3068 tt_int_op(lng1,OP_EQ, -67890);
3069 tt_int_op(int2,OP_EQ, -1);
3071 #if SIZEOF_INT == 4
3072 /* %u */
3073 /* UINT32_MAX should work */
3074 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
3075 tt_int_op(4294967295U,OP_EQ, u1);
3077 /* But UINT32_MAX + 1 shouldn't work */
3078 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
3079 /* but parsing only 9... */
3080 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
3081 tt_int_op(429496729U,OP_EQ, u1);
3083 /* %x */
3084 /* UINT32_MAX should work */
3085 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
3086 tt_int_op(0xFFFFFFFF,OP_EQ, u1);
3088 /* But UINT32_MAX + 1 shouldn't work */
3089 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
3091 /* %d */
3092 /* INT32_MIN and INT32_MAX should work */
3093 r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
3094 tt_int_op(r,OP_EQ, 2);
3095 tt_int_op(int1,OP_EQ, -2147483647 - 1);
3096 tt_int_op(int2,OP_EQ, 2147483647);
3098 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3099 r = tor_sscanf("-2147483649.", "%d.", &int1);
3100 tt_int_op(r,OP_EQ, 0);
3102 r = tor_sscanf("2147483648.", "%d.", &int1);
3103 tt_int_op(r,OP_EQ, 0);
3105 /* and the first failure stops further processing */
3106 r = tor_sscanf("-2147483648. 2147483648.",
3107 "%d. %d.", &int1, &int2);
3108 tt_int_op(r,OP_EQ, 1);
3110 r = tor_sscanf("-2147483649. 2147483647.",
3111 "%d. %d.", &int1, &int2);
3112 tt_int_op(r,OP_EQ, 0);
3114 r = tor_sscanf("2147483648. -2147483649.",
3115 "%d. %d.", &int1, &int2);
3116 tt_int_op(r,OP_EQ, 0);
3117 #elif SIZEOF_INT == 8
3118 /* %u */
3119 /* UINT64_MAX should work */
3120 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
3121 tt_int_op(18446744073709551615U,OP_EQ, u1);
3123 /* But UINT64_MAX + 1 shouldn't work */
3124 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
3125 /* but parsing only 19... */
3126 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
3127 tt_int_op(1844674407370955161U,OP_EQ, u1);
3129 /* %x */
3130 /* UINT64_MAX should work */
3131 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
3132 tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
3134 /* But UINT64_MAX + 1 shouldn't work */
3135 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
3137 /* %d */
3138 /* INT64_MIN and INT64_MAX should work */
3139 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3140 "%d. %d.", &int1, &int2);
3141 tt_int_op(r,OP_EQ, 2);
3142 tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
3143 tt_int_op(int2,OP_EQ, 9223372036854775807);
3145 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3146 r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
3147 tt_int_op(r,OP_EQ, 0);
3149 r = tor_sscanf("9223372036854775808.", "%d.", &int1);
3150 tt_int_op(r,OP_EQ, 0);
3152 /* and the first failure stops further processing */
3153 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3154 "%d. %d.", &int1, &int2);
3155 tt_int_op(r,OP_EQ, 1);
3157 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3158 "%d. %d.", &int1, &int2);
3159 tt_int_op(r,OP_EQ, 0);
3161 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3162 "%d. %d.", &int1, &int2);
3163 tt_int_op(r,OP_EQ, 0);
3164 #endif /* SIZEOF_INT == 4 || ... */
3166 #if SIZEOF_LONG == 4
3167 /* %lu */
3168 /* UINT32_MAX should work */
3169 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
3170 tt_int_op(4294967295UL,OP_EQ, ulng);
3172 /* But UINT32_MAX + 1 shouldn't work */
3173 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
3174 /* but parsing only 9... */
3175 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
3176 tt_int_op(429496729UL,OP_EQ, ulng);
3178 /* %lx */
3179 /* UINT32_MAX should work */
3180 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
3181 tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
3183 /* But UINT32_MAX + 1 shouldn't work */
3184 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
3186 /* %ld */
3187 /* INT32_MIN and INT32_MAX should work */
3188 r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
3189 tt_int_op(r,OP_EQ, 2);
3190 tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
3191 tt_int_op(lng2,OP_EQ, 2147483647L);
3193 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3194 r = tor_sscanf("-2147483649.", "%ld.", &lng1);
3195 tt_int_op(r,OP_EQ, 0);
3197 r = tor_sscanf("2147483648.", "%ld.", &lng1);
3198 tt_int_op(r,OP_EQ, 0);
3200 /* and the first failure stops further processing */
3201 r = tor_sscanf("-2147483648. 2147483648.",
3202 "%ld. %ld.", &lng1, &lng2);
3203 tt_int_op(r,OP_EQ, 1);
3205 r = tor_sscanf("-2147483649. 2147483647.",
3206 "%ld. %ld.", &lng1, &lng2);
3207 tt_int_op(r,OP_EQ, 0);
3209 r = tor_sscanf("2147483648. -2147483649.",
3210 "%ld. %ld.", &lng1, &lng2);
3211 tt_int_op(r,OP_EQ, 0);
3212 #elif SIZEOF_LONG == 8
3213 /* %lu */
3214 /* UINT64_MAX should work */
3215 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
3216 tt_int_op(18446744073709551615UL,OP_EQ, ulng);
3218 /* But UINT64_MAX + 1 shouldn't work */
3219 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
3220 /* but parsing only 19... */
3221 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
3222 tt_int_op(1844674407370955161UL,OP_EQ, ulng);
3224 /* %lx */
3225 /* UINT64_MAX should work */
3226 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
3227 tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
3229 /* But UINT64_MAX + 1 shouldn't work */
3230 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
3232 /* %ld */
3233 /* INT64_MIN and INT64_MAX should work */
3234 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3235 "%ld. %ld.", &lng1, &lng2);
3236 tt_int_op(r,OP_EQ, 2);
3237 tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
3238 tt_int_op(lng2,OP_EQ, 9223372036854775807L);
3240 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3241 r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
3242 tt_int_op(r,OP_EQ, 0);
3244 r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
3245 tt_int_op(r,OP_EQ, 0);
3247 /* and the first failure stops further processing */
3248 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3249 "%ld. %ld.", &lng1, &lng2);
3250 tt_int_op(r,OP_EQ, 1);
3252 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3253 "%ld. %ld.", &lng1, &lng2);
3254 tt_int_op(r,OP_EQ, 0);
3256 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3257 "%ld. %ld.", &lng1, &lng2);
3258 tt_int_op(r,OP_EQ, 0);
3259 #endif /* SIZEOF_LONG == 4 || ... */
3261 r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
3262 "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
3263 tt_int_op(r,OP_EQ, 4);
3264 test_feq(d1, 123.456);
3265 test_feq(d2, .000007);
3266 test_feq(d3, -900123123.2000787);
3267 test_feq(d4, 3.2);
3269 /* missing float */
3270 r = tor_sscanf("3 ", "%d %lf", &int1, &d1);
3271 tt_int_op(r, OP_EQ, 1);
3272 tt_int_op(int1, OP_EQ, 3);
3274 /* not a float */
3275 r = tor_sscanf("999 notafloat", "%d %lf", &int1, &d1);
3276 tt_int_op(r, OP_EQ, 1);
3277 tt_int_op(int1, OP_EQ, 999);
3279 /* %s but no buffer. */
3280 char *nullbuf = NULL;
3281 r = tor_sscanf("hello", "%3s", nullbuf);
3282 tt_int_op(r, OP_EQ, 0);
3284 done:
3285 tor_free(huge);
3288 #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
3289 #define tt_ci_char_op(a,op,b) \
3290 tt_char_op(TOR_TOLOWER((int)a),op,TOR_TOLOWER((int)b))
3292 #ifndef HAVE_STRNLEN
3293 static size_t
3294 strnlen(const char *s, size_t len)
3296 const char *p = memchr(s, 0, len);
3297 if (!p)
3298 return len;
3299 return p - s;
3301 #endif /* !defined(HAVE_STRNLEN) */
3303 static void
3304 test_util_format_time_interval(void *arg)
3306 /* use the same sized buffer and integers as tor uses */
3307 #define DBUF_SIZE 64
3308 char dbuf[DBUF_SIZE];
3309 #define T_ "%ld"
3310 long sec, min, hour, day;
3312 /* we don't care about the exact spelling of the
3313 * second(s), minute(s), hour(s), day(s) labels */
3314 #define LABEL_SIZE 21
3315 #define L_ "%20s"
3316 char label_s[LABEL_SIZE];
3317 char label_m[LABEL_SIZE];
3318 char label_h[LABEL_SIZE];
3319 char label_d[LABEL_SIZE];
3321 #define TL_ T_ " " L_
3323 int r;
3325 (void)arg;
3327 /* In these tests, we're not picky about
3328 * spelling or abbreviations */
3330 /* seconds: 0, 1, 9, 10, 59 */
3332 /* ignore exact spelling of "second(s)"*/
3333 format_time_interval(dbuf, sizeof(dbuf), 0);
3334 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3335 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3336 tt_int_op(r,OP_EQ, 2);
3337 tt_ci_char_op(label_s[0],OP_EQ, 's');
3338 tt_int_op(sec,OP_EQ, 0);
3340 format_time_interval(dbuf, sizeof(dbuf), 1);
3341 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3342 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3343 tt_int_op(r,OP_EQ, 2);
3344 tt_ci_char_op(label_s[0],OP_EQ, 's');
3345 tt_int_op(sec,OP_EQ, 1);
3347 format_time_interval(dbuf, sizeof(dbuf), 10);
3348 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3349 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3350 tt_int_op(r,OP_EQ, 2);
3351 tt_ci_char_op(label_s[0],OP_EQ, 's');
3352 tt_int_op(sec,OP_EQ, 10);
3354 format_time_interval(dbuf, sizeof(dbuf), 59);
3355 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3356 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3357 tt_int_op(r,OP_EQ, 2);
3358 tt_ci_char_op(label_s[0],OP_EQ, 's');
3359 tt_int_op(sec,OP_EQ, 59);
3361 /* negative seconds are reported as their absolute value */
3363 format_time_interval(dbuf, sizeof(dbuf), -4);
3364 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3365 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3366 tt_int_op(r,OP_EQ, 2);
3367 tt_ci_char_op(label_s[0],OP_EQ, 's');
3368 tt_int_op(sec,OP_EQ, 4);
3369 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3371 format_time_interval(dbuf, sizeof(dbuf), -32);
3372 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3373 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3374 tt_int_op(r,OP_EQ, 2);
3375 tt_ci_char_op(label_s[0],OP_EQ, 's');
3376 tt_int_op(sec,OP_EQ, 32);
3377 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3379 /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
3381 /* ignore trailing "0 second(s)", if present */
3382 format_time_interval(dbuf, sizeof(dbuf), 60);
3383 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3384 r = tor_sscanf(dbuf, TL_, &min, label_m);
3385 tt_int_op(r,OP_EQ, 2);
3386 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3387 tt_int_op(min,OP_EQ, 1);
3388 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3390 /* ignore exact spelling of "minute(s)," and "second(s)" */
3391 format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
3392 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3393 r = tor_sscanf(dbuf, TL_ " " TL_,
3394 &min, label_m, &sec, label_s);
3395 tt_int_op(r,OP_EQ, 4);
3396 tt_int_op(min,OP_EQ, 1);
3397 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3398 tt_int_op(sec,OP_EQ, 1);
3399 tt_ci_char_op(label_s[0],OP_EQ, 's');
3400 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3402 format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
3403 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3404 r = tor_sscanf(dbuf, TL_ " " TL_,
3405 &min, label_m, &sec, label_s);
3406 tt_int_op(r,OP_EQ, 4);
3407 tt_int_op(min,OP_EQ, 1);
3408 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3409 tt_int_op(sec,OP_EQ, 59);
3410 tt_ci_char_op(label_s[0],OP_EQ, 's');
3412 /* ignore trailing "0 second(s)", if present */
3413 format_time_interval(dbuf, sizeof(dbuf), 60*2);
3414 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3415 r = tor_sscanf(dbuf, TL_, &min, label_m);
3416 tt_int_op(r,OP_EQ, 2);
3417 tt_int_op(min,OP_EQ, 2);
3418 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3420 /* ignore exact spelling of "minute(s)," and "second(s)" */
3421 format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
3422 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3423 r = tor_sscanf(dbuf, TL_ " " TL_,
3424 &min, label_m, &sec, label_s);
3425 tt_int_op(r,OP_EQ, 4);
3426 tt_int_op(min,OP_EQ, 2);
3427 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3428 tt_int_op(sec,OP_EQ, 1);
3429 tt_ci_char_op(label_s[0],OP_EQ, 's');
3431 format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
3432 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3433 r = tor_sscanf(dbuf, TL_ " " TL_,
3434 &min, label_m, &sec, label_s);
3435 tt_int_op(r,OP_EQ, 4);
3436 tt_int_op(min,OP_EQ, 59);
3437 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3438 tt_int_op(sec,OP_EQ, 59);
3439 tt_ci_char_op(label_s[0],OP_EQ, 's');
3441 /* negative minutes are reported as their absolute value */
3443 /* ignore trailing "0 second(s)", if present */
3444 format_time_interval(dbuf, sizeof(dbuf), -3*60);
3445 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3446 r = tor_sscanf(dbuf, TL_, &min, label_m);
3447 tt_int_op(r,OP_EQ, 2);
3448 tt_int_op(min,OP_EQ, 3);
3449 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3451 /* ignore exact spelling of "minute(s)," and "second(s)" */
3452 format_time_interval(dbuf, sizeof(dbuf), -96);
3453 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3454 r = tor_sscanf(dbuf, TL_ " " TL_,
3455 &min, label_m, &sec, label_s);
3456 tt_int_op(r,OP_EQ, 4);
3457 tt_int_op(min,OP_EQ, 1);
3458 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3459 tt_int_op(sec,OP_EQ, 36);
3460 tt_ci_char_op(label_s[0],OP_EQ, 's');
3462 format_time_interval(dbuf, sizeof(dbuf), -2815);
3463 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3464 r = tor_sscanf(dbuf, TL_ " " TL_,
3465 &min, label_m, &sec, label_s);
3466 tt_int_op(r,OP_EQ, 4);
3467 tt_int_op(min,OP_EQ, 46);
3468 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3469 tt_int_op(sec,OP_EQ, 55);
3470 tt_ci_char_op(label_s[0],OP_EQ, 's');
3472 /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
3473 /* always ignore trailing seconds, if present */
3475 /* ignore trailing "0 minute(s)" etc., if present */
3476 format_time_interval(dbuf, sizeof(dbuf), 60*60);
3477 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3478 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3479 tt_int_op(r,OP_EQ, 2);
3480 tt_int_op(hour,OP_EQ, 1);
3481 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3483 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
3484 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3485 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3486 tt_int_op(r,OP_EQ, 2);
3487 tt_int_op(hour,OP_EQ, 1);
3488 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3490 /* ignore exact spelling of "hour(s)," etc. */
3491 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
3492 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3493 r = tor_sscanf(dbuf, TL_ " " TL_,
3494 &hour, label_h, &min, label_m);
3495 tt_int_op(r,OP_EQ, 4);
3496 tt_int_op(hour,OP_EQ, 1);
3497 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3498 tt_int_op(min,OP_EQ, 1);
3499 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3501 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
3502 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3503 r = tor_sscanf(dbuf, TL_ " " TL_,
3504 &hour, label_h, &min, label_m);
3505 tt_int_op(r,OP_EQ, 4);
3506 tt_int_op(hour,OP_EQ, 23);
3507 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3508 tt_int_op(min,OP_EQ, 59);
3509 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3511 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
3512 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3513 r = tor_sscanf(dbuf, TL_ " " TL_,
3514 &hour, label_h, &min, label_m);
3515 tt_int_op(r,OP_EQ, 4);
3516 tt_int_op(hour,OP_EQ, 23);
3517 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3518 tt_int_op(min,OP_EQ, 59);
3519 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3521 /* negative hours are reported as their absolute value */
3523 /* ignore exact spelling of "hour(s)," etc., if present */
3524 format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
3525 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3526 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3527 tt_int_op(r,OP_EQ, 2);
3528 tt_int_op(hour,OP_EQ, 2);
3529 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3531 format_time_interval(dbuf, sizeof(dbuf), -75804);
3532 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3533 r = tor_sscanf(dbuf, TL_ " " TL_,
3534 &hour, label_h, &min, label_m);
3535 tt_int_op(r,OP_EQ, 4);
3536 tt_int_op(hour,OP_EQ, 21);
3537 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3538 tt_int_op(min,OP_EQ, 3);
3539 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3541 /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
3542 /* always ignore trailing seconds, if present */
3544 /* ignore trailing "0 hours(s)" etc., if present */
3545 format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
3546 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3547 r = tor_sscanf(dbuf, TL_, &day, label_d);
3548 tt_int_op(r,OP_EQ, 2);
3549 tt_int_op(day,OP_EQ, 1);
3550 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3552 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
3553 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3554 r = tor_sscanf(dbuf, TL_, &day, label_d);
3555 tt_int_op(r,OP_EQ, 2);
3556 tt_int_op(day,OP_EQ, 1);
3557 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3559 /* ignore exact spelling of "days(s)," etc. */
3560 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
3561 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3562 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3563 &day, label_d, &hour, label_h, &min, label_m);
3564 if (r == -1) {
3565 /* ignore 0 hours(s), if present */
3566 r = tor_sscanf(dbuf, TL_ " " TL_,
3567 &day, label_d, &min, label_m);
3569 tt_assert(r == 4 || r == 6);
3570 tt_int_op(day,OP_EQ, 1);
3571 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3572 if (r == 6) {
3573 tt_int_op(hour,OP_EQ, 0);
3574 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3576 tt_int_op(min,OP_EQ, 1);
3577 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3579 /* ignore trailing "0 minutes(s)" etc., if present */
3580 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
3581 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3582 r = tor_sscanf(dbuf, TL_ " " TL_,
3583 &day, label_d, &hour, label_h);
3584 tt_int_op(r,OP_EQ, 4);
3585 tt_int_op(day,OP_EQ, 1);
3586 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3587 tt_int_op(hour,OP_EQ, 1);
3588 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3590 /* negative days are reported as their absolute value */
3592 format_time_interval(dbuf, sizeof(dbuf), -21936184);
3593 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3594 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3595 &day, label_d, &hour, label_h, &min, label_m);
3596 tt_int_op(r,OP_EQ, 6);
3597 tt_int_op(day,OP_EQ, 253);
3598 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3599 tt_int_op(hour,OP_EQ, 21);
3600 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3601 tt_int_op(min,OP_EQ, 23);
3602 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3604 /* periods > 1 year are reported in days (warn?) */
3606 /* ignore exact spelling of "days(s)," etc., if present */
3607 format_time_interval(dbuf, sizeof(dbuf), 758635154);
3608 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3609 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3610 &day, label_d, &hour, label_h, &min, label_m);
3611 tt_int_op(r,OP_EQ, 6);
3612 tt_int_op(day,OP_EQ, 8780);
3613 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3614 tt_int_op(hour,OP_EQ, 11);
3615 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3616 tt_int_op(min,OP_EQ, 59);
3617 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3619 /* negative periods > 1 year are reported in days (warn?) */
3621 format_time_interval(dbuf, sizeof(dbuf), -1427014922);
3622 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3623 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3624 &day, label_d, &hour, label_h, &min, label_m);
3625 tt_int_op(r,OP_EQ, 6);
3626 tt_int_op(day,OP_EQ, 16516);
3627 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3628 tt_int_op(hour,OP_EQ, 9);
3629 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3630 tt_int_op(min,OP_EQ, 2);
3631 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3633 #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
3635 /* We can try INT32_MIN/MAX */
3636 /* Always ignore second(s) */
3638 /* INT32_MAX */
3639 format_time_interval(dbuf, sizeof(dbuf), 2147483647);
3640 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3641 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3642 &day, label_d, &hour, label_h, &min, label_m);
3643 tt_int_op(r,OP_EQ, 6);
3644 tt_int_op(day,OP_EQ, 24855);
3645 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3646 tt_int_op(hour,OP_EQ, 3);
3647 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3648 tt_int_op(min,OP_EQ, 14);
3649 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3650 /* and 7 seconds - ignored */
3652 /* INT32_MIN: check that we get the absolute value of interval,
3653 * which doesn't actually fit in int32_t.
3654 * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
3655 format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
3656 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3657 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3658 &day, label_d, &hour, label_h, &min, label_m);
3659 tt_int_op(r,OP_EQ, 6);
3660 tt_int_op(day,OP_EQ, 24855);
3661 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3662 tt_int_op(hour,OP_EQ, 3);
3663 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3664 tt_int_op(min,OP_EQ, 14);
3665 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3666 /* and 7 or 8 seconds - ignored */
3668 #endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */
3670 #if SIZEOF_LONG == 8
3672 /* We can try INT64_MIN/MAX */
3673 /* Always ignore second(s) */
3675 /* INT64_MAX */
3676 format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
3677 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3678 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3679 &day, label_d, &hour, label_h, &min, label_m);
3680 tt_int_op(r,OP_EQ, 6);
3681 tt_int_op(day,OP_EQ, 106751991167300L);
3682 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3683 tt_int_op(hour,OP_EQ, 15);
3684 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3685 tt_int_op(min,OP_EQ, 30);
3686 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3687 /* and 7 seconds - ignored */
3689 /* INT64_MIN: check that we get the absolute value of interval,
3690 * which doesn't actually fit in int64_t.
3691 * We expect INT64_MAX */
3692 format_time_interval(dbuf, sizeof(dbuf),
3693 -9223372036854775807L - 1L);
3694 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3695 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3696 &day, label_d, &hour, label_h, &min, label_m);
3697 tt_int_op(r,OP_EQ, 6);
3698 tt_int_op(day,OP_EQ, 106751991167300L);
3699 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3700 tt_int_op(hour,OP_EQ, 15);
3701 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3702 tt_int_op(min,OP_EQ, 30);
3703 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3704 /* and 7 or 8 seconds - ignored */
3706 #endif /* SIZEOF_LONG == 8 */
3708 done:
3712 #undef tt_char_op
3713 #undef tt_ci_char_op
3714 #undef DBUF_SIZE
3715 #undef T_
3716 #undef LABEL_SIZE
3717 #undef L_
3718 #undef TL_
3720 static void
3721 test_util_path_is_relative(void *arg)
3723 /* OS-independent tests */
3724 (void)arg;
3725 tt_int_op(1,OP_EQ, path_is_relative(""));
3726 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3727 tt_int_op(1,OP_EQ, path_is_relative("dir/"));
3728 tt_int_op(1,OP_EQ, path_is_relative("./dir"));
3729 tt_int_op(1,OP_EQ, path_is_relative("../dir"));
3731 tt_int_op(0,OP_EQ, path_is_relative("/"));
3732 tt_int_op(0,OP_EQ, path_is_relative("/dir"));
3733 tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
3735 /* Windows */
3736 #ifdef _WIN32
3737 /* I don't have Windows so I can't test this, hence the "#ifdef
3738 0". These are tests that look useful, so please try to get them
3739 running and uncomment if it all works as it should */
3740 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3741 tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
3742 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
3743 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
3744 tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
3746 tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
3747 tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
3748 tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
3749 #endif /* defined(_WIN32) */
3751 done:
3755 /** Run unittests for memory area allocator */
3756 static void
3757 test_util_memarea(void *arg)
3759 memarea_t *area = memarea_new();
3760 char *p1, *p2, *p3, *p1_orig;
3761 void *malloced_ptr = NULL;
3762 int i;
3764 #ifdef DISABLE_MEMORY_SENTINELS
3765 /* If memory sentinels are disabled, this whole module is just an alias for
3766 malloc(), which is free to lay out memory most any way it wants. */
3767 if (1)
3768 tt_skip();
3769 #endif /* defined(DISABLE_MEMORY_SENTINELS) */
3771 (void)arg;
3772 tt_assert(area);
3774 p1_orig = p1 = memarea_alloc(area,64);
3775 p2 = memarea_alloc_zero(area,52);
3776 p3 = memarea_alloc(area,11);
3778 tt_assert(memarea_owns_ptr(area, p1));
3779 tt_assert(memarea_owns_ptr(area, p2));
3780 tt_assert(memarea_owns_ptr(area, p3));
3781 /* Make sure we left enough space. */
3782 tt_assert(p1+64 <= p2);
3783 tt_assert(p2+52 <= p3);
3784 /* Make sure we aligned. */
3785 tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
3786 tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
3787 tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
3788 tt_assert(!memarea_owns_ptr(area, p3+8192));
3789 tt_assert(!memarea_owns_ptr(area, p3+30));
3790 tt_assert(tor_mem_is_zero(p2, 52));
3791 /* Make sure we don't overalign. */
3792 p1 = memarea_alloc(area, 1);
3793 p2 = memarea_alloc(area, 1);
3794 tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
3796 malloced_ptr = tor_malloc(64);
3797 tt_assert(!memarea_owns_ptr(area, malloced_ptr));
3798 tor_free(malloced_ptr);
3801 /* memarea_memdup */
3803 malloced_ptr = tor_malloc(64);
3804 crypto_rand((char*)malloced_ptr, 64);
3805 p1 = memarea_memdup(area, malloced_ptr, 64);
3806 tt_assert(p1 != malloced_ptr);
3807 tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
3808 tor_free(malloced_ptr);
3811 /* memarea_strdup. */
3812 p1 = memarea_strdup(area,"");
3813 p2 = memarea_strdup(area, "abcd");
3814 tt_assert(p1);
3815 tt_assert(p2);
3816 tt_str_op(p1,OP_EQ, "");
3817 tt_str_op(p2,OP_EQ, "abcd");
3819 /* memarea_strndup. */
3821 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
3822 /* (From Turandot, act 3.) */
3823 size_t len = strlen(s);
3824 p1 = memarea_strndup(area, s, 1000);
3825 p2 = memarea_strndup(area, s, 10);
3826 tt_str_op(p1,OP_EQ, s);
3827 tt_assert(p2 >= p1 + len + 1);
3828 tt_mem_op(s,OP_EQ, p2, 10);
3829 tt_int_op(p2[10],OP_EQ, '\0');
3830 p3 = memarea_strndup(area, s, len);
3831 tt_str_op(p3,OP_EQ, s);
3832 p3 = memarea_strndup(area, s, len-1);
3833 tt_mem_op(s,OP_EQ, p3, len-1);
3834 tt_int_op(p3[len-1],OP_EQ, '\0');
3837 memarea_clear(area);
3838 p1 = memarea_alloc(area, 1);
3839 tt_ptr_op(p1,OP_EQ, p1_orig);
3840 memarea_clear(area);
3841 size_t total = 0, initial_allocation, allocation2, dummy;
3842 memarea_get_stats(area, &initial_allocation, &dummy);
3844 /* Check for running over an area's size. */
3845 for (i = 0; i < 4096; ++i) {
3846 size_t n = crypto_rand_int(6);
3847 p1 = memarea_alloc(area, n);
3848 total += n;
3849 tt_assert(memarea_owns_ptr(area, p1));
3851 memarea_assert_ok(area);
3852 memarea_get_stats(area, &allocation2, &dummy);
3853 /* Make sure we can allocate a too-big object. */
3854 p1 = memarea_alloc_zero(area, 9000);
3855 p2 = memarea_alloc_zero(area, 16);
3856 total += 9000;
3857 total += 16;
3858 tt_assert(memarea_owns_ptr(area, p1));
3859 tt_assert(memarea_owns_ptr(area, p2));
3861 /* Now test stats... */
3862 size_t allocated = 0, used = 0;
3863 memarea_get_stats(area, &allocated, &used);
3864 tt_int_op(used, OP_LE, allocated);
3865 tt_int_op(used, OP_GE, total); /* not EQ, because of alignment and headers*/
3866 tt_int_op(allocated, OP_GT, allocation2);
3868 tt_int_op(allocation2, OP_GT, initial_allocation);
3870 memarea_clear(area);
3871 memarea_get_stats(area, &allocated, &used);
3872 tt_int_op(used, OP_LT, 128); /* Not 0, because of header */
3873 tt_int_op(allocated, OP_EQ, initial_allocation);
3875 done:
3876 memarea_drop_all(area);
3877 tor_free(malloced_ptr);
3880 /** Run unit tests for utility functions to get file names relative to
3881 * the data directory. */
3882 static void
3883 test_util_datadir(void *arg)
3885 char buf[1024];
3886 char *f = NULL;
3887 char *temp_dir = NULL;
3889 (void)arg;
3890 temp_dir = get_datadir_fname(NULL);
3891 f = get_datadir_fname("state");
3892 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
3893 tt_str_op(f,OP_EQ, buf);
3894 tor_free(f);
3895 f = get_datadir_fname2("cache", "thingy");
3896 tor_snprintf(buf, sizeof(buf),
3897 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
3898 tt_str_op(f,OP_EQ, buf);
3899 tor_free(f);
3900 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
3901 tor_snprintf(buf, sizeof(buf),
3902 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
3903 tt_str_op(f,OP_EQ, buf);
3904 tor_free(f);
3905 f = get_datadir_fname_suffix("cache", ".foo");
3906 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
3907 temp_dir);
3908 tt_str_op(f,OP_EQ, buf);
3910 done:
3911 tor_free(f);
3912 tor_free(temp_dir);
3915 static void
3916 test_util_strtok(void *arg)
3918 char buf[128];
3919 char buf2[128];
3920 int i;
3921 char *cp1, *cp2;
3923 (void)arg;
3924 for (i = 0; i < 3; i++) {
3925 const char *pad1="", *pad2="";
3926 switch (i) {
3927 case 0:
3928 break;
3929 case 1:
3930 pad1 = " ";
3931 pad2 = "!";
3932 break;
3933 case 2:
3934 pad1 = " ";
3935 pad2 = ";!";
3936 break;
3938 tor_snprintf(buf, sizeof(buf), "%s", pad1);
3939 tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
3940 tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL);
3941 tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL);
3943 tor_snprintf(buf, sizeof(buf),
3944 "%sGraved on the dark in gestures of descent%s", pad1, pad1);
3945 tor_snprintf(buf2, sizeof(buf2),
3946 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
3947 /* -- "Year's End", Richard Wilbur */
3949 tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3950 tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
3951 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
3952 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
3953 tt_str_op("on",OP_EQ, S1());
3954 tt_str_op("the",OP_EQ, S1());
3955 tt_str_op("dark",OP_EQ, S1());
3956 tt_str_op("seemed",OP_EQ, S2());
3957 tt_str_op("their",OP_EQ, S2());
3958 tt_str_op("own",OP_EQ, S2());
3959 tt_str_op("in",OP_EQ, S1());
3960 tt_str_op("gestures",OP_EQ, S1());
3961 tt_str_op("of",OP_EQ, S1());
3962 tt_str_op("most",OP_EQ, S2());
3963 tt_str_op("perfect",OP_EQ, S2());
3964 tt_str_op("descent",OP_EQ, S1());
3965 tt_str_op("monument",OP_EQ, S2());
3966 tt_ptr_op(NULL,OP_EQ, S1());
3967 tt_ptr_op(NULL,OP_EQ, S2());
3970 buf[0] = 0;
3971 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3972 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
3974 strlcpy(buf, "Howdy!", sizeof(buf));
3975 tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
3976 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
3978 strlcpy(buf, " ", sizeof(buf));
3979 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3980 strlcpy(buf, " ", sizeof(buf));
3981 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3983 strlcpy(buf, "something ", sizeof(buf));
3984 tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3985 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
3986 done:
3990 static void
3991 test_util_find_str_at_start_of_line(void *ptr)
3993 const char *long_string =
3994 "howdy world. how are you? i hope it's fine.\n"
3995 "hello kitty\n"
3996 "third line";
3997 char *line2 = strchr(long_string,'\n')+1;
3998 char *line3 = strchr(line2,'\n')+1;
3999 const char *short_string = "hello kitty\n"
4000 "second line\n";
4001 char *short_line2 = strchr(short_string,'\n')+1;
4003 (void)ptr;
4005 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
4006 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
4007 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
4008 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
4009 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
4010 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
4011 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
4012 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
4013 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
4014 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
4015 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
4016 tt_ptr_op(line2,OP_EQ,
4017 find_str_at_start_of_line(long_string, "hello kitty\n"));
4018 tt_ptr_op(line2,OP_EQ,
4019 find_str_at_start_of_line(long_string, "hello kitty\nt"));
4020 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
4021 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
4022 tt_ptr_op(NULL, OP_EQ,
4023 find_str_at_start_of_line(long_string, "third line\n"));
4024 tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
4025 "second line\n"));
4026 done:
4030 static void
4031 test_util_string_is_C_identifier(void *ptr)
4033 (void)ptr;
4035 tt_int_op(1,OP_EQ, string_is_C_identifier("string_is_C_identifier"));
4036 tt_int_op(1,OP_EQ, string_is_C_identifier("_string_is_C_identifier"));
4037 tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
4038 tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
4039 tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
4040 tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
4041 tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
4042 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4043 tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
4044 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4046 tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
4047 tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
4048 tt_int_op(0,OP_EQ, string_is_C_identifier(""));
4049 tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
4050 tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
4051 tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
4052 tt_int_op(0,OP_EQ, string_is_C_identifier("í"));
4053 tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
4055 done:
4059 static void
4060 test_util_string_is_utf8(void *ptr)
4062 (void)ptr;
4064 tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0));
4065 tt_int_op(1, OP_EQ, string_is_utf8("", 1));
4066 tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3));
4067 tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3));
4068 tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7));
4069 tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9));
4071 /* Test the utf8_no_bom function */
4072 tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFF", 3));
4073 tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFFFE", 3));
4074 tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFFlove", 7));
4075 tt_int_op(1, OP_EQ, string_is_utf8_no_bom("loveandrespect",
4076 strlen("loveandrespect")));
4078 // Validate exactly 'len' bytes.
4079 tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2));
4080 tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6));
4082 // Reject sequences with missing bytes.
4083 tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1));
4084 tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1));
4085 tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2));
4086 tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2));
4087 tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3));
4088 tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3));
4089 tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4));
4091 // Reject encodings that are overly long.
4092 tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2));
4093 tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2));
4094 tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3));
4095 tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3));
4096 tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4));
4097 tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4));
4099 // Reject UTF-16 surrogate halves.
4100 tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3));
4101 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3));
4102 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
4103 tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
4105 // The maximum legal codepoint, 10FFFF.
4106 tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
4107 tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
4109 done:
4113 static void
4114 test_util_asprintf(void *ptr)
4116 #define LOREMIPSUM \
4117 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
4118 char *cp=NULL, *cp2=NULL;
4119 int r;
4120 (void)ptr;
4122 /* simple string */
4123 r = tor_asprintf(&cp, "simple string 100%% safe");
4124 tt_assert(cp);
4125 tt_str_op("simple string 100% safe",OP_EQ, cp);
4126 tt_int_op(strlen(cp),OP_EQ, r);
4127 tor_free(cp);
4129 /* empty string */
4130 r = tor_asprintf(&cp, "%s", "");
4131 tt_assert(cp);
4132 tt_str_op("",OP_EQ, cp);
4133 tt_int_op(strlen(cp),OP_EQ, r);
4134 tor_free(cp);
4136 /* numbers (%i) */
4137 r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
4138 tt_assert(cp);
4139 tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
4140 tt_int_op(strlen(cp),OP_EQ, r);
4141 /* don't free cp; next test uses it. */
4143 /* numbers (%d) */
4144 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
4145 tt_assert(cp2);
4146 tt_int_op(strlen(cp2),OP_EQ, r);
4147 tt_str_op("First=101, Second=202",OP_EQ, cp2);
4148 tt_assert(cp != cp2);
4149 tor_free(cp);
4150 tor_free(cp2);
4152 /* Glass-box test: a string exactly 128 characters long. */
4153 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
4154 tt_assert(cp);
4155 tt_int_op(128,OP_EQ, r);
4156 tt_int_op(cp[128], OP_EQ, '\0');
4157 tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
4158 tor_free(cp);
4160 /* String longer than 128 characters */
4161 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
4162 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
4163 tt_assert(cp);
4164 tt_int_op(strlen(cp),OP_EQ, r);
4165 tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
4167 done:
4168 tor_free(cp);
4169 tor_free(cp2);
4172 static void
4173 test_util_listdir(void *ptr)
4175 smartlist_t *dir_contents = NULL;
4176 char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
4177 int r;
4178 (void)ptr;
4180 fname1 = tor_strdup(get_fname("hopscotch"));
4181 fname2 = tor_strdup(get_fname("mumblety-peg"));
4182 fname3 = tor_strdup(get_fname(".hidden-file"));
4183 dir1 = tor_strdup(get_fname("some-directory"));
4184 dirname = tor_strdup(get_fname(NULL));
4186 tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
4187 tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
4188 tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
4189 #ifdef _WIN32
4190 r = mkdir(dir1);
4191 #else
4192 r = mkdir(dir1, 0700);
4193 #endif
4194 if (r) {
4195 fprintf(stderr, "Can't create directory %s:", dir1);
4196 perror("");
4197 exit(1);
4200 dir_contents = tor_listdir(dirname);
4201 tt_assert(dir_contents);
4202 /* make sure that each filename is listed. */
4203 tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
4204 tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
4205 tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
4206 tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
4208 tt_assert(!smartlist_contains_string(dir_contents, "."));
4209 tt_assert(!smartlist_contains_string(dir_contents, ".."));
4211 done:
4212 tor_free(fname1);
4213 tor_free(fname2);
4214 tor_free(fname3);
4215 tor_free(dir1);
4216 tor_free(dirname);
4217 if (dir_contents) {
4218 SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
4219 smartlist_free(dir_contents);
4223 static void
4224 test_util_parent_dir(void *ptr)
4226 char *cp;
4227 (void)ptr;
4229 #define T(output,expect_ok,input) \
4230 do { \
4231 int ok; \
4232 cp = tor_strdup(input); \
4233 ok = get_parent_directory(cp); \
4234 tt_int_op(expect_ok, OP_EQ, ok); \
4235 if (ok==0) \
4236 tt_str_op(output, OP_EQ, cp); \
4237 tor_free(cp); \
4238 } while (0);
4240 T("/home/wombat", 0, "/home/wombat/knish");
4241 T("/home/wombat", 0, "/home/wombat/knish/");
4242 T("/home/wombat", 0, "/home/wombat/knish///");
4243 T("./home/wombat", 0, "./home/wombat/knish/");
4244 T("/", 0, "/home");
4245 T("/", 0, "/home//");
4246 T(".", 0, "./wombat");
4247 T(".", 0, "./wombat/");
4248 T(".", 0, "./wombat//");
4249 T("wombat", 0, "wombat/foo");
4250 T("wombat/..", 0, "wombat/../foo");
4251 T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
4252 T("wombat/.", 0, "wombat/./foo");
4253 T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
4254 T("wombat", 0, "wombat/..//");
4255 T("wombat", 0, "wombat/foo/");
4256 T("wombat", 0, "wombat/.foo");
4257 T("wombat", 0, "wombat/.foo/");
4259 T("wombat", -1, "");
4260 T("w", -1, "");
4261 T("wombat", 0, "wombat/knish");
4263 T("/", 0, "/");
4264 T("/", 0, "////");
4266 done:
4267 tor_free(cp);
4270 static void
4271 test_util_ftruncate(void *ptr)
4273 char *buf = NULL;
4274 const char *fname;
4275 int fd = -1;
4276 const char *message = "Hello world";
4277 const char *message2 = "Hola mundo";
4278 struct stat st;
4280 (void) ptr;
4282 fname = get_fname("ftruncate");
4284 fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
4285 tt_int_op(fd, OP_GE, 0);
4287 /* Make the file be there. */
4288 tt_int_op(strlen(message), OP_EQ,
4289 write_all_to_fd(fd, message, strlen(message)));
4290 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
4291 tt_int_op(0, OP_EQ, fstat(fd, &st));
4292 tt_int_op((int)st.st_size, OP_EQ, strlen(message));
4294 /* Truncate and see if it got truncated */
4295 tt_int_op(0, OP_EQ, tor_ftruncate(fd));
4296 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
4297 tt_int_op(0, OP_EQ, fstat(fd, &st));
4298 tt_int_op((int)st.st_size, OP_EQ, 0);
4300 /* Replace, and see if it got replaced */
4301 tt_int_op(strlen(message2), OP_EQ,
4302 write_all_to_fd(fd, message2, strlen(message2)));
4303 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
4304 tt_int_op(0, OP_EQ, fstat(fd, &st));
4305 tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
4307 close(fd);
4308 fd = -1;
4310 buf = read_file_to_str(fname, 0, NULL);
4311 tt_str_op(message2, OP_EQ, buf);
4313 done:
4314 if (fd >= 0)
4315 close(fd);
4316 tor_free(buf);
4319 static void
4320 test_util_num_cpus(void *arg)
4322 (void)arg;
4323 int num = compute_num_cpus();
4324 if (num < 0)
4325 tt_skip();
4327 tt_int_op(num, OP_GE, 1);
4328 tt_int_op(num, OP_LE, 16);
4330 done:
4334 #ifdef _WIN32
4335 static void
4336 test_util_load_win_lib(void *ptr)
4338 HANDLE h = load_windows_system_library(_T("advapi32.dll"));
4339 (void) ptr;
4341 tt_assert(h);
4342 done:
4343 if (h)
4344 FreeLibrary(h);
4346 #endif /* defined(_WIN32) */
4349 * Test for format_hex_number_sigsafe()
4352 static void
4353 test_util_format_hex_number(void *ptr)
4355 int i, len;
4356 char buf[33];
4357 const struct {
4358 const char *str;
4359 unsigned int x;
4360 } test_data[] = {
4361 {"0", 0},
4362 {"1", 1},
4363 {"273A", 0x273a},
4364 {"FFFF", 0xffff},
4365 {"7FFFFFFF", 0x7fffffff},
4366 {"FFFFFFFF", 0xffffffff},
4367 #if UINT_MAX >= 0xffffffff
4368 {"31BC421D", 0x31bc421d},
4369 {"FFFFFFFF", 0xffffffff},
4370 #endif
4371 {NULL, 0}
4374 (void)ptr;
4376 for (i = 0; test_data[i].str != NULL; ++i) {
4377 len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
4378 tt_int_op(len,OP_NE, 0);
4379 tt_int_op(len,OP_EQ, strlen(buf));
4380 tt_str_op(buf,OP_EQ, test_data[i].str);
4383 tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
4384 tt_str_op(buf,OP_EQ, "FFFF");
4385 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
4386 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
4388 done:
4389 return;
4393 * Test for format_hex_number_sigsafe()
4396 static void
4397 test_util_format_dec_number(void *ptr)
4399 int i, len;
4400 char buf[33];
4401 const struct {
4402 const char *str;
4403 unsigned int x;
4404 } test_data[] = {
4405 {"0", 0},
4406 {"1", 1},
4407 {"1234", 1234},
4408 {"12345678", 12345678},
4409 {"99999999", 99999999},
4410 {"100000000", 100000000},
4411 {"4294967295", 4294967295u},
4412 #if UINT_MAX > 0xffffffff
4413 {"18446744073709551615", 18446744073709551615u },
4414 #endif
4415 {NULL, 0}
4418 (void)ptr;
4420 for (i = 0; test_data[i].str != NULL; ++i) {
4421 len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
4422 tt_int_op(len,OP_NE, 0);
4423 tt_int_op(len,OP_EQ, strlen(buf));
4424 tt_str_op(buf,OP_EQ, test_data[i].str);
4426 len = format_dec_number_sigsafe(test_data[i].x, buf,
4427 (int)(strlen(test_data[i].str) + 1));
4428 tt_int_op(len,OP_EQ, strlen(buf));
4429 tt_str_op(buf,OP_EQ, test_data[i].str);
4432 tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
4433 tt_str_op(buf,OP_EQ, "7331");
4434 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
4435 tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
4436 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
4438 done:
4439 return;
4442 #define MAX_SPLIT_LINE_COUNT 4
4443 struct split_lines_test_t {
4444 const char *orig_line; // Line to be split (may contain \0's)
4445 int orig_length; // Length of orig_line
4446 const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
4449 static void
4450 test_util_di_ops(void *arg)
4452 #define LT -1
4453 #define GT 1
4454 #define EQ 0
4455 const struct {
4456 const char *a; int want_sign; const char *b;
4457 } examples[] = {
4458 { "Foo", EQ, "Foo" },
4459 { "foo", GT, "bar", },
4460 { "foobar", EQ ,"foobar" },
4461 { "foobar", LT, "foobaw" },
4462 { "foobar", GT, "f00bar" },
4463 { "foobar", GT, "boobar" },
4464 { "", EQ, "" },
4465 { NULL, 0, NULL },
4468 int i;
4470 (void)arg;
4471 for (i = 0; examples[i].a; ++i) {
4472 size_t len = strlen(examples[i].a);
4473 int eq1, eq2, neq1, neq2, cmp1, cmp2;
4474 tt_int_op(len,OP_EQ, strlen(examples[i].b));
4475 /* We do all of the operations, with operands in both orders. */
4476 eq1 = tor_memeq(examples[i].a, examples[i].b, len);
4477 eq2 = tor_memeq(examples[i].b, examples[i].a, len);
4478 neq1 = tor_memneq(examples[i].a, examples[i].b, len);
4479 neq2 = tor_memneq(examples[i].b, examples[i].a, len);
4480 cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
4481 cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
4483 /* Check for correctness of cmp1 */
4484 if (cmp1 < 0 && examples[i].want_sign != LT)
4485 TT_DIE(("Assertion failed."));
4486 else if (cmp1 > 0 && examples[i].want_sign != GT)
4487 TT_DIE(("Assertion failed."));
4488 else if (cmp1 == 0 && examples[i].want_sign != EQ)
4489 TT_DIE(("Assertion failed."));
4491 /* Check for consistency of everything else with cmp1 */
4492 tt_int_op(eq1,OP_EQ, eq2);
4493 tt_int_op(neq1,OP_EQ, neq2);
4494 tt_int_op(cmp1,OP_EQ, -cmp2);
4495 tt_int_op(eq1,OP_EQ, cmp1 == 0);
4496 tt_int_op(neq1,OP_EQ, !eq1);
4500 uint8_t zz = 0;
4501 uint8_t ii = 0;
4502 int z;
4504 /* exhaustively test tor_memeq and tor_memcmp
4505 * against each possible single-byte numeric difference
4506 * some arithmetic bugs only appear with certain bit patterns */
4507 for (z = 0; z < 256; z++) {
4508 for (i = 0; i < 256; i++) {
4509 ii = (uint8_t)i;
4510 zz = (uint8_t)z;
4511 tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
4512 tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
4513 zz > ii ? GT : EQ);
4514 tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
4515 ii < zz ? LT : EQ);
4520 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
4521 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
4522 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
4523 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
4524 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
4525 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
4526 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
4527 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
4528 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
4530 done:
4534 static void
4535 test_util_di_map(void *arg)
4537 (void)arg;
4538 di_digest256_map_t *dimap = NULL;
4539 uint8_t key1[] = "Robert Anton Wilson ";
4540 uint8_t key2[] = "Martin Gardner, _Fads&fallacies";
4541 uint8_t key3[] = "Tom Lehrer, _Be Prepared_. ";
4542 uint8_t key4[] = "Ursula Le Guin,_A Wizard of... ";
4544 char dflt_entry[] = "'You have made a good beginning', but no more";
4546 tt_int_op(32, OP_EQ, sizeof(key1));
4547 tt_int_op(32, OP_EQ, sizeof(key2));
4548 tt_int_op(32, OP_EQ, sizeof(key3));
4550 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry));
4552 char *str1 = tor_strdup("You are precisely as big as what you love"
4553 " and precisely as small as what you allow"
4554 " to annoy you.");
4555 char *str2 = tor_strdup("Let us hope that Lysenko's success in Russia will"
4556 " serve for many generations to come as another"
4557 " reminder to the world of how quickly and easily"
4558 " a science can be corrupted when ignorant"
4559 " political leaders deem themselves competent"
4560 " to arbitrate scientific disputes");
4561 char *str3 = tor_strdup("Don't write naughty words on walls "
4562 "if you can't spell.");
4564 dimap_add_entry(&dimap, key1, str1);
4565 dimap_add_entry(&dimap, key2, str2);
4566 dimap_add_entry(&dimap, key3, str3);
4568 tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry));
4569 tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry));
4570 tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry));
4571 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry));
4573 done:
4574 dimap_free(dimap, tor_free_);
4578 * Test counting high bits
4580 static void
4581 test_util_n_bits_set(void *ptr)
4583 (void)ptr;
4584 tt_int_op(0,OP_EQ, n_bits_set_u8(0));
4585 tt_int_op(1,OP_EQ, n_bits_set_u8(1));
4586 tt_int_op(3,OP_EQ, n_bits_set_u8(7));
4587 tt_int_op(1,OP_EQ, n_bits_set_u8(8));
4588 tt_int_op(2,OP_EQ, n_bits_set_u8(129));
4589 tt_int_op(8,OP_EQ, n_bits_set_u8(255));
4590 done:
4595 * Test LHS whitespace (and comment) eater
4597 static void
4598 test_util_eat_whitespace(void *ptr)
4600 const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
4601 char str[80];
4602 size_t i;
4604 (void)ptr;
4606 /* Try one leading ws */
4607 strlcpy(str, "fuubaar", sizeof(str));
4608 for (i = 0; i < sizeof(ws); ++i) {
4609 str[0] = ws[i];
4610 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
4611 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4612 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
4613 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4615 str[0] = '\n';
4616 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
4617 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4618 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4619 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4621 /* Empty string */
4622 strlcpy(str, "", sizeof(str));
4623 tt_ptr_op(str,OP_EQ, eat_whitespace(str));
4624 tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
4625 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4626 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
4628 /* Only ws */
4629 strlcpy(str, " \t\r\n", sizeof(str));
4630 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4631 tt_ptr_op(str + strlen(str),OP_EQ,
4632 eat_whitespace_eos(str, str + strlen(str)));
4633 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
4634 eat_whitespace_no_nl(str));
4635 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
4636 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4638 strlcpy(str, " \t\r ", sizeof(str));
4639 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4640 tt_ptr_op(str + strlen(str),OP_EQ,
4641 eat_whitespace_eos(str, str + strlen(str)));
4642 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
4643 tt_ptr_op(str + strlen(str),OP_EQ,
4644 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4646 /* Multiple ws */
4647 strlcpy(str, "fuubaar", sizeof(str));
4648 for (i = 0; i < sizeof(ws); ++i)
4649 str[i] = ws[i];
4650 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
4651 tt_ptr_op(str + sizeof(ws),OP_EQ,
4652 eat_whitespace_eos(str, str + strlen(str)));
4653 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
4654 tt_ptr_op(str + sizeof(ws),OP_EQ,
4655 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4657 /* Eat comment */
4658 strlcpy(str, "# Comment \n No Comment", sizeof(str));
4659 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
4660 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4661 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4662 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4664 /* Eat comment & ws mix */
4665 strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
4666 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
4667 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4668 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
4669 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4671 /* Eat entire comment */
4672 strlcpy(str, "#Comment", sizeof(str));
4673 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4674 tt_ptr_op(str + strlen(str),OP_EQ,
4675 eat_whitespace_eos(str, str + strlen(str)));
4676 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4677 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4679 /* Blank line, then comment */
4680 strlcpy(str, " \t\n # Comment", sizeof(str));
4681 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4682 tt_ptr_op(str + strlen(str),OP_EQ,
4683 eat_whitespace_eos(str, str + strlen(str)));
4684 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
4685 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4687 done:
4691 /** Return a newly allocated smartlist containing the lines of text in
4692 * <b>lines</b>. The returned strings are heap-allocated, and must be
4693 * freed by the caller.
4695 * XXXX? Move to container.[hc] ? */
4696 static smartlist_t *
4697 smartlist_new_from_text_lines(const char *lines)
4699 smartlist_t *sl = smartlist_new();
4700 char *last_line;
4702 smartlist_split_string(sl, lines, "\n", 0, 0);
4704 last_line = smartlist_pop_last(sl);
4705 if (last_line != NULL && *last_line != '\0') {
4706 smartlist_add(sl, last_line);
4707 } else {
4708 tor_free(last_line);
4711 return sl;
4714 /** Test smartlist_new_from_text_lines */
4715 static void
4716 test_util_sl_new_from_text_lines(void *ptr)
4718 (void)ptr;
4720 { /* Normal usage */
4721 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
4722 int sl_len = smartlist_len(sl);
4724 tt_want_int_op(sl_len, OP_EQ, 3);
4726 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
4727 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
4728 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
4730 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4731 smartlist_free(sl);
4734 { /* No final newline */
4735 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
4736 int sl_len = smartlist_len(sl);
4738 tt_want_int_op(sl_len, OP_EQ, 3);
4740 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
4741 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
4742 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
4744 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4745 smartlist_free(sl);
4748 { /* No newlines */
4749 smartlist_t *sl = smartlist_new_from_text_lines("foo");
4750 int sl_len = smartlist_len(sl);
4752 tt_want_int_op(sl_len, OP_EQ, 1);
4754 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
4756 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4757 smartlist_free(sl);
4760 { /* No text at all */
4761 smartlist_t *sl = smartlist_new_from_text_lines("");
4762 int sl_len = smartlist_len(sl);
4764 tt_want_int_op(sl_len, OP_EQ, 0);
4766 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4767 smartlist_free(sl);
4771 static void
4772 test_util_envnames(void *ptr)
4774 (void) ptr;
4776 tt_assert(environment_variable_names_equal("abc", "abc"));
4777 tt_assert(environment_variable_names_equal("abc", "abc="));
4778 tt_assert(environment_variable_names_equal("abc", "abc=def"));
4779 tt_assert(environment_variable_names_equal("abc=def", "abc"));
4780 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
4782 tt_assert(environment_variable_names_equal("abc", "abc"));
4783 tt_assert(environment_variable_names_equal("abc", "abc="));
4784 tt_assert(environment_variable_names_equal("abc", "abc=def"));
4785 tt_assert(environment_variable_names_equal("abc=def", "abc"));
4786 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
4788 tt_assert(!environment_variable_names_equal("abc", "abcd"));
4789 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
4790 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
4791 tt_assert(!environment_variable_names_equal("abc=", "def"));
4792 tt_assert(!environment_variable_names_equal("abc=", "def="));
4793 tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
4795 tt_assert(!environment_variable_names_equal("", "a=def"));
4796 /* A bit surprising. */
4797 tt_assert(environment_variable_names_equal("", "=def"));
4798 tt_assert(environment_variable_names_equal("=y", "=x"));
4800 done:
4804 /** Test process_environment_make */
4805 static void
4806 test_util_make_environment(void *ptr)
4808 const char *env_vars_string =
4809 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4810 "HOME=/home/foozer\n";
4811 const char expected_windows_env_block[] =
4812 "HOME=/home/foozer\000"
4813 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
4814 "\000";
4815 size_t expected_windows_env_block_len =
4816 sizeof(expected_windows_env_block) - 1;
4818 smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
4819 smartlist_t *env_vars_sorted = smartlist_new();
4820 smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
4822 process_environment_t *env;
4824 (void)ptr;
4826 env = process_environment_make(env_vars);
4828 /* Check that the Windows environment block is correct. */
4829 tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
4830 expected_windows_env_block_len));
4832 /* Now for the Unixoid environment block. We don't care which order
4833 * these environment variables are in, so we sort both lists first. */
4835 smartlist_add_all(env_vars_sorted, env_vars);
4838 char **v;
4839 for (v = env->unixoid_environment_block; *v; ++v) {
4840 smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
4844 smartlist_sort_strings(env_vars_sorted);
4845 smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
4847 tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
4848 smartlist_len(env_vars_in_unixoid_env_block_sorted));
4850 int len = smartlist_len(env_vars_sorted);
4851 int i;
4853 if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
4854 len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
4857 for (i = 0; i < len; ++i) {
4858 tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
4859 smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
4863 /* Clean up. */
4864 smartlist_free(env_vars_in_unixoid_env_block_sorted);
4865 smartlist_free(env_vars_sorted);
4867 SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
4868 smartlist_free(env_vars);
4870 process_environment_free(env);
4873 /** Test set_environment_variable_in_smartlist */
4874 static void
4875 test_util_set_env_var_in_sl(void *ptr)
4877 /* The environment variables in these strings are in arbitrary
4878 * order; we sort the resulting lists before comparing them.
4880 * (They *will not* end up in the order shown in
4881 * expected_resulting_env_vars_string.) */
4883 const char *base_env_vars_string =
4884 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4885 "HOME=/home/foozer\n"
4886 "TERM=xterm\n"
4887 "SHELL=/bin/ksh\n"
4888 "USER=foozer\n"
4889 "LOGNAME=foozer\n"
4890 "USERNAME=foozer\n"
4891 "LANG=en_US.utf8\n"
4894 const char *new_env_vars_string =
4895 "TERM=putty\n"
4896 "DISPLAY=:18.0\n"
4899 const char *expected_resulting_env_vars_string =
4900 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4901 "HOME=/home/foozer\n"
4902 "TERM=putty\n"
4903 "SHELL=/bin/ksh\n"
4904 "USER=foozer\n"
4905 "LOGNAME=foozer\n"
4906 "USERNAME=foozer\n"
4907 "LANG=en_US.utf8\n"
4908 "DISPLAY=:18.0\n"
4911 smartlist_t *merged_env_vars =
4912 smartlist_new_from_text_lines(base_env_vars_string);
4913 smartlist_t *new_env_vars =
4914 smartlist_new_from_text_lines(new_env_vars_string);
4915 smartlist_t *expected_resulting_env_vars =
4916 smartlist_new_from_text_lines(expected_resulting_env_vars_string);
4918 /* Elements of merged_env_vars are heap-allocated, and must be
4919 * freed. Some of them are (or should) be freed by
4920 * set_environment_variable_in_smartlist.
4922 * Elements of new_env_vars are heap-allocated, but are copied into
4923 * merged_env_vars, so they are not freed separately at the end of
4924 * the function.
4926 * Elements of expected_resulting_env_vars are heap-allocated, and
4927 * must be freed. */
4929 (void)ptr;
4931 SMARTLIST_FOREACH(new_env_vars, char *, env_var,
4932 set_environment_variable_in_smartlist(merged_env_vars,
4933 env_var,
4934 tor_free_,
4935 1));
4937 smartlist_sort_strings(merged_env_vars);
4938 smartlist_sort_strings(expected_resulting_env_vars);
4940 tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
4941 smartlist_len(expected_resulting_env_vars));
4943 int len = smartlist_len(merged_env_vars);
4944 int i;
4946 if (smartlist_len(expected_resulting_env_vars) < len) {
4947 len = smartlist_len(expected_resulting_env_vars);
4950 for (i = 0; i < len; ++i) {
4951 tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
4952 smartlist_get(expected_resulting_env_vars, i));
4956 /* Clean up. */
4957 SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
4958 smartlist_free(merged_env_vars);
4960 smartlist_free(new_env_vars);
4962 SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
4963 smartlist_free(expected_resulting_env_vars);
4966 static void
4967 test_util_weak_random(void *arg)
4969 int i, j, n[16];
4970 tor_weak_rng_t rng;
4971 (void) arg;
4973 tor_init_weak_random(&rng, (unsigned)time(NULL));
4975 for (i = 1; i <= 256; ++i) {
4976 for (j=0;j<100;++j) {
4977 int r = tor_weak_random_range(&rng, i);
4978 tt_int_op(0, OP_LE, r);
4979 tt_int_op(r, OP_LT, i);
4983 memset(n,0,sizeof(n));
4984 for (j=0;j<8192;++j) {
4985 n[tor_weak_random_range(&rng, 16)]++;
4988 for (i=0;i<16;++i)
4989 tt_int_op(n[i], OP_GT, 0);
4990 done:
4994 static void
4995 test_util_mathlog(void *arg)
4997 double d;
4998 (void) arg;
5000 d = tor_mathlog(2.718281828);
5001 tt_double_op(fabs(d - 1.0), OP_LT, .000001);
5002 d = tor_mathlog(10);
5003 tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
5004 done:
5008 static void
5009 test_util_fraction(void *arg)
5011 uint64_t a,b;
5012 (void)arg;
5014 a = 99; b = 30;
5015 simplify_fraction64(&a,&b);
5016 tt_u64_op(a, OP_EQ, 33);
5017 tt_u64_op(b, OP_EQ, 10);
5019 a = 3000000; b = 10000000;
5020 simplify_fraction64(&a,&b);
5021 tt_u64_op(a, OP_EQ, 3);
5022 tt_u64_op(b, OP_EQ, 10);
5024 a = 0; b = 15;
5025 simplify_fraction64(&a,&b);
5026 tt_u64_op(a, OP_EQ, 0);
5027 tt_u64_op(b, OP_EQ, 1);
5029 done:
5033 static void
5034 test_util_round_to_next_multiple_of(void *arg)
5036 (void)arg;
5038 tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0);
5039 tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0);
5041 tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99);
5042 tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105);
5043 tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99);
5045 tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ,
5046 UINT64_MAX);
5048 tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0);
5049 tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0);
5051 tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99);
5052 tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105);
5053 tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99);
5055 tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ,
5056 UINT32_MAX);
5058 tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0);
5059 tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0);
5061 tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99);
5062 tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105);
5063 tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99);
5065 tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ,
5066 UINT_MAX);
5067 done:
5071 static void
5072 test_util_laplace(void *arg)
5074 /* Sample values produced using Python's SciPy:
5076 * >>> from scipy.stats import laplace
5077 * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
5078 ... loc = 24, scale = 24)
5079 * array([ nan, -inf, -69.88855213, 24. ,
5080 * 24.48486498, 117.88855213, inf, nan])
5082 const double mu = 24.0, b = 24.0;
5083 const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
5084 (void)arg;
5086 tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0));
5087 tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01));
5088 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5));
5089 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51));
5090 tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99));
5092 /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
5093 * ... loc = 0, scale = 50)
5094 * array([ -inf, -80.47189562, -34.65735903, 0. ,
5095 * 34.65735903, 80.47189562, 195.60115027])
5097 tt_i64_op(INT64_MIN + 20, OP_EQ,
5098 add_laplace_noise(20, 0.0, delta_f, epsilon));
5100 tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon));
5101 tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon));
5102 tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon));
5103 tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon));
5104 tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon));
5105 tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon));
5107 /* Test extreme values of signal with maximally negative values of noise
5108 * 1.0000000000000002 is the smallest number > 1
5109 * 0.0000000000000002 is the double epsilon (error when calculating near 1)
5110 * this is approximately 1/(2^52)
5111 * per https://en.wikipedia.org/wiki/Double_precision
5112 * (let's not descend into the world of subnormals)
5113 * >>> laplace.ppf([0, 0.0000000000000002], loc = 0, scale = 1)
5114 * array([ -inf, -35.45506713])
5116 const double noscale_df = 1.0, noscale_eps = 1.0;
5118 tt_i64_op(INT64_MIN, OP_EQ,
5119 add_laplace_noise(0, 0.0, noscale_df, noscale_eps));
5121 /* is it clipped to INT64_MIN? */
5122 tt_i64_op(INT64_MIN, OP_EQ,
5123 add_laplace_noise(-1, 0.0, noscale_df, noscale_eps));
5124 tt_i64_op(INT64_MIN, OP_EQ,
5125 add_laplace_noise(INT64_MIN, 0.0,
5126 noscale_df, noscale_eps));
5127 /* ... even when scaled? */
5128 tt_i64_op(INT64_MIN, OP_EQ,
5129 add_laplace_noise(0, 0.0, delta_f, epsilon));
5130 tt_i64_op(INT64_MIN, OP_EQ,
5131 add_laplace_noise(0, 0.0,
5132 DBL_MAX, 1));
5133 tt_i64_op(INT64_MIN, OP_EQ,
5134 add_laplace_noise(INT64_MIN, 0.0,
5135 DBL_MAX, 1));
5137 /* does it play nice with INT64_MAX? */
5138 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5139 add_laplace_noise(INT64_MAX, 0.0,
5140 noscale_df, noscale_eps));
5142 /* do near-zero fractional values work? */
5143 const double min_dbl_error = 0.0000000000000002;
5145 tt_i64_op(-35, OP_EQ,
5146 add_laplace_noise(0, min_dbl_error,
5147 noscale_df, noscale_eps));
5148 tt_i64_op(INT64_MIN, OP_EQ,
5149 add_laplace_noise(INT64_MIN, min_dbl_error,
5150 noscale_df, noscale_eps));
5151 tt_i64_op((-35 + INT64_MAX), OP_EQ,
5152 add_laplace_noise(INT64_MAX, min_dbl_error,
5153 noscale_df, noscale_eps));
5154 tt_i64_op(INT64_MIN, OP_EQ,
5155 add_laplace_noise(0, min_dbl_error,
5156 DBL_MAX, 1));
5157 tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ,
5158 add_laplace_noise(INT64_MAX, min_dbl_error,
5159 DBL_MAX, 1));
5160 tt_i64_op(INT64_MIN, OP_EQ,
5161 add_laplace_noise(INT64_MIN, min_dbl_error,
5162 DBL_MAX, 1));
5164 /* does it play nice with INT64_MAX? */
5165 tt_i64_op((INT64_MAX - 35), OP_EQ,
5166 add_laplace_noise(INT64_MAX, min_dbl_error,
5167 noscale_df, noscale_eps));
5169 /* Test extreme values of signal with maximally positive values of noise
5170 * 1.0000000000000002 is the smallest number > 1
5171 * 0.9999999999999998 is the greatest number < 1 by calculation
5172 * per https://en.wikipedia.org/wiki/Double_precision
5173 * >>> laplace.ppf([1.0, 0.9999999999999998], loc = 0, scale = 1)
5174 * array([inf, 35.35050621])
5175 * but the function rejects p == 1.0, so we just use max_dbl_lt_one
5177 const double max_dbl_lt_one = 0.9999999999999998;
5179 /* do near-one fractional values work? */
5180 tt_i64_op(35, OP_EQ,
5181 add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps));
5183 /* is it clipped to INT64_MAX? */
5184 tt_i64_op(INT64_MAX, OP_EQ,
5185 add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one,
5186 noscale_df, noscale_eps));
5187 tt_i64_op(INT64_MAX, OP_EQ,
5188 add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one,
5189 noscale_df, noscale_eps));
5190 tt_i64_op(INT64_MAX, OP_EQ,
5191 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5192 noscale_df, noscale_eps));
5193 /* ... even when scaled? */
5194 tt_i64_op(INT64_MAX, OP_EQ,
5195 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5196 delta_f, epsilon));
5197 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5198 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5199 DBL_MAX, 1));
5200 tt_i64_op(INT64_MAX, OP_EQ,
5201 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5202 DBL_MAX, 1));
5203 /* does it play nice with INT64_MIN? */
5204 tt_i64_op((INT64_MIN + 35), OP_EQ,
5205 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5206 noscale_df, noscale_eps));
5208 done:
5212 static void
5213 test_util_clamp_double_to_int64(void *arg)
5215 (void)arg;
5217 tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL));
5218 tt_i64_op(INT64_MIN, OP_EQ,
5219 clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0));
5220 tt_i64_op(INT64_MIN, OP_EQ,
5221 clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0));
5222 tt_i64_op(((uint64_t) -1) << 53, OP_EQ,
5223 clamp_double_to_int64(-1.0 * pow(2.0, 53.0)));
5224 tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ,
5225 clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0));
5226 tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0));
5227 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9));
5228 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1));
5229 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0));
5230 tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL));
5231 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1));
5232 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9));
5233 tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0));
5234 tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ,
5235 clamp_double_to_int64(pow(2.0, 53.0) - 1.0));
5236 tt_i64_op(((int64_t) 1) << 53, OP_EQ,
5237 clamp_double_to_int64(pow(2.0, 53.0)));
5238 tt_i64_op(INT64_MAX, OP_EQ,
5239 clamp_double_to_int64(pow(2.0, 63.0)));
5240 tt_i64_op(INT64_MAX, OP_EQ,
5241 clamp_double_to_int64(pow(2.0, 64.0)));
5242 tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL));
5244 done:
5248 #ifdef FD_CLOEXEC
5249 #define CAN_CHECK_CLOEXEC
5250 static int
5251 fd_is_cloexec(tor_socket_t fd)
5253 int flags = fcntl(fd, F_GETFD, 0);
5254 return (flags & FD_CLOEXEC) == FD_CLOEXEC;
5256 #endif /* defined(FD_CLOEXEC) */
5258 #ifndef _WIN32
5259 #define CAN_CHECK_NONBLOCK
5260 static int
5261 fd_is_nonblocking(tor_socket_t fd)
5263 int flags = fcntl(fd, F_GETFL, 0);
5264 return (flags & O_NONBLOCK) == O_NONBLOCK;
5266 #endif /* !defined(_WIN32) */
5268 #define ERRNO_IS_EPROTO(e) (e == SOCK_ERRNO(EPROTONOSUPPORT))
5269 #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
5271 /* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
5272 static void
5273 test_util_socket(void *arg)
5275 const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
5276 tor_socket_t fd1 = TOR_INVALID_SOCKET;
5277 tor_socket_t fd2 = TOR_INVALID_SOCKET;
5278 tor_socket_t fd3 = TOR_INVALID_SOCKET;
5279 tor_socket_t fd4 = TOR_INVALID_SOCKET;
5280 int n = get_n_open_sockets();
5282 TT_BLATHER(("Starting with %d open sockets.", n));
5284 (void)arg;
5286 fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
5287 int err = tor_socket_errno(fd1);
5288 if (fd1 < 0 && (err == SOCK_ERRNO(EPROTONOSUPPORT) ||
5289 err == SOCK_ERRNO(EAFNOSUPPORT))) {
5290 /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
5291 goto done;
5293 fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
5294 tt_assert(SOCKET_OK(fd1));
5295 tt_assert(SOCKET_OK(fd2));
5296 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5297 //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
5298 //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
5299 fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
5300 fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
5301 tt_assert(SOCKET_OK(fd3));
5302 tt_assert(SOCKET_OK(fd4));
5303 tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
5305 #ifdef CAN_CHECK_CLOEXEC
5306 tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
5307 tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
5308 tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
5309 tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
5310 #endif /* defined(CAN_CHECK_CLOEXEC) */
5311 #ifdef CAN_CHECK_NONBLOCK
5312 tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
5313 tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
5314 tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
5315 tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
5316 #endif /* defined(CAN_CHECK_NONBLOCK) */
5318 tor_assert(tor_close_socket == tor_close_socket__real);
5320 /* we use close_socket__real here so that coverity can tell that we are
5321 * really closing these sockets. */
5322 tor_close_socket__real(fd1);
5323 tor_close_socket__real(fd2);
5324 fd1 = fd2 = TOR_INVALID_SOCKET;
5325 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5326 tor_close_socket__real(fd3);
5327 tor_close_socket__real(fd4);
5328 fd3 = fd4 = TOR_INVALID_SOCKET;
5329 tt_int_op(get_n_open_sockets(), OP_EQ, n);
5331 done:
5332 if (SOCKET_OK(fd1))
5333 tor_close_socket__real(fd1);
5334 if (SOCKET_OK(fd2))
5335 tor_close_socket__real(fd2);
5336 if (SOCKET_OK(fd3))
5337 tor_close_socket__real(fd3);
5338 if (SOCKET_OK(fd4))
5339 tor_close_socket__real(fd4);
5342 #if 0
5343 static int
5344 is_there_a_localhost(int family)
5346 tor_socket_t s;
5347 s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP);
5348 tor_assert(SOCKET_OK(s));
5350 int result = 0;
5351 if (family == AF_INET) {
5352 struct sockaddr_in s_in;
5353 memset(&s_in, 0, sizeof(s_in));
5354 s_in.sin_family = AF_INET;
5355 s_in.sin_addr.s_addr = htonl(0x7f000001);
5356 s_in.sin_port = 0;
5358 if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) {
5359 result = 1;
5361 } else if (family == AF_INET6) {
5362 struct sockaddr_in6 sin6;
5363 memset(&sin6, 0, sizeof(sin6));
5364 sin6.sin6_family = AF_INET6;
5365 sin6.sin6_addr.s6_addr[15] = 1;
5366 sin6.sin6_port = 0;
5368 tor_close_socket(s);
5370 return result;
5372 #endif /* 0 */
5374 /* Test for socketpair and ersatz_socketpair(). We test them both, since
5375 * the latter is a tolerably good way to exercise tor_accept_socket(). */
5376 static void
5377 test_util_socketpair(void *arg)
5379 const int ersatz = !strcmp(arg, "1");
5380 int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
5381 ersatz ? tor_ersatz_socketpair : tor_socketpair;
5382 int n = get_n_open_sockets();
5383 tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
5384 const int family = AF_UNIX;
5385 int socketpair_result = 0;
5387 socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
5389 #ifdef __FreeBSD__
5390 /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail.
5391 * Otherwise, we risk exposing a socketpair on a routable IP address. (Some
5392 * BSD jails use a routable address for localhost. Fortunately, they have
5393 * the real AF_UNIX socketpair.) */
5394 if (ersatz && socketpair_result < 0) {
5395 /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL.
5396 * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */
5397 tt_skip();
5399 #endif /* defined(__FreeBSD__) */
5400 tt_int_op(0, OP_EQ, socketpair_result);
5402 tt_assert(SOCKET_OK(fds[0]));
5403 tt_assert(SOCKET_OK(fds[1]));
5404 if (ersatz)
5405 tt_int_op(get_n_open_sockets(), OP_EQ, n);
5406 else
5407 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5408 #ifdef CAN_CHECK_CLOEXEC
5409 tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, !ersatz);
5410 tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, !ersatz);
5411 #endif
5412 #ifdef CAN_CHECK_NONBLOCK
5413 tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
5414 tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
5415 #endif
5417 done:
5418 if (ersatz) {
5419 if (SOCKET_OK(fds[0]))
5420 tor_close_socket_simple(fds[0]);
5421 if (SOCKET_OK(fds[1]))
5422 tor_close_socket_simple(fds[1]);
5423 } else {
5424 if (SOCKET_OK(fds[0]))
5425 tor_close_socket(fds[0]);
5426 if (SOCKET_OK(fds[1]))
5427 tor_close_socket(fds[1]);
5431 #undef SOCKET_EPROTO
5433 static void
5434 test_util_max_mem(void *arg)
5436 size_t memory1, memory2;
5437 int r, r2;
5438 (void) arg;
5440 r = get_total_system_memory(&memory1);
5441 r2 = get_total_system_memory(&memory2);
5442 tt_int_op(r, OP_EQ, r2);
5443 tt_uint_op(memory2, OP_EQ, memory1);
5445 TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1)));
5447 if (r==0) {
5448 /* You have at least a megabyte. */
5449 tt_uint_op(memory1, OP_GT, (1<<20));
5450 } else {
5451 /* You do not have a petabyte. */
5452 #if SIZEOF_SIZE_T >= 8
5453 tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50));
5454 #endif
5457 done:
5461 static void
5462 test_util_dest_validation_edgecase(void *arg)
5464 (void)arg;
5466 tt_assert(!string_is_valid_dest(NULL));
5467 tt_assert(!string_is_valid_dest(""));
5469 done:
5470 return;
5473 static void
5474 test_util_hostname_validation(void *arg)
5476 (void)arg;
5478 // Lets try valid hostnames first.
5479 tt_assert(string_is_valid_nonrfc_hostname("torproject.org"));
5480 tt_assert(string_is_valid_nonrfc_hostname("ocw.mit.edu"));
5481 tt_assert(string_is_valid_nonrfc_hostname("i.4cdn.org"));
5482 tt_assert(string_is_valid_nonrfc_hostname("stanford.edu"));
5483 tt_assert(string_is_valid_nonrfc_hostname("multiple-words-with-hypens.jp"));
5485 // Subdomain name cannot start with '-' or '_'.
5486 tt_assert(!string_is_valid_nonrfc_hostname("-torproject.org"));
5487 tt_assert(!string_is_valid_nonrfc_hostname("subdomain.-domain.org"));
5488 tt_assert(!string_is_valid_nonrfc_hostname("-subdomain.domain.org"));
5489 tt_assert(!string_is_valid_nonrfc_hostname("___abc.org"));
5491 // Hostnames cannot contain non-alphanumeric characters.
5492 tt_assert(!string_is_valid_nonrfc_hostname("%%domain.\\org."));
5493 tt_assert(!string_is_valid_nonrfc_hostname("***x.net"));
5494 tt_assert(!string_is_valid_nonrfc_hostname("\xff\xffxyz.org"));
5495 tt_assert(!string_is_valid_nonrfc_hostname("word1 word2.net"));
5497 // Test workaround for nytimes.com stupidity, technically invalid,
5498 // but we allow it since they are big, even though they are failing to
5499 // comply with a ~30 year old standard.
5500 tt_assert(string_is_valid_nonrfc_hostname("core3_euw1.fabrik.nytimes.com"));
5502 // Firefox passes FQDNs with trailing '.'s directly to the SOCKS proxy,
5503 // which is redundant since the spec states DOMAINNAME addresses are fully
5504 // qualified. While unusual, this should be tollerated.
5505 tt_assert(string_is_valid_nonrfc_hostname("core9_euw1.fabrik.nytimes.com."));
5506 tt_assert(!string_is_valid_nonrfc_hostname(
5507 "..washingtonpost.is.better.com"));
5508 tt_assert(!string_is_valid_nonrfc_hostname("so.is..ft.com"));
5509 tt_assert(!string_is_valid_nonrfc_hostname("..."));
5511 // XXX: do we allow single-label DNS names?
5512 // We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
5513 // but only test pathologically malformed traling '.' cases for now.
5514 tt_assert(!string_is_valid_nonrfc_hostname("."));
5515 tt_assert(!string_is_valid_nonrfc_hostname(".."));
5517 // IP address strings are not hostnames.
5518 tt_assert(!string_is_valid_nonrfc_hostname("8.8.8.8"));
5519 tt_assert(!string_is_valid_nonrfc_hostname("[2a00:1450:401b:800::200e]"));
5520 tt_assert(!string_is_valid_nonrfc_hostname("2a00:1450:401b:800::200e"));
5522 // We allow alphanumeric TLDs. For discussion, see ticket #25055.
5523 tt_assert(string_is_valid_nonrfc_hostname("lucky.13"));
5524 tt_assert(string_is_valid_nonrfc_hostname("luck.y13"));
5525 tt_assert(string_is_valid_nonrfc_hostname("luck.y13."));
5527 // We allow punycode TLDs. For examples, see
5528 // http://data.iana.org/TLD/tlds-alpha-by-domain.txt
5529 tt_assert(string_is_valid_nonrfc_hostname("example.xn--l1acc"));
5531 done:
5532 return;
5535 static void
5536 test_util_ipv4_validation(void *arg)
5538 (void)arg;
5540 tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
5541 tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
5543 tt_assert(!string_is_valid_ipv4_address("abcd"));
5544 tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
5545 tt_assert(!string_is_valid_ipv4_address("8.8."));
5547 done:
5548 return;
5551 static void
5552 test_util_ipv6_validation(void *arg)
5554 (void)arg;
5556 tt_assert(string_is_valid_ipv6_address("2a00:1450:401b:800::200e"));
5557 tt_assert(!string_is_valid_ipv6_address("11:22::33:44:"));
5559 done:
5560 return;
5563 static void
5564 test_util_writepid(void *arg)
5566 (void) arg;
5568 char *contents = NULL;
5569 const char *fname = get_fname("tmp_pid");
5570 unsigned long pid;
5571 char c;
5573 write_pidfile(fname);
5575 contents = read_file_to_str(fname, 0, NULL);
5576 tt_assert(contents);
5578 int n = tor_sscanf(contents, "%lu\n%c", &pid, &c);
5579 tt_int_op(n, OP_EQ, 1);
5581 #ifdef _WIN32
5582 tt_uint_op(pid, OP_EQ, _getpid());
5583 #else
5584 tt_uint_op(pid, OP_EQ, getpid());
5585 #endif
5587 done:
5588 tor_free(contents);
5591 static void
5592 test_util_get_avail_disk_space(void *arg)
5594 (void) arg;
5595 int64_t val;
5597 /* No answer for nonexistent directory */
5598 val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa");
5599 tt_i64_op(val, OP_EQ, -1);
5601 /* Try the current directory */
5602 val = tor_get_avail_disk_space(".");
5604 #if !defined(HAVE_STATVFS) && !defined(_WIN32)
5605 tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */
5606 #else
5607 tt_i64_op(val, OP_GT, 0); /* You have some space. */
5608 tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */
5609 #endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */
5611 done:
5615 static void
5616 test_util_touch_file(void *arg)
5618 (void) arg;
5619 const char *fname = get_fname("touch");
5621 const time_t now = time(NULL);
5622 struct stat st;
5623 write_bytes_to_file(fname, "abc", 3, 1);
5624 tt_int_op(0, OP_EQ, stat(fname, &st));
5625 /* A subtle point: the filesystem time is not necessarily equal to the
5626 * system clock time, since one can be using a monotonic clock, or coarse
5627 * monotonic clock, or whatever. So we might wind up with an mtime a few
5628 * microseconds ago. Let's just give it a lot of wiggle room. */
5629 tt_i64_op(st.st_mtime, OP_GE, now - 1);
5631 const time_t five_sec_ago = now - 5;
5632 struct utimbuf u = { five_sec_ago, five_sec_ago };
5633 tt_int_op(0, OP_EQ, utime(fname, &u));
5634 tt_int_op(0, OP_EQ, stat(fname, &st));
5635 /* Let's hope that utime/stat give the same second as a round-trip? */
5636 tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
5638 /* Finally we can touch the file */
5639 tt_int_op(0, OP_EQ, touch_file(fname));
5640 tt_int_op(0, OP_EQ, stat(fname, &st));
5641 tt_i64_op(st.st_mtime, OP_GE, now-1);
5643 done:
5647 #ifndef _WIN32
5648 static void
5649 test_util_pwdb(void *arg)
5651 (void) arg;
5652 const struct passwd *me = NULL, *me2, *me3;
5653 char *name = NULL;
5654 char *dir = NULL;
5656 /* Uncached case. */
5657 /* Let's assume that we exist. */
5658 me = tor_getpwuid(getuid());
5659 tt_ptr_op(me, OP_NE, NULL);
5660 name = tor_strdup(me->pw_name);
5662 /* Uncached case */
5663 me2 = tor_getpwnam(name);
5664 tt_ptr_op(me2, OP_NE, NULL);
5665 tt_int_op(me2->pw_uid, OP_EQ, getuid());
5667 /* Cached case */
5668 me3 = tor_getpwuid(getuid());
5669 tt_ptr_op(me3, OP_NE, NULL);
5670 tt_str_op(me3->pw_name, OP_EQ, name);
5672 me3 = tor_getpwnam(name);
5673 tt_ptr_op(me3, OP_NE, NULL);
5674 tt_int_op(me3->pw_uid, OP_EQ, getuid());
5676 dir = get_user_homedir(name);
5677 tt_ptr_op(dir, OP_NE, NULL);
5679 /* Try failing cases. First find a user that doesn't exist by name */
5680 char randbytes[4];
5681 char badname[9];
5682 int i, found=0;
5683 for (i = 0; i < 100; ++i) {
5684 crypto_rand(randbytes, sizeof(randbytes));
5685 base16_encode(badname, sizeof(badname), randbytes, sizeof(randbytes));
5686 if (tor_getpwnam(badname) == NULL) {
5687 found = 1;
5688 break;
5691 tt_assert(found);
5692 tor_free(dir);
5694 /* We should do a LOG_ERR */
5695 setup_full_capture_of_logs(LOG_ERR);
5696 dir = get_user_homedir(badname);
5697 tt_ptr_op(dir, OP_EQ, NULL);
5698 expect_log_msg_containing("not found");
5699 tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1);
5700 teardown_capture_of_logs();
5702 /* Now try to find a user that doesn't exist by ID. */
5703 found = 0;
5704 for (i = 0; i < 1000; ++i) {
5705 uid_t u;
5706 crypto_rand((char*)&u, sizeof(u));
5707 if (tor_getpwuid(u) == NULL) {
5708 found = 1;
5709 break;
5712 tt_assert(found);
5714 done:
5715 tor_free(name);
5716 tor_free(dir);
5717 teardown_capture_of_logs();
5719 #endif /* !defined(_WIN32) */
5721 static void
5722 test_util_calloc_check(void *arg)
5724 (void) arg;
5725 /* Easy cases that are good. */
5726 tt_assert(size_mul_check(0,0));
5727 tt_assert(size_mul_check(0,100));
5728 tt_assert(size_mul_check(100,0));
5729 tt_assert(size_mul_check(100,100));
5731 /* Harder cases that are still good. */
5732 tt_assert(size_mul_check(SIZE_MAX, 1));
5733 tt_assert(size_mul_check(1, SIZE_MAX));
5734 tt_assert(size_mul_check(SIZE_MAX / 10, 9));
5735 tt_assert(size_mul_check(11, SIZE_MAX / 12));
5736 const size_t sqrt_size_max_p1 = ((size_t)1) << (sizeof(size_t) * 4);
5737 tt_assert(size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1 - 1));
5739 /* Cases that overflow */
5740 tt_assert(! size_mul_check(SIZE_MAX, 2));
5741 tt_assert(! size_mul_check(2, SIZE_MAX));
5742 tt_assert(! size_mul_check(SIZE_MAX / 10, 11));
5743 tt_assert(! size_mul_check(11, SIZE_MAX / 10));
5744 tt_assert(! size_mul_check(SIZE_MAX / 8, 9));
5745 tt_assert(! size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1));
5747 done:
5751 static void
5752 test_util_monotonic_time(void *arg)
5754 (void)arg;
5756 monotime_t mt1, mt2;
5757 monotime_coarse_t mtc1, mtc2;
5758 uint64_t nsec1, nsec2, usec1, msec1;
5759 uint64_t nsecc1, nsecc2, usecc1, msecc1;
5760 uint32_t stamp1, stamp2;
5762 monotime_init();
5764 monotime_get(&mt1);
5765 monotime_coarse_get(&mtc1);
5766 nsec1 = monotime_absolute_nsec();
5767 usec1 = monotime_absolute_usec();
5768 msec1 = monotime_absolute_msec();
5769 nsecc1 = monotime_coarse_absolute_nsec();
5770 usecc1 = monotime_coarse_absolute_usec();
5771 msecc1 = monotime_coarse_absolute_msec();
5772 stamp1 = monotime_coarse_to_stamp(&mtc1);
5774 tor_sleep_msec(200);
5776 monotime_get(&mt2);
5777 monotime_coarse_get(&mtc2);
5778 nsec2 = monotime_absolute_nsec();
5779 nsecc2 = monotime_coarse_absolute_nsec();
5780 stamp2 = monotime_coarse_to_stamp(&mtc2);
5782 /* We need to be a little careful here since we don't know the system load.
5784 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_GE, 175);
5785 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_LT, 1000);
5786 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_GE, 125);
5787 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_LT, 1000);
5788 tt_u64_op(nsec2-nsec1, OP_GE, 175000000);
5789 tt_u64_op(nsec2-nsec1, OP_LT, 1000000000);
5790 tt_u64_op(nsecc2-nsecc1, OP_GE, 125000000);
5791 tt_u64_op(nsecc2-nsecc1, OP_LT, 1000000000);
5793 tt_u64_op(msec1, OP_GE, nsec1 / 1000000);
5794 tt_u64_op(usec1, OP_GE, nsec1 / 1000);
5795 tt_u64_op(msecc1, OP_GE, nsecc1 / 1000000);
5796 tt_u64_op(usecc1, OP_GE, nsecc1 / 1000);
5797 tt_u64_op(msec1, OP_LE, nsec1 / 1000000 + 10);
5798 tt_u64_op(usec1, OP_LE, nsec1 / 1000 + 10000);
5799 tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 10);
5800 tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 10000);
5802 uint64_t coarse_stamp_diff =
5803 monotime_coarse_stamp_units_to_approx_msec(stamp2-stamp1);
5804 tt_u64_op(coarse_stamp_diff, OP_GE, 120);
5805 tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
5808 uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
5809 uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
5810 tt_u64_op(ms, OP_GE, 4950);
5811 tt_u64_op(ms, OP_LT, 5050);
5814 done:
5818 static void
5819 test_util_monotonic_time_ratchet(void *arg)
5821 (void)arg;
5822 monotime_init();
5823 monotime_reset_ratchets_for_testing();
5825 /* win32, performance counter ratchet. */
5826 tt_i64_op(100, OP_EQ, ratchet_performance_counter(100));
5827 tt_i64_op(101, OP_EQ, ratchet_performance_counter(101));
5828 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(2000));
5829 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(100));
5830 tt_i64_op(2005, OP_EQ, ratchet_performance_counter(105));
5831 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1105));
5832 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1000));
5833 tt_i64_op(3010, OP_EQ, ratchet_performance_counter(1005));
5835 /* win32, GetTickCounts32 ratchet-and-rollover-detector. */
5836 const int64_t R = ((int64_t)1) << 32;
5837 tt_i64_op(5, OP_EQ, ratchet_coarse_performance_counter(5));
5838 tt_i64_op(1000, OP_EQ, ratchet_coarse_performance_counter(1000));
5839 tt_i64_op(5+R, OP_EQ, ratchet_coarse_performance_counter(5));
5840 tt_i64_op(10+R, OP_EQ, ratchet_coarse_performance_counter(10));
5841 tt_i64_op(4+R*2, OP_EQ, ratchet_coarse_performance_counter(4));
5843 /* gettimeofday regular ratchet. */
5844 struct timeval tv_in = {0,0}, tv_out;
5845 tv_in.tv_usec = 9000;
5847 ratchet_timeval(&tv_in, &tv_out);
5848 tt_int_op(tv_out.tv_usec, OP_EQ, 9000);
5849 tt_i64_op(tv_out.tv_sec, OP_EQ, 0);
5851 tv_in.tv_sec = 1337;
5852 tv_in.tv_usec = 0;
5853 ratchet_timeval(&tv_in, &tv_out);
5854 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
5855 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
5857 tv_in.tv_sec = 1336;
5858 tv_in.tv_usec = 500000;
5859 ratchet_timeval(&tv_in, &tv_out);
5860 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
5861 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
5863 tv_in.tv_sec = 1337;
5864 tv_in.tv_usec = 0;
5865 ratchet_timeval(&tv_in, &tv_out);
5866 tt_int_op(tv_out.tv_usec, OP_EQ, 500000);
5867 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
5869 tv_in.tv_sec = 1337;
5870 tv_in.tv_usec = 600000;
5871 ratchet_timeval(&tv_in, &tv_out);
5872 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
5873 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
5875 tv_in.tv_sec = 1000;
5876 tv_in.tv_usec = 1000;
5877 ratchet_timeval(&tv_in, &tv_out);
5878 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
5879 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
5881 tv_in.tv_sec = 2000;
5882 tv_in.tv_usec = 2000;
5883 ratchet_timeval(&tv_in, &tv_out);
5884 tt_int_op(tv_out.tv_usec, OP_EQ, 101000);
5885 tt_i64_op(tv_out.tv_sec, OP_EQ, 2338);
5887 done:
5891 static void
5892 test_util_monotonic_time_zero(void *arg)
5894 (void) arg;
5895 monotime_t t1;
5896 monotime_coarse_t ct1;
5897 monotime_init();
5898 /* Check 1: The current time is not zero. */
5899 monotime_get(&t1);
5900 monotime_coarse_get(&ct1);
5901 tt_assert(!monotime_is_zero(&t1));
5902 tt_assert(!monotime_coarse_is_zero(&ct1));
5904 /* Check 2: The _zero() makes the time zero. */
5905 monotime_zero(&t1);
5906 monotime_coarse_zero(&ct1);
5907 tt_assert(monotime_is_zero(&t1));
5908 tt_assert(monotime_coarse_is_zero(&ct1));
5909 done:
5913 static void
5914 test_util_monotonic_time_add_msec(void *arg)
5916 (void) arg;
5917 monotime_t t1, t2;
5918 monotime_coarse_t ct1, ct2;
5919 monotime_init();
5921 monotime_get(&t1);
5922 monotime_coarse_get(&ct1);
5924 /* adding zero does nothing */
5925 monotime_add_msec(&t2, &t1, 0);
5926 monotime_coarse_add_msec(&ct2, &ct1, 0);
5927 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 0);
5928 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 0);
5930 /* Add 1337 msec; see if the diff function agree */
5931 monotime_add_msec(&t2, &t1, 1337);
5932 monotime_coarse_add_msec(&ct2, &ct1, 1337);
5933 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
5934 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
5935 // The 32-bit variant must be within 1% of the regular one.
5936 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
5937 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
5939 /* Add 1337 msec twice more; make sure that any second rollover issues
5940 * worked. */
5941 monotime_add_msec(&t2, &t2, 1337);
5942 monotime_coarse_add_msec(&ct2, &ct2, 1337);
5943 monotime_add_msec(&t2, &t2, 1337);
5944 monotime_coarse_add_msec(&ct2, &ct2, 1337);
5945 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
5946 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
5947 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
5948 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
5950 done:
5954 static void
5955 test_util_nowrap_math(void *arg)
5957 (void)arg;
5959 tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
5960 tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
5961 tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
5962 tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
5963 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
5964 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
5965 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
5967 done:
5971 static void
5972 test_util_htonll(void *arg)
5974 (void)arg;
5975 #ifdef WORDS_BIGENDIAN
5976 const uint64_t res_be = 0x8877665544332211;
5977 #else
5978 const uint64_t res_le = 0x1122334455667788;
5979 #endif
5981 tt_u64_op(0, OP_EQ, tor_htonll(0));
5982 tt_u64_op(0, OP_EQ, tor_ntohll(0));
5983 tt_u64_op(UINT64_MAX, OP_EQ, tor_htonll(UINT64_MAX));
5984 tt_u64_op(UINT64_MAX, OP_EQ, tor_ntohll(UINT64_MAX));
5986 #ifdef WORDS_BIGENDIAN
5987 tt_u64_op(res_be, OP_EQ, tor_htonll(0x8877665544332211));
5988 tt_u64_op(res_be, OP_EQ, tor_ntohll(0x8877665544332211));
5989 #else
5990 tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211));
5991 tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211));
5992 #endif /* defined(WORDS_BIGENDIAN) */
5994 done:
5998 static void
5999 test_util_get_unquoted_path(void *arg)
6001 (void)arg;
6003 char *r = NULL;
6005 r = get_unquoted_path("\""); // "
6006 tt_ptr_op(r, OP_EQ, NULL);
6007 tor_free(r);
6009 r = get_unquoted_path("\"\"\""); // """
6010 tt_ptr_op(r, OP_EQ, NULL);
6011 tor_free(r);
6013 r = get_unquoted_path("\\\""); // \"
6014 tt_ptr_op(r, OP_EQ, NULL);
6015 tor_free(r);
6017 r = get_unquoted_path("\\\"\\\""); // \"\"
6018 tt_ptr_op(r, OP_EQ, NULL);
6019 tor_free(r);
6021 r = get_unquoted_path("A\\B\\C\""); // A\B\C"
6022 tt_ptr_op(r, OP_EQ, NULL);
6023 tor_free(r);
6025 r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
6026 tt_ptr_op(r, OP_EQ, NULL);
6027 tor_free(r);
6029 r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
6030 tt_ptr_op(r, OP_EQ, NULL);
6031 tor_free(r);
6033 r = get_unquoted_path("A\\B\"C"); // A\B"C
6034 tt_ptr_op(r, OP_EQ, NULL);
6035 tor_free(r);
6037 r = get_unquoted_path("");
6038 tt_str_op(r, OP_EQ, "");
6039 tor_free(r);
6041 r = get_unquoted_path("\"\""); // ""
6042 tt_str_op(r, OP_EQ, "");
6043 tor_free(r);
6045 r = get_unquoted_path("A\\B\\C"); // A\B\C
6046 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6047 tor_free(r);
6049 r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
6050 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6051 tor_free(r);
6053 r = get_unquoted_path("\"\\\""); // "\"
6054 tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
6055 tor_free(r);
6057 r = get_unquoted_path("\"\\\"\""); // "\""
6058 tt_str_op(r, OP_EQ, "\""); // "
6059 tor_free(r);
6061 r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
6062 tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
6063 tor_free(r);
6065 r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
6066 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6067 tor_free(r);
6069 r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
6070 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6072 done:
6073 tor_free(r);
6076 static void
6077 test_util_log_mallinfo(void *arg)
6079 (void)arg;
6080 char *log1 = NULL, *log2 = NULL, *mem = NULL;
6081 #ifdef HAVE_MALLINFO
6082 setup_capture_of_logs(LOG_INFO);
6083 tor_log_mallinfo(LOG_INFO);
6084 expect_single_log_msg_containing("mallinfo() said: ");
6085 mock_saved_log_entry_t *lg = smartlist_get(mock_saved_logs(), 0);
6086 log1 = tor_strdup(lg->generated_msg);
6088 mock_clean_saved_logs();
6089 mem = tor_malloc(8192);
6090 tor_log_mallinfo(LOG_INFO);
6091 expect_single_log_msg_containing("mallinfo() said: ");
6092 lg = smartlist_get(mock_saved_logs(), 0);
6093 log2 = tor_strdup(lg->generated_msg);
6095 /* Make sure that the amount of used memory increased. */
6096 const char *used1 = strstr(log1, "uordblks=");
6097 const char *used2 = strstr(log2, "uordblks=");
6098 tt_assert(used1);
6099 tt_assert(used2);
6100 used1 += strlen("uordblks=");
6101 used2 += strlen("uordblks=");
6103 int ok1, ok2;
6104 char *next1 = NULL, *next2 = NULL;
6105 uint64_t mem1 = tor_parse_uint64(used1, 10, 0, UINT64_MAX, &ok1, &next1);
6106 uint64_t mem2 = tor_parse_uint64(used2, 10, 0, UINT64_MAX, &ok2, &next2);
6107 tt_assert(ok1);
6108 tt_assert(ok2);
6109 tt_assert(next1);
6110 tt_assert(next2);
6111 if (mem2 == 0) {
6112 /* This is a fake mallinfo that doesn't actually fill in its outputs. */
6113 tt_u64_op(mem1, OP_EQ, 0);
6114 } else {
6115 tt_u64_op(mem1, OP_LT, mem2);
6117 #else
6118 tt_skip();
6119 #endif
6120 done:
6121 teardown_capture_of_logs();
6122 tor_free(log1);
6123 tor_free(log2);
6124 tor_free(mem);
6127 static void
6128 test_util_map_anon(void *arg)
6130 (void)arg;
6131 char *ptr = NULL;
6132 size_t sz = 16384;
6134 /* Basic checks. */
6135 ptr = tor_mmap_anonymous(sz, 0);
6136 tt_ptr_op(ptr, OP_NE, 0);
6137 ptr[sz-1] = 3;
6138 tt_int_op(ptr[0], OP_EQ, 0);
6139 tt_int_op(ptr[sz-2], OP_EQ, 0);
6140 tt_int_op(ptr[sz-1], OP_EQ, 3);
6142 /* Try again, with a private (non-swappable) mapping. */
6143 tor_munmap_anonymous(ptr, sz);
6144 ptr = tor_mmap_anonymous(sz, ANONMAP_PRIVATE);
6145 tt_ptr_op(ptr, OP_NE, 0);
6146 ptr[sz-1] = 10;
6147 tt_int_op(ptr[0], OP_EQ, 0);
6148 tt_int_op(ptr[sz/2], OP_EQ, 0);
6149 tt_int_op(ptr[sz-1], OP_EQ, 10);
6151 /* Now let's test a drop-on-fork mapping. */
6152 tor_munmap_anonymous(ptr, sz);
6153 ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT);
6154 tt_ptr_op(ptr, OP_NE, 0);
6155 ptr[sz-1] = 10;
6156 tt_int_op(ptr[0], OP_EQ, 0);
6157 tt_int_op(ptr[sz/2], OP_EQ, 0);
6158 tt_int_op(ptr[sz-1], OP_EQ, 10);
6160 done:
6161 tor_munmap_anonymous(ptr, sz);
6164 static void
6165 test_util_map_anon_nofork(void *arg)
6167 (void)arg;
6168 #if !defined(HAVE_MADVISE) && !defined(HAVE_MINHERIT)
6169 /* The operating system doesn't support this. */
6170 tt_skip();
6171 done:
6173 #else
6174 /* We have the right OS support. We're going to try marking the buffer as
6175 * either zero-on-fork or as drop-on-fork, whichever is supported. Then we
6176 * will fork and send a byte back to the parent process. This will either
6177 * crash, or send zero. */
6179 char *ptr = NULL;
6180 size_t sz = 16384;
6181 int pipefd[2] = {-1, -1};
6183 tor_munmap_anonymous(ptr, sz);
6184 ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT);
6185 tt_ptr_op(ptr, OP_NE, 0);
6186 memset(ptr, 0xd0, sz);
6188 tt_int_op(0, OP_EQ, pipe(pipefd));
6189 pid_t child = fork();
6190 if (child == 0) {
6191 /* We're in the child. */
6192 close(pipefd[0]);
6193 ssize_t r = write(pipefd[1], &ptr[sz-1], 1); /* This may crash. */
6194 close(pipefd[1]);
6195 if (r < 0)
6196 exit(1);
6197 exit(0);
6199 tt_int_op(child, OP_GT, 0);
6200 /* In the parent. */
6201 close(pipefd[1]);
6202 pipefd[1] = -1;
6203 char buf[1];
6204 ssize_t r = read(pipefd[0], buf, 1);
6205 #if defined(INHERIT_ZERO) || defined(MADV_WIPEONFORK)
6206 tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
6207 tt_int_op(buf[0], OP_EQ, 0);
6208 #else
6209 tt_int_op(r, OP_LE, 0); // child said nothing; it should have crashed.
6210 #endif
6211 int ws;
6212 waitpid(child, &ws, 0);
6214 done:
6215 tor_munmap_anonymous(ptr, sz);
6216 if (pipefd[0] >= 0) {
6217 close(pipefd[0]);
6219 if (pipefd[1] >= 0) {
6220 close(pipefd[1]);
6222 #endif
6225 #define UTIL_LEGACY(name) \
6226 { #name, test_util_ ## name , 0, NULL, NULL }
6228 #define UTIL_TEST(name, flags) \
6229 { #name, test_util_ ## name, flags, NULL, NULL }
6231 #define COMPRESS(name, identifier) \
6232 { "compress/" #name, test_util_compress, 0, &compress_setup, \
6233 (char*)(identifier) }
6235 #define COMPRESS_CONCAT(name, identifier) \
6236 { "compress_concat/" #name, test_util_decompress_concatenated, 0, \
6237 &compress_setup, \
6238 (char*)(identifier) }
6240 #define COMPRESS_JUNK(name, identifier) \
6241 { "compress_junk/" #name, test_util_decompress_junk, 0, \
6242 &compress_setup, \
6243 (char*)(identifier) }
6245 #define COMPRESS_DOS(name, identifier) \
6246 { "compress_dos/" #name, test_util_decompress_dos, 0, \
6247 &compress_setup, \
6248 (char*)(identifier) }
6250 #ifdef _WIN32
6251 #define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
6252 #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
6253 #define UTIL_LEGACY_NO_WIN(n) UTIL_TEST_NO_WIN(n, 0)
6254 #else
6255 #define UTIL_TEST_NO_WIN(n, f) UTIL_TEST(n, (f))
6256 #define UTIL_TEST_WIN_ONLY(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
6257 #define UTIL_LEGACY_NO_WIN(n) UTIL_LEGACY(n)
6258 #endif /* defined(_WIN32) */
6260 struct testcase_t util_tests[] = {
6261 UTIL_LEGACY(time),
6262 UTIL_TEST(parse_http_time, 0),
6263 UTIL_LEGACY(config_line),
6264 UTIL_LEGACY(config_line_quotes),
6265 UTIL_LEGACY(config_line_comment_character),
6266 UTIL_LEGACY(config_line_escaped_content),
6267 UTIL_LEGACY(config_line_crlf),
6268 UTIL_LEGACY_NO_WIN(expand_filename),
6269 UTIL_LEGACY(escape_string_socks),
6270 UTIL_LEGACY(string_is_key_value),
6271 UTIL_LEGACY(strmisc),
6272 UTIL_TEST(parse_integer, 0),
6273 UTIL_LEGACY(pow2),
6274 COMPRESS(zlib, "deflate"),
6275 COMPRESS(gzip, "gzip"),
6276 COMPRESS(lzma, "x-tor-lzma"),
6277 COMPRESS(zstd, "x-zstd"),
6278 COMPRESS(zstd_nostatic, "x-zstd:nostatic"),
6279 COMPRESS(none, "identity"),
6280 COMPRESS_CONCAT(zlib, "deflate"),
6281 COMPRESS_CONCAT(gzip, "gzip"),
6282 COMPRESS_CONCAT(lzma, "x-tor-lzma"),
6283 COMPRESS_CONCAT(zstd, "x-zstd"),
6284 COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"),
6285 COMPRESS_CONCAT(none, "identity"),
6286 COMPRESS_JUNK(zlib, "deflate"),
6287 COMPRESS_JUNK(gzip, "gzip"),
6288 COMPRESS_JUNK(lzma, "x-tor-lzma"),
6289 COMPRESS_DOS(zlib, "deflate"),
6290 COMPRESS_DOS(gzip, "gzip"),
6291 COMPRESS_DOS(lzma, "x-tor-lzma"),
6292 COMPRESS_DOS(zstd, "x-zstd"),
6293 COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"),
6294 UTIL_TEST(gzip_compression_bomb, TT_FORK),
6295 UTIL_LEGACY(datadir),
6296 UTIL_LEGACY(memarea),
6297 UTIL_LEGACY(control_formats),
6298 UTIL_LEGACY(mmap),
6299 UTIL_TEST(sscanf, TT_FORK),
6300 UTIL_LEGACY(format_time_interval),
6301 UTIL_LEGACY(path_is_relative),
6302 UTIL_LEGACY(strtok),
6303 UTIL_LEGACY(di_ops),
6304 UTIL_TEST(di_map, 0),
6305 UTIL_TEST(round_to_next_multiple_of, 0),
6306 UTIL_TEST(laplace, 0),
6307 UTIL_TEST(clamp_double_to_int64, 0),
6308 UTIL_TEST(find_str_at_start_of_line, 0),
6309 UTIL_TEST(string_is_C_identifier, 0),
6310 UTIL_TEST(string_is_utf8, 0),
6311 UTIL_TEST(asprintf, 0),
6312 UTIL_TEST(listdir, 0),
6313 UTIL_TEST(parent_dir, 0),
6314 UTIL_TEST(ftruncate, 0),
6315 UTIL_TEST(nowrap_math, 0),
6316 UTIL_TEST(num_cpus, 0),
6317 UTIL_TEST_WIN_ONLY(load_win_lib, 0),
6318 UTIL_TEST(format_hex_number, 0),
6319 UTIL_TEST(format_dec_number, 0),
6320 UTIL_TEST(n_bits_set, 0),
6321 UTIL_TEST(eat_whitespace, 0),
6322 UTIL_TEST(sl_new_from_text_lines, 0),
6323 UTIL_TEST(envnames, 0),
6324 UTIL_TEST(make_environment, 0),
6325 UTIL_TEST(set_env_var_in_sl, 0),
6326 UTIL_TEST(read_file_eof_tiny_limit, 0),
6327 UTIL_TEST(read_file_eof_one_loop_a, 0),
6328 UTIL_TEST(read_file_eof_one_loop_b, 0),
6329 UTIL_TEST(read_file_eof_two_loops, 0),
6330 UTIL_TEST(read_file_eof_two_loops_b, 0),
6331 UTIL_TEST(read_file_eof_zero_bytes, 0),
6332 UTIL_TEST(write_chunks_to_file, 0),
6333 UTIL_TEST(mathlog, 0),
6334 UTIL_TEST(fraction, 0),
6335 UTIL_TEST(weak_random, 0),
6336 { "tor_isinf", test_tor_isinf, TT_FORK, NULL, NULL },
6337 { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
6338 (void*)"4" },
6339 { "socket_ipv6", test_util_socket, TT_FORK,
6340 &passthrough_setup, (void*)"6" },
6341 { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
6342 (void*)"0" },
6343 { "socketpair_ersatz", test_util_socketpair, TT_FORK,
6344 &passthrough_setup, (void*)"1" },
6345 UTIL_TEST(max_mem, 0),
6346 UTIL_TEST(hostname_validation, 0),
6347 UTIL_TEST(dest_validation_edgecase, 0),
6348 UTIL_TEST(ipv4_validation, 0),
6349 UTIL_TEST(ipv6_validation, 0),
6350 UTIL_TEST(writepid, 0),
6351 UTIL_TEST(get_avail_disk_space, 0),
6352 UTIL_TEST(touch_file, 0),
6353 UTIL_TEST_NO_WIN(pwdb, TT_FORK),
6354 UTIL_TEST(calloc_check, 0),
6355 UTIL_TEST(monotonic_time, 0),
6356 UTIL_TEST(monotonic_time_ratchet, TT_FORK),
6357 UTIL_TEST(monotonic_time_zero, 0),
6358 UTIL_TEST(monotonic_time_add_msec, 0),
6359 UTIL_TEST(htonll, 0),
6360 UTIL_TEST(get_unquoted_path, 0),
6361 UTIL_TEST(log_mallinfo, 0),
6362 UTIL_TEST(map_anon, 0),
6363 UTIL_TEST(map_anon_nofork, 0),
6364 END_OF_TESTCASES