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