TOR_VEGAS: Implement Prop#324 TOR_VEGAS.
[tor.git] / src / test / test_util.c
blob291a97d52bb5e31723b932cb9fe9200c5f31e228
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 setup_full_capture_of_logs(LOG_WARN); \
823 } while (0)
824 #define CHECK_TIMEGM_WARNING(msg) do { \
825 expect_single_log_msg_containing(msg); \
826 teardown_capture_of_logs(); \
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 teardown_capture_of_logs(); \
833 } while (0)
835 #define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
836 CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")
838 /* year */
840 /* Wrong year < 1970 */
841 a_time.tm_year = 1969-1900;
842 CAPTURE();
843 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
844 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
846 a_time.tm_year = -1-1900;
847 CAPTURE();
848 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
849 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
851 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
852 a_time.tm_year = -1*(1 << 16);
853 CAPTURE();
854 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
855 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
857 /* one of the smallest tm_year values my 64 bit system supports:
858 * t_res = -9223372036854775LL without clamping */
859 a_time.tm_year = -292275055-1900;
860 CAPTURE();
861 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
862 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
864 a_time.tm_year = INT32_MIN;
865 CAPTURE();
866 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
867 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
868 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
870 #if SIZEOF_INT == 8
871 a_time.tm_year = -1*(1 << 48);
872 CAPTURE();
873 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
874 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
876 /* while unlikely, the system's gmtime(_r) could return
877 * a "correct" retrospective gregorian negative year value,
878 * which I'm pretty sure is:
879 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
880 * 730485 is the number of days in two millennia, including leap days */
881 a_time.tm_year = -292277022657-1900;
882 CAPTURE();
883 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
884 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
886 a_time.tm_year = INT64_MIN;
887 CAPTURE();
888 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
889 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
890 #endif /* SIZEOF_INT == 8 */
892 /* Wrong year >= INT32_MAX - 1900 */
893 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
894 a_time.tm_year = INT32_MAX-1900;
895 CAPTURE();
896 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
897 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
899 a_time.tm_year = INT32_MAX;
900 CAPTURE();
901 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
902 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
903 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
905 #if SIZEOF_INT == 8
906 /* one of the largest tm_year values my 64 bit system supports */
907 a_time.tm_year = 292278994-1900;
908 CAPTURE();
909 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
910 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
912 /* while unlikely, the system's gmtime(_r) could return
913 * a "correct" proleptic gregorian year value,
914 * which I'm pretty sure is:
915 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
916 * 730485 is the number of days in two millennia, including leap days */
917 a_time.tm_year = 292277026596-1900;
918 CAPTURE();
919 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
920 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
922 a_time.tm_year = INT64_MAX-1900;
923 CAPTURE();
924 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
925 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
927 a_time.tm_year = INT64_MAX;
928 CAPTURE();
929 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
930 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
931 #endif /* SIZEOF_INT == 8 */
933 /* month */
934 a_time.tm_year = 2007-1900; /* restore valid year */
936 a_time.tm_mon = 12; /* Wrong month, it's 0-based */
937 CAPTURE();
938 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
939 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
941 a_time.tm_mon = -1; /* Wrong month */
942 CAPTURE();
943 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
944 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
946 /* day */
947 a_time.tm_mon = 6; /* Try July */
948 a_time.tm_mday = 32; /* Wrong day */
949 CAPTURE();
950 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
951 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
953 a_time.tm_mon = 5; /* Try June */
954 a_time.tm_mday = 31; /* Wrong day */
955 CAPTURE();
956 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
957 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
959 a_time.tm_year = 2008-1900; /* Try a leap year */
960 a_time.tm_mon = 1; /* in feb. */
961 a_time.tm_mday = 30; /* Wrong day */
962 CAPTURE();
963 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
964 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
966 a_time.tm_year = 2011-1900; /* Try a non-leap year */
967 a_time.tm_mon = 1; /* in feb. */
968 a_time.tm_mday = 29; /* Wrong day */
969 CAPTURE();
970 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
971 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
973 a_time.tm_mday = 0; /* Wrong day, it's 1-based (to be different) */
974 CAPTURE();
975 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
976 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
978 /* hour */
979 a_time.tm_mday = 3; /* restore valid month day */
981 a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
982 CAPTURE();
983 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
984 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
986 a_time.tm_hour = -1; /* Wrong hour */
987 CAPTURE();
988 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
989 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
991 /* minute */
992 a_time.tm_hour = 22; /* restore valid hour */
994 a_time.tm_min = 60; /* Wrong minute, it's 0-based */
995 CAPTURE();
996 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
997 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
999 a_time.tm_min = -1; /* Wrong minute */
1000 CAPTURE();
1001 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
1002 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
1004 /* second */
1005 a_time.tm_min = 37; /* restore valid minute */
1007 a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
1008 CAPTURE();
1009 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
1010 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
1012 a_time.tm_sec = -1; /* Wrong second */
1013 CAPTURE();
1014 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
1015 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
1017 /* Test tor_gmtime_r out of range */
1019 /* time_t < 0 yields a year clamped to 1 or 1970,
1020 * depending on whether the implementation of the system gmtime(_r)
1021 * sets struct tm (1) or not (1970) */
1022 t_res = -1;
1023 CAPTURE();
1024 tor_gmtime_r(&t_res, &b_time);
1025 CHECK_POSSIBLE_EINVAL();
1026 tt_assert(b_time.tm_year == (1970-1900) ||
1027 b_time.tm_year == (1969-1900));
1029 if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
1030 t_res = -1*(1 << 30);
1031 CAPTURE();
1032 tor_gmtime_r(&t_res, &b_time);
1033 CHECK_POSSIBLE_EINVAL();
1034 tt_assert(b_time.tm_year == (1970-1900) ||
1035 b_time.tm_year == (1935-1900));
1037 t_res = INT32_MIN;
1038 CAPTURE();
1039 tor_gmtime_r(&t_res, &b_time);
1040 CHECK_POSSIBLE_EINVAL();
1041 tt_assert(b_time.tm_year == (1970-1900) ||
1042 b_time.tm_year == (1901-1900));
1045 #if SIZEOF_TIME_T == 8
1047 /* one of the smallest tm_year values my 64 bit system supports:
1048 * b_time.tm_year == (-292275055LL-1900LL) without clamping */
1049 t_res = -9223372036854775LL;
1050 CAPTURE();
1051 tor_gmtime_r(&t_res, &b_time);
1052 CHECK_POSSIBLE_EINVAL();
1053 tt_assert(b_time.tm_year == (1970-1900) ||
1054 b_time.tm_year == (1-1900));
1056 /* while unlikely, the system's gmtime(_r) could return
1057 * a "correct" retrospective gregorian negative year value,
1058 * which I'm pretty sure is:
1059 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
1060 * 730485 is the number of days in two millennia, including leap days
1061 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
1062 t_res = INT64_MIN;
1063 CAPTURE();
1064 tor_gmtime_r(&t_res, &b_time);
1065 if (! (b_time.tm_year == (1970-1900) ||
1066 b_time.tm_year == (1-1900))) {
1067 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
1069 if (b_time.tm_year != 1970-1900) {
1070 CHECK_TIMEGM_WARNING("Rounding up to ");
1071 } else {
1072 teardown_capture_of_logs();
1076 /* As above, but with localtime. */
1077 t_res = -9223372036854775LL;
1078 CAPTURE();
1079 tor_localtime_r(&t_res, &b_time);
1080 CHECK_POSSIBLE_EINVAL();
1081 tt_assert(b_time.tm_year == (1970-1900) ||
1082 b_time.tm_year == (1-1900));
1084 /* while unlikely, the system's gmtime(_r) could return
1085 * a "correct" retrospective gregorian negative year value,
1086 * which I'm pretty sure is:
1087 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
1088 * 730485 is the number of days in two millennia, including leap days
1089 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
1090 t_res = INT64_MIN;
1091 CAPTURE();
1092 tor_localtime_r(&t_res, &b_time);
1093 if (! (b_time.tm_year == (1970-1900) ||
1094 b_time.tm_year == (1-1900))) {
1095 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
1097 if (b_time.tm_year != 1970-1900) {
1098 CHECK_TIMEGM_WARNING("Rounding up to ");
1099 } else {
1100 teardown_capture_of_logs();
1103 #endif /* SIZEOF_TIME_T == 8 */
1105 /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
1106 * depending on whether the implementation of the system gmtime(_r)
1107 * sets struct tm (9999) or not (2037) */
1108 #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
1110 t_res = 3*(1 << 29);
1111 tor_gmtime_r(&t_res, &b_time);
1112 tt_assert(b_time.tm_year == (2021-1900));
1114 t_res = INT32_MAX;
1115 tor_gmtime_r(&t_res, &b_time);
1116 tt_assert(b_time.tm_year == (2037-1900) ||
1117 b_time.tm_year == (2038-1900));
1120 /* as above but with localtime. */
1121 t_res = 3*(1 << 29);
1122 tor_localtime_r(&t_res, &b_time);
1123 tt_assert(b_time.tm_year == (2021-1900));
1125 t_res = INT32_MAX;
1126 tor_localtime_r(&t_res, &b_time);
1127 tt_assert(b_time.tm_year == (2037-1900) ||
1128 b_time.tm_year == (2038-1900));
1130 #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */
1132 #if SIZEOF_TIME_T == 8
1134 /* one of the largest tm_year values my 64 bit system supports:
1135 * b_time.tm_year == (292278994L-1900L) without clamping */
1136 t_res = 9223372036854775LL;
1137 CAPTURE();
1138 tor_gmtime_r(&t_res, &b_time);
1139 CHECK_POSSIBLE_EINVAL();
1140 tt_assert(b_time.tm_year == (2037-1900) ||
1141 b_time.tm_year == (9999-1900));
1143 /* while unlikely, the system's gmtime(_r) could return
1144 * a "correct" proleptic gregorian year value,
1145 * which I'm pretty sure is:
1146 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1147 * 730485 is the number of days in two millennia, including leap days
1148 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1149 t_res = INT64_MAX;
1150 CAPTURE();
1151 tor_gmtime_r(&t_res, &b_time);
1152 CHECK_TIMEGM_WARNING("Rounding down to ");
1154 tt_assert(b_time.tm_year == (2037-1900) ||
1155 b_time.tm_year == (9999-1900));
1158 /* As above but with localtime. */
1159 t_res = 9223372036854775LL;
1160 CAPTURE();
1161 tor_localtime_r(&t_res, &b_time);
1162 CHECK_POSSIBLE_EINVAL();
1163 tt_assert(b_time.tm_year == (2037-1900) ||
1164 b_time.tm_year == (9999-1900));
1166 /* while unlikely, the system's gmtime(_r) could return
1167 * a "correct" proleptic gregorian year value,
1168 * which I'm pretty sure is:
1169 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1170 * 730485 is the number of days in two millennia, including leap days
1171 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1172 t_res = INT64_MAX;
1173 CAPTURE();
1174 tor_localtime_r(&t_res, &b_time);
1175 CHECK_TIMEGM_WARNING("Rounding down to ");
1177 tt_assert(b_time.tm_year == (2037-1900) ||
1178 b_time.tm_year == (9999-1900));
1180 #endif /* SIZEOF_TIME_T == 8 */
1182 /* Test {format,parse}_rfc1123_time */
1184 format_rfc1123_time(timestr, 0);
1185 tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
1186 format_rfc1123_time(timestr, (time_t)1091580502UL);
1187 tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
1189 t_res = 0;
1190 i = parse_rfc1123_time(timestr, &t_res);
1191 tt_int_op(0,OP_EQ, i);
1192 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1194 /* This value is in range with 32 bit and 64 bit time_t */
1195 format_rfc1123_time(timestr, (time_t)2080000000UL);
1196 tt_str_op("Fri, 30 Nov 2035 01:46:40 GMT",OP_EQ, timestr);
1198 t_res = 0;
1199 i = parse_rfc1123_time(timestr, &t_res);
1200 tt_int_op(0,OP_EQ, i);
1201 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1203 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1204 * time_t */
1205 CAPTURE();
1206 format_rfc1123_time(timestr, (time_t)2150000000UL);
1207 CHECK_POSSIBLE_EINVAL();
1209 #if SIZEOF_TIME_T == 4
1210 #if 0
1211 /* Wrapping around will have made it this. */
1212 /* On windows, at least, this is clipped to 1 Jan 1970. ??? */
1213 tt_str_op("Sat, 11 Jan 1902 23:45:04 GMT",OP_EQ, timestr);
1214 #endif
1215 /* Make sure that the right date doesn't parse. */
1216 strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr));
1218 t_res = 0;
1219 CAPTURE();
1220 i = parse_rfc1123_time(timestr, &t_res);
1221 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1222 tt_int_op(-1,OP_EQ, i);
1223 #elif SIZEOF_TIME_T == 8
1224 tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr);
1226 t_res = 0;
1227 i = parse_rfc1123_time(timestr, &t_res);
1228 tt_int_op(0,OP_EQ, i);
1229 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1230 #endif /* SIZEOF_TIME_T == 4 || ... */
1232 /* The timezone doesn't matter */
1233 t_res = 0;
1234 tt_int_op(0,OP_EQ,
1235 parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
1236 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1237 tt_int_op(-1,OP_EQ,
1238 parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
1239 tt_int_op(-1,OP_EQ,
1240 parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
1241 tt_int_op(-1,OP_EQ,
1242 parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
1243 tt_int_op(-1,OP_EQ,
1244 parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
1245 tt_int_op(-1,OP_EQ,
1246 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
1247 tt_int_op(-1,OP_EQ,
1248 parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
1249 tt_int_op(-1,OP_EQ,
1250 parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
1251 tt_int_op(-1,OP_EQ,
1252 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
1253 tt_int_op(-1,OP_EQ,
1254 parse_rfc1123_time("Wed, 30 Mar 1900 23:59:59 GMT", &t_res));
1256 /* Leap year. */
1257 tt_int_op(-1,OP_EQ,
1258 parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
1259 tt_int_op(0,OP_EQ,
1260 parse_rfc1123_time("Wed, 29 Feb 2012 16:00:00 GMT", &t_res));
1262 /* Leap second plus one */
1263 tt_int_op(-1,OP_EQ,
1264 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
1266 /* Test parse_iso_time */
1268 t_res = 0;
1269 i = parse_iso_time("", &t_res);
1270 tt_int_op(-1,OP_EQ, i);
1271 t_res = 0;
1272 i = parse_iso_time("2004-08-32 00:48:22", &t_res);
1273 tt_int_op(-1,OP_EQ, i);
1274 t_res = 0;
1275 i = parse_iso_time("1969-08-03 00:48:22", &t_res);
1276 tt_int_op(-1,OP_EQ, i);
1278 t_res = 0;
1279 i = parse_iso_time("2004-08-04 00:48:22", &t_res);
1280 tt_int_op(0,OP_EQ, i);
1281 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1282 t_res = 0;
1283 i = parse_iso_time("2004-8-4 0:48:22", &t_res);
1284 tt_int_op(0,OP_EQ, i);
1285 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1287 /* This value is in range with 32 bit and 64 bit time_t */
1288 t_res = 0;
1289 i = parse_iso_time("2035-11-30 01:46:40", &t_res);
1290 tt_int_op(0,OP_EQ, i);
1291 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1293 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1294 * time_t */
1295 t_res = 0;
1296 #if SIZEOF_TIME_T == 4
1297 CAPTURE();
1298 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1299 tt_int_op(-1,OP_EQ, i);
1300 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1301 #elif SIZEOF_TIME_T == 8
1302 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1303 tt_int_op(0,OP_EQ, i);
1304 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1305 #endif /* SIZEOF_TIME_T == 4 || ... */
1307 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
1308 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
1309 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
1310 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
1311 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
1312 tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
1313 tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
1314 tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
1315 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
1316 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
1317 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
1319 /* but... that _is_ acceptable if we aren't being strict. */
1320 t_res = 0;
1321 i = parse_iso_time_("2004-08-04 00:48:22XYZ", &t_res, 0, 0);
1322 tt_int_op(0,OP_EQ, i);
1323 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1325 /* try nospace variant. */
1326 t_res = 0;
1327 i = parse_iso_time_nospace("2004-08-04T00:48:22", &t_res);
1328 tt_int_op(0,OP_EQ, i);
1329 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1331 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04T00:48:22", &t_res));
1332 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04 00:48:22", &t_res));
1333 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04x00:48:22", &t_res));
1334 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04x00:48:22", &t_res));
1336 /* Test tor_gettimeofday */
1338 end.tv_sec = 4;
1339 end.tv_usec = 999990;
1340 start.tv_sec = 1;
1341 start.tv_usec = 500;
1343 tor_gettimeofday(&start);
1344 /* now make sure time works. */
1345 tor_gettimeofday(&end);
1346 /* We might've timewarped a little. */
1347 tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
1349 /* Test format_iso_time */
1351 tv.tv_sec = (time_t)1326296338UL;
1352 tv.tv_usec = 3060;
1353 format_iso_time(timestr, (time_t)tv.tv_sec);
1354 tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
1355 /* The output of format_local_iso_time will vary by timezone, and setting
1356 our timezone for testing purposes would be a nontrivial flaky pain.
1357 Skip this test for now.
1358 format_local_iso_time(timestr, tv.tv_sec);
1359 test_streq("2012-01-11 10:38:58", timestr);
1361 format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
1362 tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
1363 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
1364 format_iso_time_nospace_usec(timestr, &tv);
1365 tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
1366 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
1368 tv.tv_usec = 0;
1369 /* This value is in range with 32 bit and 64 bit time_t */
1370 tv.tv_sec = (time_t)2080000000UL;
1371 format_iso_time(timestr, (time_t)tv.tv_sec);
1372 tt_str_op("2035-11-30 01:46:40",OP_EQ, timestr);
1374 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1375 * time_t */
1376 tv.tv_sec = (time_t)2150000000UL;
1377 CAPTURE();
1378 format_iso_time(timestr, (time_t)tv.tv_sec);
1379 CHECK_POSSIBLE_EINVAL();
1380 #if SIZEOF_TIME_T == 4
1381 /* format_iso_time should indicate failure on overflow, but it doesn't yet.
1382 * Hopefully #18480 will improve the failure semantics in this case.
1383 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1385 #elif SIZEOF_TIME_T == 8
1386 #ifndef _WIN32
1387 /* This SHOULD work on windows too; see bug #18665 */
1388 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1389 #endif
1390 #endif /* SIZEOF_TIME_T == 4 || ... */
1392 #undef CAPTURE
1393 #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE
1394 #undef CHECK_POSSIBLE_EINVAL
1396 done:
1397 teardown_capture_of_logs();
1400 static void
1401 test_util_parse_http_time(void *arg)
1403 struct tm a_time;
1404 char b[ISO_TIME_LEN+1];
1405 (void)arg;
1407 #define T(s) do { \
1408 format_iso_time(b, tor_timegm(&a_time)); \
1409 tt_str_op(b, OP_EQ, (s)); \
1410 b[0]='\0'; \
1411 } while (0)
1413 /* Test parse_http_time */
1415 tt_int_op(-1,OP_EQ,
1416 parse_http_time("", &a_time));
1417 tt_int_op(-1,OP_EQ,
1418 parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
1419 tt_int_op(-1,OP_EQ,
1420 parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
1421 tt_int_op(-1,OP_EQ,
1422 parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
1423 tt_int_op(-1,OP_EQ,
1424 parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
1425 tt_int_op(-1,OP_EQ,
1426 parse_http_time("Sunday, August the third", &a_time));
1427 tt_int_op(-1,OP_EQ,
1428 parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
1430 tt_int_op(0,OP_EQ,
1431 parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
1432 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1433 T("1994-08-04 00:48:22");
1434 tt_int_op(0,OP_EQ,
1435 parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
1436 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1437 T("1994-08-04 00:48:22");
1438 tt_int_op(0,OP_EQ,
1439 parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
1440 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1441 T("1994-08-04 00:48:22");
1442 tt_int_op(0,OP_EQ,
1443 parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
1444 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1445 T("1994-08-04 00:48:22");
1446 tt_int_op(0,OP_EQ,
1447 parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
1448 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1449 T("1994-08-04 00:48:22");
1450 tt_int_op(0,OP_EQ,
1451 parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
1452 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1453 T("1994-08-04 00:48:22");
1454 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
1455 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1456 T("1994-08-04 00:48:22");
1457 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
1458 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1459 T("1994-08-04 00:48:22");
1460 tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
1461 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1462 T("1994-08-04 00:48:22");
1463 tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
1464 tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
1465 T("2012-01-01 00:00:00");
1466 tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
1467 tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
1468 T("2012-12-31 00:00:00");
1470 /* This value is in range with 32 bit and 64 bit time_t */
1471 tt_int_op(0,OP_EQ,parse_http_time("Fri, 30 Nov 2035 01:46:40 GMT", &a_time));
1472 tt_int_op((time_t)2080000000UL,OP_EQ, tor_timegm(&a_time));
1473 T("2035-11-30 01:46:40");
1475 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1476 * time_t */
1477 #if SIZEOF_TIME_T == 4
1478 /* parse_http_time should indicate failure on overflow, but it doesn't yet.
1479 * Hopefully #18480 will improve the failure semantics in this case. */
1480 setup_full_capture_of_logs(LOG_WARN);
1481 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1482 tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time));
1483 expect_single_log_msg_containing("does not fit in tor_timegm");
1484 teardown_capture_of_logs();
1485 #elif SIZEOF_TIME_T == 8
1486 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1487 tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time));
1488 T("2038-02-17 06:13:20");
1489 #endif /* SIZEOF_TIME_T == 4 || ... */
1491 tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
1492 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
1493 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
1494 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
1495 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
1496 tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
1497 tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
1498 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
1500 #undef T
1501 done:
1502 teardown_capture_of_logs();
1505 static void
1506 test_util_timegm_real(void *arg)
1508 (void)arg;
1509 /* Get the real timegm again! We're not testing our impl; we want the
1510 * one that will actually get called. */
1511 #undef tor_timegm
1513 /* Now check: is timegm the real inverse of gmtime? */
1514 time_t now = time(NULL), time2=0;
1515 struct tm tm, *p;
1516 p = tor_gmtime_r(&now, &tm);
1517 tt_ptr_op(p, OP_NE, NULL);
1519 int r = tor_timegm(&tm, &time2);
1520 tt_int_op(r, OP_EQ, 0);
1521 tt_i64_op((int64_t) now, OP_EQ, (int64_t) time2);
1523 done:
1527 static void
1528 test_util_config_line(void *arg)
1530 char buf[1024];
1531 char *k=NULL, *v=NULL;
1532 const char *str;
1534 /* Test parse_config_line_from_str */
1535 (void)arg;
1536 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
1537 "k2\n"
1538 "k3 \n" "\n" " \n" "#comment\n"
1539 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
1540 "kseven \"a quoted 'string\"\n"
1541 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
1542 "k9 a line that\\\n spans two lines.\n\n"
1543 "k10 more than\\\n one contin\\\nuation\n"
1544 "k11 \\\ncontinuation at the start\n"
1545 "k12 line with a\\\n#comment\n embedded\n"
1546 "k13\\\ncontinuation at the very start\n"
1547 "k14 a line that has a comment and # ends with a slash \\\n"
1548 "k15 this should be the next new line\n"
1549 "k16 a line that has a comment and # ends without a slash \n"
1550 "k17 this should be the next new line\n"
1551 , sizeof(buf));
1552 str = buf;
1554 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1555 tt_str_op(k,OP_EQ, "k");
1556 tt_str_op(v,OP_EQ, "v");
1557 tor_free(k); tor_free(v);
1558 tt_assert(!strcmpstart(str, "key value with"));
1560 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1561 tt_str_op(k,OP_EQ, "key");
1562 tt_str_op(v,OP_EQ, "value with spaces");
1563 tor_free(k); tor_free(v);
1564 tt_assert(!strcmpstart(str, "keykey"));
1566 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1567 tt_str_op(k,OP_EQ, "keykey");
1568 tt_str_op(v,OP_EQ, "val");
1569 tor_free(k); tor_free(v);
1570 tt_assert(!strcmpstart(str, "k2\n"));
1572 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1573 tt_str_op(k,OP_EQ, "k2");
1574 tt_str_op(v,OP_EQ, "");
1575 tor_free(k); tor_free(v);
1576 tt_assert(!strcmpstart(str, "k3 \n"));
1578 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1579 tt_str_op(k,OP_EQ, "k3");
1580 tt_str_op(v,OP_EQ, "");
1581 tor_free(k); tor_free(v);
1582 tt_assert(!strcmpstart(str, "#comment"));
1584 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1585 tt_str_op(k,OP_EQ, "k4");
1586 tt_str_op(v,OP_EQ, "");
1587 tor_free(k); tor_free(v);
1588 tt_assert(!strcmpstart(str, "k5#abc"));
1590 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1591 tt_str_op(k,OP_EQ, "k5");
1592 tt_str_op(v,OP_EQ, "");
1593 tor_free(k); tor_free(v);
1594 tt_assert(!strcmpstart(str, "k6"));
1596 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1597 tt_str_op(k,OP_EQ, "k6");
1598 tt_str_op(v,OP_EQ, "val");
1599 tor_free(k); tor_free(v);
1600 tt_assert(!strcmpstart(str, "kseven"));
1602 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1603 tt_str_op(k,OP_EQ, "kseven");
1604 tt_str_op(v,OP_EQ, "a quoted \'string");
1605 tor_free(k); tor_free(v);
1606 tt_assert(!strcmpstart(str, "k8 "));
1608 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1609 tt_str_op(k,OP_EQ, "k8");
1610 tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
1611 tor_free(k); tor_free(v);
1613 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1614 tt_str_op(k,OP_EQ, "k9");
1615 tt_str_op(v,OP_EQ, "a line that spans two lines.");
1616 tor_free(k); tor_free(v);
1618 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1619 tt_str_op(k,OP_EQ, "k10");
1620 tt_str_op(v,OP_EQ, "more than one continuation");
1621 tor_free(k); tor_free(v);
1623 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1624 tt_str_op(k,OP_EQ, "k11");
1625 tt_str_op(v,OP_EQ, "continuation at the start");
1626 tor_free(k); tor_free(v);
1628 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1629 tt_str_op(k,OP_EQ, "k12");
1630 tt_str_op(v,OP_EQ, "line with a embedded");
1631 tor_free(k); tor_free(v);
1633 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1634 tt_str_op(k,OP_EQ, "k13");
1635 tt_str_op(v,OP_EQ, "continuation at the very start");
1636 tor_free(k); tor_free(v);
1638 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1639 tt_str_op(k,OP_EQ, "k14");
1640 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1641 tor_free(k); tor_free(v);
1643 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1644 tt_str_op(k,OP_EQ, "k15");
1645 tt_str_op(v,OP_EQ, "this should be the next new line");
1646 tor_free(k); tor_free(v);
1648 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1649 tt_str_op(k,OP_EQ, "k16");
1650 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1651 tor_free(k); tor_free(v);
1653 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1654 tt_str_op(k,OP_EQ, "k17");
1655 tt_str_op(v,OP_EQ, "this should be the next new line");
1656 tor_free(k); tor_free(v);
1658 tt_str_op(str,OP_EQ, "");
1660 done:
1661 tor_free(k);
1662 tor_free(v);
1665 static void
1666 test_util_config_line_quotes(void *arg)
1668 char buf1[1024];
1669 char buf2[128];
1670 char buf3[128];
1671 char buf4[128];
1672 char *k=NULL, *v=NULL;
1673 const char *str;
1675 /* Test parse_config_line_from_str */
1676 (void)arg;
1677 strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
1678 "kTrailingGarbage \"quoted value\"trailing garbage\n"
1679 , sizeof(buf1));
1680 strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
1681 , sizeof(buf2));
1682 strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
1683 , sizeof(buf3));
1684 strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
1685 , sizeof(buf4));
1686 str = buf1;
1688 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1689 tt_str_op(k,OP_EQ, "kTrailingSpace");
1690 tt_str_op(v,OP_EQ, "quoted value");
1691 tor_free(k); tor_free(v);
1693 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1694 tt_ptr_op(str,OP_EQ, NULL);
1695 tor_free(k); tor_free(v);
1697 str = buf2;
1699 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1700 tt_ptr_op(str,OP_EQ, NULL);
1701 tor_free(k); tor_free(v);
1703 str = buf3;
1705 const char *err = NULL;
1706 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1707 tt_ptr_op(str,OP_EQ, NULL);
1708 tor_free(k); tor_free(v);
1709 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1711 str = buf4;
1713 err = NULL;
1714 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1715 tt_ptr_op(str,OP_EQ, NULL);
1716 tor_free(k); tor_free(v);
1717 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1719 done:
1720 tor_free(k);
1721 tor_free(v);
1724 static void
1725 test_util_config_line_comment_character(void *arg)
1727 char buf[1024];
1728 char *k=NULL, *v=NULL;
1729 const char *str;
1731 /* Test parse_config_line_from_str */
1732 (void)arg;
1733 strlcpy(buf, "k1 \"# in quotes\"\n"
1734 "k2 some value # some comment\n"
1735 "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
1736 , sizeof(buf));
1737 str = buf;
1739 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1740 tt_str_op(k,OP_EQ, "k1");
1741 tt_str_op(v,OP_EQ, "# in quotes");
1742 tor_free(k); tor_free(v);
1744 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1745 tt_str_op(k,OP_EQ, "k2");
1746 tt_str_op(v,OP_EQ, "some value");
1747 tor_free(k); tor_free(v);
1749 tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
1751 #if 0
1752 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1753 test_streq(k, "k3");
1754 test_streq(v, "/home/user/myTorNetwork#2");
1755 tor_free(k); tor_free(v);
1757 test_streq(str, "");
1758 #endif /* 0 */
1760 done:
1761 tor_free(k);
1762 tor_free(v);
1765 static void
1766 test_util_config_line_escaped_content(void *arg)
1768 char buf1[1024];
1769 char buf2[128];
1770 char buf3[128];
1771 char buf4[128];
1772 char buf5[128];
1773 char buf6[128];
1774 char *k=NULL, *v=NULL;
1775 const char *str;
1777 /* Test parse_config_line_from_str */
1778 (void)arg;
1779 strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
1780 "HexadecimalUpper \"\\x2A\"\n"
1781 "HexadecimalUpperX \"\\X2A\"\n"
1782 "Octal \"\\52\"\n"
1783 "Newline \"\\n\"\n"
1784 "Tab \"\\t\"\n"
1785 "CarriageReturn \"\\r\"\n"
1786 "DoubleQuote \"\\\"\"\n"
1787 "SimpleQuote \"\\'\"\n"
1788 "Backslash \"\\\\\"\n"
1789 "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
1790 , sizeof(buf1));
1792 strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
1793 , sizeof(buf2));
1795 strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
1796 , sizeof(buf3));
1798 strlcpy(buf4, "BrokenOctal \"\\8\"\n"
1799 , sizeof(buf4));
1801 strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
1802 , sizeof(buf5));
1804 strlcpy(buf6, "BrokenEscape \"\\"
1805 , sizeof(buf6));
1807 str = buf1;
1809 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1810 tt_str_op(k,OP_EQ, "HexadecimalLower");
1811 tt_str_op(v,OP_EQ, "*");
1812 tor_free(k); tor_free(v);
1814 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1815 tt_str_op(k,OP_EQ, "HexadecimalUpper");
1816 tt_str_op(v,OP_EQ, "*");
1817 tor_free(k); tor_free(v);
1819 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1820 tt_str_op(k,OP_EQ, "HexadecimalUpperX");
1821 tt_str_op(v,OP_EQ, "*");
1822 tor_free(k); tor_free(v);
1824 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1825 tt_str_op(k,OP_EQ, "Octal");
1826 tt_str_op(v,OP_EQ, "*");
1827 tor_free(k); tor_free(v);
1829 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1830 tt_str_op(k,OP_EQ, "Newline");
1831 tt_str_op(v,OP_EQ, "\n");
1832 tor_free(k); tor_free(v);
1834 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1835 tt_str_op(k,OP_EQ, "Tab");
1836 tt_str_op(v,OP_EQ, "\t");
1837 tor_free(k); tor_free(v);
1839 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1840 tt_str_op(k,OP_EQ, "CarriageReturn");
1841 tt_str_op(v,OP_EQ, "\r");
1842 tor_free(k); tor_free(v);
1844 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1845 tt_str_op(k,OP_EQ, "DoubleQuote");
1846 tt_str_op(v,OP_EQ, "\"");
1847 tor_free(k); tor_free(v);
1849 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1850 tt_str_op(k,OP_EQ, "SimpleQuote");
1851 tt_str_op(v,OP_EQ, "'");
1852 tor_free(k); tor_free(v);
1854 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1855 tt_str_op(k,OP_EQ, "Backslash");
1856 tt_str_op(v,OP_EQ, "\\");
1857 tor_free(k); tor_free(v);
1859 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1860 tt_str_op(k,OP_EQ, "Mix");
1861 tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
1862 tor_free(k); tor_free(v);
1863 tt_str_op(str,OP_EQ, "");
1865 str = buf2;
1867 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1868 tt_ptr_op(str,OP_EQ, NULL);
1869 tor_free(k); tor_free(v);
1871 str = buf3;
1873 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1874 tt_ptr_op(str,OP_EQ, NULL);
1875 tor_free(k); tor_free(v);
1877 str = buf4;
1879 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1880 tt_ptr_op(str,OP_EQ, NULL);
1881 tor_free(k); tor_free(v);
1883 #if 0
1884 str = buf5;
1886 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1887 tt_ptr_op(str, OP_EQ, NULL);
1888 tor_free(k); tor_free(v);
1889 #endif /* 0 */
1891 str = buf6;
1893 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1894 tt_ptr_op(str,OP_EQ, NULL);
1895 tor_free(k); tor_free(v);
1897 /* more things to try. */
1898 /* Bad hex: */
1899 strlcpy(buf1, "Foo \"\\x9g\"\n", sizeof(buf1));
1900 strlcpy(buf2, "Foo \"\\xg0\"\n", sizeof(buf2));
1901 strlcpy(buf3, "Foo \"\\xf\"\n", sizeof(buf3));
1902 /* bad escape */
1903 strlcpy(buf4, "Foo \"\\q\"\n", sizeof(buf4));
1904 /* missing endquote */
1905 strlcpy(buf5, "Foo \"hello\n", sizeof(buf5));
1906 /* extra stuff */
1907 strlcpy(buf6, "Foo \"hello\" world\n", sizeof(buf6));
1909 str=buf1;
1910 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1911 tt_ptr_op(str,OP_EQ, NULL);
1912 tor_free(k); tor_free(v);
1914 str=buf2;
1915 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1916 tt_ptr_op(str,OP_EQ, NULL);
1917 tor_free(k); tor_free(v);
1919 str=buf3;
1920 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1921 tt_ptr_op(str,OP_EQ, NULL);
1922 tor_free(k); tor_free(v);
1924 str=buf4;
1925 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1926 tt_ptr_op(str,OP_EQ, NULL);
1927 tor_free(k); tor_free(v);
1929 str=buf5;
1931 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1932 tt_ptr_op(str,OP_EQ, NULL);
1933 tor_free(k); tor_free(v);
1935 str=buf6;
1936 const char *err = NULL;
1937 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1938 tt_ptr_op(str,OP_EQ, NULL);
1939 tor_free(k); tor_free(v);
1940 tt_str_op(err,OP_EQ, "Excess data after quoted string");
1942 done:
1943 tor_free(k);
1944 tor_free(v);
1947 static void
1948 test_util_config_line_crlf(void *arg)
1950 char *k=NULL, *v=NULL;
1951 const char *err = NULL;
1952 (void)arg;
1953 const char *str =
1954 "Hello world\r\n"
1955 "Hello \"nice big world\"\r\n";
1957 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1958 tt_assert(str);
1959 tt_str_op(k,OP_EQ,"Hello");
1960 tt_str_op(v,OP_EQ,"world");
1961 tt_ptr_op(err, OP_EQ, NULL);
1962 tor_free(k); tor_free(v);
1964 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1965 tt_assert(str);
1966 tt_str_op(k,OP_EQ,"Hello");
1967 tt_str_op(v,OP_EQ,"nice big world");
1968 tt_ptr_op(err, OP_EQ, NULL);
1969 tor_free(k); tor_free(v);
1970 tt_str_op(str,OP_EQ, "");
1972 done:
1973 tor_free(k); tor_free(v);
1976 static void
1977 test_util_config_line_partition(void *arg)
1979 (void)arg;
1980 config_line_t *lines = NULL, *orig, *rest = NULL;
1982 config_line_append(&lines, "Header", "X");
1983 config_line_append(&lines, "Item", "Y");
1984 config_line_append(&lines, "Thing", "Z");
1986 config_line_append(&lines, "HEADER", "X2");
1988 config_line_append(&lines, "header", "X3");
1989 config_line_append(&lines, "Item3", "Foob");
1991 /* set up h2 and h3 to point to the places where we hope the headers will
1992 be. */
1993 config_line_t *h2 = lines->next->next->next;
1994 config_line_t *h3 = h2->next;
1995 tt_str_op(h2->key, OP_EQ, "HEADER");
1996 tt_str_op(h3->key, OP_EQ, "header");
1998 orig = lines;
1999 rest = config_lines_partition(lines, "Header");
2000 tt_ptr_op(lines, OP_EQ, orig);
2001 tt_ptr_op(rest, OP_EQ, h2);
2002 tt_str_op(lines->next->key, OP_EQ, "Item");
2003 tt_str_op(lines->next->next->key, OP_EQ, "Thing");
2004 tt_ptr_op(lines->next->next->next, OP_EQ, NULL);
2005 config_free_lines(lines);
2007 orig = lines = rest;
2008 rest = config_lines_partition(lines, "Header");
2009 tt_ptr_op(lines, OP_EQ, orig);
2010 tt_ptr_op(rest, OP_EQ, h3);
2011 tt_ptr_op(lines->next, OP_EQ, NULL);
2012 config_free_lines(lines);
2014 orig = lines = rest;
2015 rest = config_lines_partition(lines, "Header");
2016 tt_ptr_op(lines, OP_EQ, orig);
2017 tt_ptr_op(rest, OP_EQ, NULL);
2018 tt_str_op(lines->next->key, OP_EQ, "Item3");
2019 tt_ptr_op(lines->next->next, OP_EQ, NULL);
2021 done:
2022 config_free_lines(lines);
2023 config_free_lines(rest);
2026 #ifndef DISABLE_PWDB_TESTS
2027 static void
2028 test_util_expand_filename(void *arg)
2030 char *str;
2032 (void)arg;
2033 setenv("HOME", "/home/itv", 1); /* For "internal test value" */
2035 str = expand_filename("");
2036 tt_str_op("",OP_EQ, str);
2037 tor_free(str);
2039 str = expand_filename("/normal/path");
2040 tt_str_op("/normal/path",OP_EQ, str);
2041 tor_free(str);
2043 str = expand_filename("/normal/trailing/path/");
2044 tt_str_op("/normal/trailing/path/",OP_EQ, str);
2045 tor_free(str);
2047 str = expand_filename("~");
2048 tt_str_op("/home/itv/",OP_EQ, str);
2049 tor_free(str);
2051 str = expand_filename("$HOME/nodice");
2052 tt_str_op("$HOME/nodice",OP_EQ, str);
2053 tor_free(str);
2055 str = expand_filename("~/");
2056 tt_str_op("/home/itv/",OP_EQ, str);
2057 tor_free(str);
2059 str = expand_filename("~/foobarqux");
2060 tt_str_op("/home/itv/foobarqux",OP_EQ, str);
2061 tor_free(str);
2063 str = expand_filename("~/../../etc/passwd");
2064 tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
2065 tor_free(str);
2067 str = expand_filename("~/trailing/");
2068 tt_str_op("/home/itv/trailing/",OP_EQ, str);
2069 tor_free(str);
2070 /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
2071 have to somehow inject/fake the get_user_homedir call) */
2073 /* $HOME ending in a trailing slash */
2074 setenv("HOME", "/home/itv/", 1);
2076 str = expand_filename("~");
2077 tt_str_op("/home/itv/",OP_EQ, str);
2078 tor_free(str);
2080 str = expand_filename("~/");
2081 tt_str_op("/home/itv/",OP_EQ, str);
2082 tor_free(str);
2084 str = expand_filename("~/foo");
2085 tt_str_op("/home/itv/foo",OP_EQ, str);
2086 tor_free(str);
2088 /* Try with empty $HOME */
2090 setenv("HOME", "", 1);
2092 str = expand_filename("~");
2093 tt_str_op("/",OP_EQ, str);
2094 tor_free(str);
2096 str = expand_filename("~/");
2097 tt_str_op("/",OP_EQ, str);
2098 tor_free(str);
2100 str = expand_filename("~/foobar");
2101 tt_str_op("/foobar",OP_EQ, str);
2102 tor_free(str);
2104 /* Try with $HOME unset */
2106 unsetenv("HOME");
2108 str = expand_filename("~");
2109 tt_str_op("/",OP_EQ, str);
2110 tor_free(str);
2112 str = expand_filename("~/");
2113 tt_str_op("/",OP_EQ, str);
2114 tor_free(str);
2116 str = expand_filename("~/foobar");
2117 tt_str_op("/foobar",OP_EQ, str);
2118 tor_free(str);
2120 done:
2121 tor_free(str);
2123 #endif /* !defined(DISABLE_PWDB_TESTS) */
2125 /** Test tor_escape_str_for_pt_args(). */
2126 static void
2127 test_util_escape_string_socks(void *arg)
2129 char *escaped_string = NULL;
2131 /** Simple backslash escape. */
2132 (void)arg;
2133 escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
2134 tt_assert(escaped_string);
2135 tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
2136 tor_free(escaped_string);
2138 /** Simple semicolon escape. */
2139 escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
2140 tt_assert(escaped_string);
2141 tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
2142 tor_free(escaped_string);
2144 /** Empty string. */
2145 escaped_string = tor_escape_str_for_pt_args("", ";\\");
2146 tt_assert(escaped_string);
2147 tt_str_op(escaped_string,OP_EQ, "");
2148 tor_free(escaped_string);
2150 /** Escape all characters. */
2151 escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
2152 tt_assert(escaped_string);
2153 tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
2154 tor_free(escaped_string);
2156 escaped_string = tor_escape_str_for_pt_args(";", ";\\");
2157 tt_assert(escaped_string);
2158 tt_str_op(escaped_string,OP_EQ, "\\;");
2159 tor_free(escaped_string);
2161 done:
2162 tor_free(escaped_string);
2165 static void
2166 test_util_string_is_key_value(void *ptr)
2168 (void)ptr;
2169 tt_assert(string_is_key_value(LOG_WARN, "key=value"));
2170 tt_assert(string_is_key_value(LOG_WARN, "k=v"));
2171 tt_assert(string_is_key_value(LOG_WARN, "key="));
2172 tt_assert(string_is_key_value(LOG_WARN, "x="));
2173 tt_assert(string_is_key_value(LOG_WARN, "xx="));
2174 tt_assert(!string_is_key_value(LOG_WARN, "=value"));
2175 tt_assert(!string_is_key_value(LOG_WARN, "=x"));
2176 tt_assert(!string_is_key_value(LOG_WARN, "="));
2178 /* ??? */
2179 /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
2180 done:
2184 /** Test basic string functionality. */
2185 static void
2186 test_util_strmisc(void *arg)
2188 char buf[1024];
2189 char *cp_tmp = NULL;
2191 /* Test strl operations */
2192 (void)arg;
2193 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
2194 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
2195 tt_str_op(buf,OP_EQ, "Hello");
2196 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
2197 tt_str_op(buf,OP_EQ, "Hello");
2198 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
2199 tt_str_op(buf,OP_EQ, "Hell");
2200 strlcpy(buf, "Hello", sizeof(buf));
2201 tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
2203 /* Test strstrip() */
2204 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
2205 tor_strstrip(buf, ",!");
2206 tt_str_op(buf,OP_EQ, "Testing 1 2 3");
2207 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
2208 tor_strstrip(buf, "!? ");
2209 tt_str_op(buf,OP_EQ, "Testing123");
2210 strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
2211 tor_strstrip(buf, "!? ");
2212 tt_str_op(buf,OP_EQ, "Testing123");
2214 /* Test snprintf */
2215 /* Returning -1 when there's not enough room in the output buffer */
2216 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
2217 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
2218 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
2219 tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
2220 /* Always NUL-terminate the output */
2221 tor_snprintf(buf, 5, "abcdef");
2222 tt_int_op(0,OP_EQ, buf[4]);
2223 tor_snprintf(buf, 10, "abcdef");
2224 tt_int_op(0,OP_EQ, buf[6]);
2225 /* uint64 */
2226 tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x",
2227 (UINT64_C(12345678901)));
2228 tt_str_op("x!12345678901!x",OP_EQ, buf);
2230 /* Test str{,case}cmpstart */
2231 tt_assert(strcmpstart("abcdef", "abcdef")==0);
2232 tt_assert(strcmpstart("abcdef", "abc")==0);
2233 tt_assert(strcmpstart("abcdef", "abd")<0);
2234 tt_assert(strcmpstart("abcdef", "abb")>0);
2235 tt_assert(strcmpstart("ab", "abb")<0);
2236 tt_assert(strcmpstart("ab", "")==0);
2237 tt_assert(strcmpstart("ab", "ab ")<0);
2238 tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
2239 tt_assert(strcasecmpstart("abcDeF", "abc")==0);
2240 tt_assert(strcasecmpstart("abcdef", "Abd")<0);
2241 tt_assert(strcasecmpstart("Abcdef", "abb")>0);
2242 tt_assert(strcasecmpstart("ab", "Abb")<0);
2243 tt_assert(strcasecmpstart("ab", "")==0);
2244 tt_assert(strcasecmpstart("ab", "ab ")<0);
2246 /* Test str{,case}cmpend */
2247 tt_assert(strcmpend("abcdef", "abcdef")==0);
2248 tt_assert(strcmpend("abcdef", "def")==0);
2249 tt_assert(strcmpend("abcdef", "deg")<0);
2250 tt_assert(strcmpend("abcdef", "dee")>0);
2251 tt_assert(strcmpend("ab", "aab")>0);
2252 tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
2253 tt_assert(strcasecmpend("abcdef", "dEF")==0);
2254 tt_assert(strcasecmpend("abcdef", "Deg")<0);
2255 tt_assert(strcasecmpend("abcDef", "dee")>0);
2256 tt_assert(strcasecmpend("AB", "abb")<0);
2258 /* Test digest_is_zero */
2259 memset(buf,0,20);
2260 buf[20] = 'x';
2261 tt_assert(tor_digest_is_zero(buf));
2262 buf[19] = 'x';
2263 tt_assert(!tor_digest_is_zero(buf));
2265 /* Test mem_is_zero */
2266 memset(buf,0,128);
2267 buf[128] = 'x';
2268 tt_assert(fast_mem_is_zero(buf, 10));
2269 tt_assert(fast_mem_is_zero(buf, 20));
2270 tt_assert(fast_mem_is_zero(buf, 128));
2271 tt_assert(!fast_mem_is_zero(buf, 129));
2272 buf[60] = (char)255;
2273 tt_assert(!fast_mem_is_zero(buf, 128));
2274 buf[0] = (char)1;
2275 tt_assert(!fast_mem_is_zero(buf, 10));
2277 /* Test 'escaped' */
2278 tt_ptr_op(escaped(NULL), OP_EQ, NULL);
2279 tt_str_op("\"\"",OP_EQ, escaped(""));
2280 tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
2281 tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
2282 tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
2283 escaped("unnecessary \'backslashes\'"));
2284 /* Non-printable characters appear as octal */
2285 tt_str_op("\"z\\001abc\\277d\"",OP_EQ, escaped("z\001abc\277d"));
2286 tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
2288 /* Other cases of esc_for_log{,_len} */
2289 cp_tmp = esc_for_log(NULL);
2290 tt_str_op(cp_tmp, OP_EQ, "(null)");
2291 tor_free(cp_tmp);
2292 cp_tmp = esc_for_log_len("abcdefg", 3);
2293 tt_str_op(cp_tmp, OP_EQ, "\"abc\"");
2294 tor_free(cp_tmp);
2295 cp_tmp = esc_for_log_len("abcdefg", 100);
2296 tt_str_op(cp_tmp, OP_EQ, "\"abcdefg\"");
2297 tor_free(cp_tmp);
2299 /* Test strndup and memdup */
2301 const char *s = "abcdefghijklmnopqrstuvwxyz";
2302 cp_tmp = tor_strndup(s, 30);
2303 tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
2304 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2305 tor_free(cp_tmp);
2307 cp_tmp = tor_strndup(s, 5);
2308 tt_str_op(cp_tmp,OP_EQ, "abcde");
2309 tor_free(cp_tmp);
2311 s = "a\0b\0c\0d\0e\0";
2312 cp_tmp = tor_memdup(s,10);
2313 tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
2314 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2315 tor_free(cp_tmp);
2318 /* Test str-foo functions */
2319 cp_tmp = tor_strdup("abcdef");
2320 tt_assert(tor_strisnonupper(cp_tmp));
2321 cp_tmp[3] = 'D';
2322 tt_assert(!tor_strisnonupper(cp_tmp));
2323 tor_strupper(cp_tmp);
2324 tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
2325 tor_strlower(cp_tmp);
2326 tt_str_op(cp_tmp,OP_EQ, "abcdef");
2327 tt_assert(tor_strisnonupper(cp_tmp));
2328 tt_assert(tor_strisprint(cp_tmp));
2329 cp_tmp[3] = 3;
2330 tt_assert(!tor_strisprint(cp_tmp));
2331 tor_free(cp_tmp);
2333 /* Test memmem and memstr */
2335 const char *haystack = "abcde";
2336 tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL);
2337 tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
2338 tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
2339 tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL);
2340 haystack = "ababcad";
2341 tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
2342 tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
2343 tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
2344 tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL);
2345 tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL);
2346 /* memstr */
2347 tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
2348 tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
2349 tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL);
2350 tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL);
2351 tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL);
2352 tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL);
2355 /* Test hex_str */
2357 char binary_data[68];
2358 size_t idx;
2359 for (idx = 0; idx < sizeof(binary_data); ++idx)
2360 binary_data[idx] = idx;
2361 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2362 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2363 tt_str_op(hex_str(binary_data, 17),OP_EQ,
2364 "000102030405060708090A0B0C0D0E0F10");
2365 tt_str_op(hex_str(binary_data, 32),OP_EQ,
2366 "000102030405060708090A0B0C0D0E0F"
2367 "101112131415161718191A1B1C1D1E1F");
2368 tt_str_op(hex_str(binary_data, 34),OP_EQ,
2369 "000102030405060708090A0B0C0D0E0F"
2370 "101112131415161718191A1B1C1D1E1F");
2371 /* Repeat these tests for shorter strings after longer strings
2372 have been tried, to make sure we're correctly terminating strings */
2373 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2374 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2377 /* Test strcmp_opt */
2378 tt_int_op(strcmp_opt("", "foo"), OP_LT, 0);
2379 tt_int_op(strcmp_opt("", ""), OP_EQ, 0);
2380 tt_int_op(strcmp_opt("foo", ""), OP_GT, 0);
2382 tt_int_op(strcmp_opt(NULL, ""), OP_LT, 0);
2383 tt_int_op(strcmp_opt(NULL, NULL), OP_EQ, 0);
2384 tt_int_op(strcmp_opt("", NULL), OP_GT, 0);
2386 tt_int_op(strcmp_opt(NULL, "foo"), OP_LT, 0);
2387 tt_int_op(strcmp_opt("foo", NULL), OP_GT, 0);
2389 done:
2390 tor_free(cp_tmp);
2393 static void
2394 test_util_parse_integer(void *arg)
2396 (void)arg;
2397 int i;
2398 char *cp;
2400 /* Test parse_long */
2401 /* Empty/zero input */
2402 tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
2403 tt_int_op(0,OP_EQ, i);
2404 tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
2405 tt_int_op(1,OP_EQ, i);
2406 /* Normal cases */
2407 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
2408 tt_int_op(1,OP_EQ, i);
2409 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
2410 tt_int_op(1,OP_EQ, i);
2411 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
2412 tt_int_op(1,OP_EQ, i);
2413 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
2414 tt_int_op(1,OP_EQ, i);
2415 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
2416 tt_int_op(1,OP_EQ, i);
2417 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
2418 tt_int_op(1,OP_EQ, i);
2419 /* Extra garbage */
2420 tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
2421 tt_int_op(0,OP_EQ, i);
2422 tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
2423 tt_int_op(0,OP_EQ, i);
2424 tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
2425 tt_int_op(1,OP_EQ, i);
2426 tt_str_op(cp,OP_EQ, "m");
2427 tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
2428 tt_int_op(1,OP_EQ, i);
2429 tt_str_op(cp,OP_EQ, " plus garbage");
2430 /* Illogical min max */
2431 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL));
2432 tt_int_op(0,OP_EQ, i);
2433 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL));
2434 tt_int_op(0,OP_EQ, i);
2435 /* Out of bounds */
2436 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
2437 tt_int_op(0,OP_EQ, i);
2438 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,0,100,&i,NULL));
2439 tt_int_op(0,OP_EQ, i);
2440 /* Base different than 10 */
2441 tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL));
2442 tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
2443 tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
2444 tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
2445 tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
2446 tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
2447 tt_int_op(i,OP_EQ, 0);
2449 /* Test parse_ulong */
2450 tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
2451 tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
2452 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
2453 tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
2454 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
2455 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
2456 tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
2457 tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
2458 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
2459 tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
2460 tt_int_op(0,OP_EQ, i);
2461 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
2462 tt_int_op(0,OP_EQ, i);
2464 /* Test parse_uint64 */
2465 tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
2466 tt_int_op(1,OP_EQ, i);
2467 tt_str_op(cp,OP_EQ, " x");
2468 tt_assert(UINT64_C(12345678901) ==
2469 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
2470 tt_int_op(1,OP_EQ, i);
2471 tt_str_op(cp,OP_EQ, "");
2472 tt_assert(UINT64_C(0) ==
2473 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
2474 tt_int_op(0,OP_EQ, i);
2475 tt_assert(UINT64_C(0) ==
2476 tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
2477 tt_int_op(0,OP_EQ, i);
2480 /* Test parse_double */
2481 double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
2482 tt_int_op(1,OP_EQ, i);
2483 tt_assert(((uint64_t)d) == 10);
2484 d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
2485 tt_int_op(1,OP_EQ, i);
2486 tt_assert(((uint64_t)d) == 0);
2487 d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
2488 tt_double_op(fabs(d), OP_LT, 1e-10);
2489 tt_int_op(0,OP_EQ, i);
2490 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL);
2491 tt_double_op(fabs(d), OP_LT, 1e-10);
2492 tt_int_op(0,OP_EQ, i);
2493 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp);
2494 tt_double_op(fabs(d), OP_LT, 1e-10);
2495 tt_int_op(1,OP_EQ, i);
2496 d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
2497 tt_int_op(1,OP_EQ, i);
2498 tt_assert(((uint64_t)d) == 0);
2499 d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
2500 tt_int_op(1,OP_EQ, i);
2501 tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
2505 /* Test tor_parse_* where we overflow/underflow the underlying type. */
2506 /* This string should overflow 64-bit ints. */
2507 #define TOOBIG "100000000000000000000000000"
2508 tt_int_op(0L, OP_EQ,
2509 tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2510 tt_int_op(i,OP_EQ, 0);
2511 tt_int_op(0L,OP_EQ,
2512 tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2513 tt_int_op(i,OP_EQ, 0);
2514 tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
2515 tt_int_op(i,OP_EQ, 0);
2516 tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
2517 0, UINT64_MAX, &i, NULL));
2518 tt_int_op(i,OP_EQ, 0);
2520 done:
2524 static void
2525 test_util_pow2(void *arg)
2527 /* Test tor_log2(). */
2528 (void)arg;
2529 tt_int_op(tor_log2(64),OP_EQ, 6);
2530 tt_int_op(tor_log2(65),OP_EQ, 6);
2531 tt_int_op(tor_log2(63),OP_EQ, 5);
2532 /* incorrect mathematically, but as specified: */
2533 tt_int_op(tor_log2(0),OP_EQ, 0);
2534 tt_int_op(tor_log2(1),OP_EQ, 0);
2535 tt_int_op(tor_log2(2),OP_EQ, 1);
2536 tt_int_op(tor_log2(3),OP_EQ, 1);
2537 tt_int_op(tor_log2(4),OP_EQ, 2);
2538 tt_int_op(tor_log2(5),OP_EQ, 2);
2539 tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55);
2540 tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
2542 /* Test round_to_power_of_2 */
2543 tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
2544 tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
2545 tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
2546 tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ,
2547 UINT64_C(1)<<55);
2548 tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ,
2549 UINT64_C(1)<<63);
2550 tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
2551 tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
2552 tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
2553 tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
2554 tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
2555 tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
2556 tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
2557 tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
2559 done:
2563 static void
2564 test_util_compress_impl(compress_method_t method)
2566 char *buf1=NULL, *buf2=NULL, *buf3=NULL;
2567 size_t len1, len2;
2569 tt_assert(tor_compress_supports_method(method));
2571 if (method != NO_METHOD) {
2572 tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
2573 tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
2576 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
2577 tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
2579 tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
2580 tt_ptr_op(buf2, OP_NE, NULL);
2581 if (method == NO_METHOD) {
2582 // The identity transform doesn't actually compress, and it isn't
2583 // detectable as "the identity transform."
2584 tt_int_op(len1, OP_EQ, strlen(buf1)+1);
2585 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
2586 } else {
2587 tt_int_op(len1, OP_LT, strlen(buf1));
2588 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
2591 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
2592 tt_ptr_op(buf3, OP_NE, NULL);
2593 tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
2594 tt_str_op(buf1, OP_EQ, buf3);
2595 tt_int_op(buf3[len2], OP_EQ, 0);
2597 /* Check whether we can uncompress concatenated, compressed strings. */
2598 tor_free(buf3);
2599 buf2 = tor_reallocarray(buf2, len1, 2);
2600 memcpy(buf2+len1, buf2, len1);
2601 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
2602 tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
2603 tt_mem_op(buf3, OP_EQ,
2604 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
2605 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
2606 (strlen(buf1)+1)*2);
2607 tt_int_op(buf3[len2], OP_EQ, 0);
2609 /* Check whether we can uncompress partial strings */
2611 tor_free(buf1);
2612 tor_free(buf2);
2613 tor_free(buf3);
2615 size_t b1len = 1<<10;
2616 if (method == ZSTD_METHOD) {
2617 // zstd needs a big input before it starts generating output that it
2618 // can partially decompress.
2619 b1len = 1<<18;
2621 buf1 = tor_malloc(b1len);
2622 crypto_rand(buf1, b1len);
2623 tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
2624 tt_int_op(len1, OP_GT, 16);
2625 /* when we allow an incomplete output we should succeed.*/
2626 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
2627 method, 0, LOG_INFO));
2628 tt_int_op(len2, OP_GT, 5);
2629 tt_int_op(len2, OP_LE, len1);
2630 tt_assert(fast_memeq(buf1, buf3, len2));
2631 tt_int_op(buf3[len2], OP_EQ, 0);
2633 /* when we demand a complete output from a real compression method, this
2634 * must fail. */
2635 tor_free(buf3);
2636 if (method != NO_METHOD) {
2637 tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
2638 method, 1, LOG_INFO));
2639 tt_ptr_op(buf3, OP_EQ, NULL);
2642 done:
2643 tor_free(buf1);
2644 tor_free(buf2);
2645 tor_free(buf3);
2648 static void
2649 test_util_compress_stream_impl(compress_method_t method,
2650 compression_level_t level)
2652 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
2653 const char *ccp2;
2654 size_t len1, len2;
2656 tor_compress_state_t *state = NULL;
2657 state = tor_compress_new(1, method, level);
2658 tt_assert(state);
2659 cp1 = buf1 = tor_malloc(1024);
2660 len1 = 1024;
2661 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
2662 len2 = 21;
2663 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
2664 OP_EQ, TOR_COMPRESS_OK);
2665 tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
2666 tt_assert(cp1 > buf1);
2668 len2 = 0;
2669 cp2 = cp1;
2670 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
2671 OP_EQ, TOR_COMPRESS_DONE);
2672 tt_int_op(0, OP_EQ, len2);
2673 if (method == NO_METHOD) {
2674 tt_ptr_op(cp1, OP_EQ, cp2);
2675 } else {
2676 tt_assert(cp1 > cp2); /* Make sure we really added something. */
2679 tt_int_op(tor_compress_state_size(state), OP_GT, 0);
2681 tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
2682 method, 1, LOG_WARN));
2683 /* Make sure it compressed right. */
2684 tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
2685 tt_int_op(21, OP_EQ, len2);
2687 done:
2688 if (state)
2689 tor_compress_free(state);
2690 tor_free(buf1);
2691 tor_free(buf2);
2692 tor_free(buf3);
2695 /** Setup function for compression tests: handles x-zstd:nostatic
2697 static void *
2698 compression_test_setup(const struct testcase_t *testcase)
2700 tor_assert(testcase->setup_data);
2701 tor_assert(testcase->setup_data != (void*)TT_SKIP);
2702 const char *methodname = testcase->setup_data;
2704 if (!strcmp(methodname, "x-zstd:nostatic")) {
2705 methodname = "x-zstd";
2706 tor_zstd_set_static_apis_disabled_for_testing(1);
2709 return (void *)methodname;
2712 /** Cleanup for compression tests: disables nostatic */
2713 static int
2714 compression_test_cleanup(const struct testcase_t *testcase, void *ptr)
2716 (void)testcase;
2717 (void)ptr;
2718 tor_zstd_set_static_apis_disabled_for_testing(0);
2719 return 1;
2722 static const struct testcase_setup_t compress_setup = {
2723 compression_test_setup, compression_test_cleanup
2726 /** Run unit tests for compression functions */
2727 static void
2728 test_util_compress(void *arg)
2730 const char *methodname = arg;
2731 tt_assert(methodname);
2733 compress_method_t method = compression_method_get_by_name(methodname);
2734 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2736 if (! tor_compress_supports_method(method)) {
2737 tt_skip();
2740 compression_level_t levels[] = {
2741 BEST_COMPRESSION,
2742 HIGH_COMPRESSION,
2743 MEDIUM_COMPRESSION,
2744 LOW_COMPRESSION
2747 test_util_compress_impl(method);
2749 for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
2750 compression_level_t level = levels[l];
2751 test_util_compress_stream_impl(method, level);
2753 done:
2757 static void
2758 test_util_decompress_concatenated_impl(compress_method_t method)
2760 char input[4096];
2761 char *c1 = NULL, *c2 = NULL, *c3 = NULL;
2762 char *result = NULL;
2763 size_t sz1, sz2, sz3, szr;
2764 int r;
2766 crypto_rand(input, sizeof(input));
2768 /* Compress the input in two chunks. */
2769 r = tor_compress(&c1, &sz1, input, 2048, method);
2770 tt_int_op(r, OP_EQ, 0);
2771 r = tor_compress(&c2, &sz2, input+2048, 2048, method);
2772 tt_int_op(r, OP_EQ, 0);
2774 /* concatenate the chunks. */
2775 sz3 = sz1 + sz2;
2776 c3 = tor_malloc(sz3);
2777 memcpy(c3, c1, sz1);
2778 memcpy(c3+sz1, c2, sz2);
2780 /* decompress the concatenated result */
2781 r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
2782 tt_int_op(r, OP_EQ, 0);
2783 tt_int_op(szr, OP_EQ, sizeof(input));
2784 tt_mem_op(result, OP_EQ, input, sizeof(input));
2786 done:
2787 tor_free(c1);
2788 tor_free(c2);
2789 tor_free(c3);
2790 tor_free(result);
2793 static void
2794 test_util_decompress_concatenated(void *arg)
2796 const char *methodname = arg;
2797 tt_assert(methodname);
2799 compress_method_t method = compression_method_get_by_name(methodname);
2800 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2801 if (! tor_compress_supports_method(method)) {
2802 tt_skip();
2805 test_util_decompress_concatenated_impl(method);
2806 done:
2810 static void
2811 test_util_decompress_junk_impl(compress_method_t method)
2813 char input[4096];
2814 char *result = NULL, *result2 = NULL;
2815 size_t szr, szr2, sz;
2816 int r;
2818 /* This shouldn't be a compressed string according to any method. */
2819 strlcpy(input, "This shouldn't be a compressed string by any means.",
2820 sizeof(input));
2821 sz = strlen(input);
2822 setup_capture_of_logs(LOG_WARN);
2823 r = tor_uncompress(&result, &szr, input, sz, method, 0, LOG_WARN);
2824 tt_int_op(r, OP_EQ, -1);
2825 tt_ptr_op(result, OP_EQ, NULL);
2826 expect_log_msg_containing("Error while uncompressing data: bad input?");
2827 mock_clean_saved_logs();
2829 /* Now try again, with a compressed object that starts out good and turns to
2830 junk. */
2831 crypto_rand(input, sizeof(input));
2832 r = tor_compress(&result, &szr, input, sizeof(input), method);
2833 tt_int_op(r, OP_EQ, 0);
2834 crypto_rand(result+szr/2, szr-(szr/2)); // trash the 2nd half of the result
2835 r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2836 tt_int_op(r, OP_EQ, -1);
2837 expect_log_msg_containing("Error while uncompressing data: bad input?");
2839 done:
2840 teardown_capture_of_logs();
2841 tor_free(result);
2842 tor_free(result2);
2845 static void
2846 test_util_decompress_junk(void *arg)
2848 const char *methodname = arg;
2849 tt_assert(methodname);
2851 compress_method_t method = compression_method_get_by_name(methodname);
2852 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2853 if (! tor_compress_supports_method(method)) {
2854 tt_skip();
2857 test_util_decompress_junk_impl(method);
2858 done:
2862 /* mock replacement for tor_compress_is_compression_bomb that doesn't
2863 * believe in compression bombs. */
2864 static int
2865 mock_is_never_compression_bomb(size_t in, size_t out)
2867 (void)in;
2868 (void) out;
2869 return 0;
2872 static void
2873 test_util_decompress_dos_impl(compress_method_t method)
2875 char *input;
2876 char *result = NULL, *result2 = NULL;
2877 size_t szr, szr2;
2878 int r;
2880 const size_t big = 1024*1024;
2881 /* one megabyte of 0s. */
2882 input = tor_malloc_zero(big);
2884 /* Compress it into "result": it should fail. */
2885 setup_full_capture_of_logs(LOG_WARN);
2886 r = tor_compress(&result, &szr, input, big, method);
2887 tt_int_op(r, OP_EQ, -1);
2888 expect_log_msg_containing(
2889 "other Tors would think this was a compression bomb");
2890 teardown_capture_of_logs();
2892 /* Try again, but this time suppress compression-bomb detection */
2893 MOCK(tor_compress_is_compression_bomb, mock_is_never_compression_bomb);
2894 r = tor_compress(&result, &szr, input, big, method);
2895 UNMOCK(tor_compress_is_compression_bomb);
2896 tt_int_op(r, OP_EQ, 0);
2897 tt_ptr_op(result, OP_NE, NULL);
2899 /* We should refuse to uncomrpess it again, since it looks like a
2900 * compression bomb. */
2901 setup_capture_of_logs(LOG_WARN);
2902 r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2903 tt_int_op(r, OP_EQ, -1);
2904 expect_log_msg_containing("bomb; abandoning stream");
2906 done:
2907 teardown_capture_of_logs();
2908 tor_free(input);
2909 tor_free(result);
2910 tor_free(result2);
2913 static void
2914 test_util_decompress_dos(void *arg)
2916 const char *methodname = arg;
2917 tt_assert(methodname);
2919 compress_method_t method = compression_method_get_by_name(methodname);
2920 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2921 if (! tor_compress_supports_method(method)) {
2922 tt_skip();
2925 test_util_decompress_dos_impl(method);
2926 done:
2930 static void
2931 test_util_gzip_compression_bomb(void *arg)
2933 /* A 'compression bomb' is a very small object that uncompresses to a huge
2934 * one. Most compression formats support them, but they can be a DOS vector.
2935 * In Tor we try not to generate them, and we don't accept them.
2937 (void) arg;
2938 size_t one_million = 1<<20;
2939 char *one_mb = tor_malloc_zero(one_million);
2940 char *result = NULL;
2941 size_t result_len = 0;
2942 tor_compress_state_t *state = NULL;
2944 /* Make sure we can't produce a compression bomb */
2945 setup_full_capture_of_logs(LOG_WARN);
2946 tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
2947 one_mb, one_million,
2948 ZLIB_METHOD));
2949 expect_single_log_msg_containing(
2950 "We compressed something and got an insanely high "
2951 "compression factor; other Tors would think this "
2952 "was a compression bomb.");
2953 teardown_capture_of_logs();
2955 /* Here's a compression bomb that we made manually. */
2956 const char compression_bomb[1039] =
2957 { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
2958 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
2959 tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
2960 compression_bomb, 1039,
2961 ZLIB_METHOD, 0, LOG_WARN));
2963 /* Now try streaming that. */
2964 state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
2965 tor_compress_output_t r;
2966 const char *inp = compression_bomb;
2967 size_t inlen = 1039;
2968 do {
2969 char *outp = one_mb;
2970 size_t outleft = 4096; /* small on purpose */
2971 r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
2972 tt_int_op(inlen, OP_NE, 0);
2973 } while (r == TOR_COMPRESS_BUFFER_FULL);
2975 tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
2977 done:
2978 tor_free(one_mb);
2979 tor_compress_free(state);
2982 /** Run unit tests for mmap() wrapper functionality. */
2983 static void
2984 test_util_mmap(void *arg)
2986 char *fname1 = tor_strdup(get_fname("mapped_1"));
2987 char *fname2 = tor_strdup(get_fname("mapped_2"));
2988 char *fname3 = tor_strdup(get_fname("mapped_3"));
2989 const size_t buflen = 17000;
2990 char *buf = tor_malloc(17000);
2991 tor_mmap_t *mapping = NULL;
2993 (void)arg;
2994 crypto_rand(buf, buflen);
2996 mapping = tor_mmap_file(fname1);
2997 tt_ptr_op(mapping, OP_EQ, NULL);
2999 write_str_to_file(fname1, "Short file.", 1);
3001 mapping = tor_mmap_file(fname1);
3002 tt_assert(mapping);
3003 tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
3004 tt_str_op(mapping->data,OP_EQ, "Short file.");
3005 #ifdef _WIN32
3006 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
3007 mapping = NULL;
3008 tt_assert(unlink(fname1) == 0);
3009 #else
3010 /* make sure we can unlink. */
3011 tt_assert(unlink(fname1) == 0);
3012 tt_str_op(mapping->data,OP_EQ, "Short file.");
3013 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
3014 mapping = NULL;
3015 #endif /* defined(_WIN32) */
3017 /* Now a zero-length file. */
3018 write_str_to_file(fname1, "", 1);
3019 mapping = tor_mmap_file(fname1);
3020 tt_ptr_op(mapping,OP_EQ, NULL);
3021 tt_int_op(ERANGE,OP_EQ, errno);
3022 unlink(fname1);
3024 /* Make sure that we fail to map a no-longer-existent file. */
3025 mapping = tor_mmap_file(fname1);
3026 tt_ptr_op(mapping, OP_EQ, NULL);
3028 /* Now try a big file that stretches across a few pages and isn't aligned */
3029 write_bytes_to_file(fname2, buf, buflen, 1);
3030 mapping = tor_mmap_file(fname2);
3031 tt_assert(mapping);
3032 tt_int_op(mapping->size,OP_EQ, buflen);
3033 tt_mem_op(mapping->data,OP_EQ, buf, buflen);
3034 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
3035 mapping = NULL;
3037 /* Now try a big aligned file. */
3038 write_bytes_to_file(fname3, buf, 16384, 1);
3039 mapping = tor_mmap_file(fname3);
3040 tt_assert(mapping);
3041 tt_int_op(mapping->size,OP_EQ, 16384);
3042 tt_mem_op(mapping->data,OP_EQ, buf, 16384);
3043 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
3044 mapping = NULL;
3046 done:
3047 unlink(fname1);
3048 unlink(fname2);
3049 unlink(fname3);
3051 tor_free(fname1);
3052 tor_free(fname2);
3053 tor_free(fname3);
3054 tor_free(buf);
3056 tor_munmap_file(mapping);
3059 /** Run unit tests for escaping/unescaping data for use by controllers. */
3060 static void
3061 test_util_control_formats(void *arg)
3063 char *out = NULL;
3064 const char *inp =
3065 "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
3066 size_t sz;
3068 (void)arg;
3069 sz = read_escaped_data(inp, strlen(inp), &out);
3070 tt_str_op(out,OP_EQ,
3071 ".This is a test\nof the emergency \n.system.\n\rZ.\n");
3072 tt_int_op(sz,OP_EQ, strlen(out));
3074 done:
3075 tor_free(out);
3078 #define test_feq(value1,value2) do { \
3079 double v1 = (value1), v2=(value2); \
3080 double tf_diff = v1-v2; \
3081 double tf_tolerance = ((v1+v2)/2.0)/1e8; \
3082 if (tf_diff<0) tf_diff=-tf_diff; \
3083 if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
3084 if (tf_diff<tf_tolerance) { \
3085 TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
3086 } else { \
3087 TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
3089 } while (0)
3091 static void
3092 test_util_sscanf(void *arg)
3094 unsigned u1, u2, u3;
3095 unsigned long ulng;
3096 char s1[20], s2[10], s3[10], ch, *huge = NULL;
3097 int r;
3098 long lng1,lng2;
3099 int int1, int2;
3100 double d1,d2,d3,d4;
3102 /* Simple tests (malformed patterns, literal matching, ...) */
3103 (void)arg;
3104 tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
3105 tt_int_op(-1,OP_EQ,
3106 tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
3107 tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
3108 /* this will fail because we don't allow widths longer than 9999 */
3110 huge = tor_malloc(1000000);
3111 r = tor_sscanf("prettylongstring", "%99999s", huge);
3112 tor_free(huge);
3113 tt_int_op(-1,OP_EQ, r);
3115 #if 0
3116 /* GCC thinks these two are illegal. */
3117 test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
3118 test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
3119 #endif
3120 /* No '%'-strings: always "success" */
3121 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
3122 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
3123 /* Excess data */
3124 tt_int_op(0,OP_EQ,
3125 tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
3126 tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
3127 tt_int_op(0,OP_EQ,
3128 tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
3129 tt_int_op(1,OP_EQ,
3130 tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
3132 /* Numbers (ie. %u) */
3133 tt_int_op(0,OP_EQ,
3134 tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
3135 tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
3136 tt_int_op(12345u,OP_EQ, u1);
3137 tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
3138 tt_int_op(12346u,OP_EQ, u1);
3139 tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
3140 tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
3141 tt_int_op(12348u,OP_EQ, u1);
3142 tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
3143 tt_int_op(0u,OP_EQ, u1);
3144 tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
3145 tt_int_op(0u,OP_EQ, u2);
3146 tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
3147 tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
3148 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
3150 /* Numbers with size (eg. %2u) */
3151 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
3152 tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
3153 tt_int_op(12u,OP_EQ, u1);
3154 tt_int_op(3456u,OP_EQ, u2);
3155 tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
3156 tt_int_op(123456u,OP_EQ, u1);
3157 tt_int_op(1,OP_EQ, tor_sscanf("123457 ", "%8u", &u1));
3158 tt_int_op(123457u,OP_EQ, u1);
3159 tt_int_op(0,OP_EQ, tor_sscanf(" 123456", "%8u", &u1));
3160 tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
3161 tt_int_op(12u,OP_EQ, u1);
3162 tt_int_op(3u,OP_EQ, u2);
3163 tt_int_op(456u,OP_EQ, u3);
3164 tt_int_op(3,OP_EQ,
3165 tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
3166 tt_int_op(67u,OP_EQ, u1);
3167 tt_int_op(8u,OP_EQ, u2);
3168 tt_int_op(99u,OP_EQ, u3);
3169 /* %u does not match space.*/
3170 tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
3171 tt_int_op(12u,OP_EQ, u1);
3172 tt_int_op(3u,OP_EQ, u2);
3173 /* %u does not match negative numbers. */
3174 tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
3175 tt_int_op(67u,OP_EQ, u1);
3176 tt_int_op(8u,OP_EQ, u2);
3177 /* Arbitrary amounts of 0-padding are okay */
3178 tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
3179 &u1, &u2, &u3));
3180 tt_int_op(12u,OP_EQ, u1);
3181 tt_int_op(3u,OP_EQ, u2);
3182 tt_int_op(99u,OP_EQ, u3);
3184 /* Hex (ie. %x) */
3185 tt_int_op(3,OP_EQ,
3186 tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
3187 tt_int_op(0x1234,OP_EQ, u1);
3188 tt_int_op(0x2ABCDEF,OP_EQ, u2);
3189 tt_int_op(0xFF,OP_EQ, u3);
3190 /* Width works on %x */
3191 tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
3192 tt_int_op(0xf00d,OP_EQ, u1);
3193 tt_int_op(0xcafe,OP_EQ, u2);
3194 tt_int_op(444,OP_EQ, u3);
3196 /* Literal '%' (ie. '%%') */
3197 tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
3198 tt_int_op(99,OP_EQ, u1);
3199 tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
3200 tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
3201 tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
3202 tt_int_op(99,OP_EQ, u1);
3203 tt_str_op(s1,OP_EQ, "fresh");
3204 tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
3205 tt_str_op("boo",OP_EQ, s1);
3207 /* Strings (ie. %s) */
3208 tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
3209 tt_str_op(s1,OP_EQ, "hel");
3210 tt_str_op(s2,OP_EQ, "lo");
3211 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
3212 tt_str_op(s3,OP_EQ, "WD");
3213 tt_int_op(40,OP_EQ, u1);
3214 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
3215 tt_str_op(s3,OP_EQ, "WD4");
3216 tt_int_op(0,OP_EQ, u1);
3217 tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
3218 tt_int_op(76,OP_EQ, u1);
3219 tt_str_op(s1,OP_EQ, "trombones");
3221 huge = tor_malloc(1000);
3222 r = tor_sscanf("prettylongstring", "%999s", huge);
3223 tt_int_op(1,OP_EQ, r);
3224 tt_str_op(huge,OP_EQ, "prettylongstring");
3225 tor_free(huge);
3227 /* %s doesn't eat spaces */
3228 tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
3229 tt_str_op(s1,OP_EQ, "hello");
3230 tt_str_op(s2,OP_EQ, "world");
3231 tt_int_op(2,OP_EQ, tor_sscanf("bye world?", "%9s %9s", s1, s2));
3232 tt_str_op(s1,OP_EQ, "bye");
3233 tt_str_op(s2,OP_EQ, "");
3234 tt_int_op(3,OP_EQ,
3235 tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
3236 tt_str_op(s1,OP_EQ, "hi");
3237 tt_str_op(s2,OP_EQ, "");
3238 tt_str_op(s3,OP_EQ, "");
3240 tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3241 tt_int_op(4,OP_EQ,
3242 tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3243 tt_int_op(' ',OP_EQ, ch);
3245 r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
3246 tt_int_op(r,OP_EQ, 3);
3247 tt_int_op(int1,OP_EQ, 12345);
3248 tt_int_op(lng1,OP_EQ, -67890);
3249 tt_int_op(int2,OP_EQ, -1);
3251 #if SIZEOF_INT == 4
3252 /* %u */
3253 /* UINT32_MAX should work */
3254 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
3255 tt_int_op(4294967295U,OP_EQ, u1);
3257 /* But UINT32_MAX + 1 shouldn't work */
3258 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
3259 /* but parsing only 9... */
3260 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
3261 tt_int_op(429496729U,OP_EQ, u1);
3263 /* %x */
3264 /* UINT32_MAX should work */
3265 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
3266 tt_int_op(0xFFFFFFFF,OP_EQ, u1);
3268 /* But UINT32_MAX + 1 shouldn't work */
3269 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
3271 /* %d */
3272 /* INT32_MIN and INT32_MAX should work */
3273 r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
3274 tt_int_op(r,OP_EQ, 2);
3275 tt_int_op(int1,OP_EQ, -2147483647 - 1);
3276 tt_int_op(int2,OP_EQ, 2147483647);
3278 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3279 r = tor_sscanf("-2147483649.", "%d.", &int1);
3280 tt_int_op(r,OP_EQ, 0);
3282 r = tor_sscanf("2147483648.", "%d.", &int1);
3283 tt_int_op(r,OP_EQ, 0);
3285 /* and the first failure stops further processing */
3286 r = tor_sscanf("-2147483648. 2147483648.",
3287 "%d. %d.", &int1, &int2);
3288 tt_int_op(r,OP_EQ, 1);
3290 r = tor_sscanf("-2147483649. 2147483647.",
3291 "%d. %d.", &int1, &int2);
3292 tt_int_op(r,OP_EQ, 0);
3294 r = tor_sscanf("2147483648. -2147483649.",
3295 "%d. %d.", &int1, &int2);
3296 tt_int_op(r,OP_EQ, 0);
3297 #elif SIZEOF_INT == 8
3298 /* %u */
3299 /* UINT64_MAX should work */
3300 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
3301 tt_int_op(18446744073709551615U,OP_EQ, u1);
3303 /* But UINT64_MAX + 1 shouldn't work */
3304 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
3305 /* but parsing only 19... */
3306 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
3307 tt_int_op(1844674407370955161U,OP_EQ, u1);
3309 /* %x */
3310 /* UINT64_MAX should work */
3311 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
3312 tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
3314 /* But UINT64_MAX + 1 shouldn't work */
3315 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
3317 /* %d */
3318 /* INT64_MIN and INT64_MAX should work */
3319 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3320 "%d. %d.", &int1, &int2);
3321 tt_int_op(r,OP_EQ, 2);
3322 tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
3323 tt_int_op(int2,OP_EQ, 9223372036854775807);
3325 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3326 r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
3327 tt_int_op(r,OP_EQ, 0);
3329 r = tor_sscanf("9223372036854775808.", "%d.", &int1);
3330 tt_int_op(r,OP_EQ, 0);
3332 /* and the first failure stops further processing */
3333 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3334 "%d. %d.", &int1, &int2);
3335 tt_int_op(r,OP_EQ, 1);
3337 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3338 "%d. %d.", &int1, &int2);
3339 tt_int_op(r,OP_EQ, 0);
3341 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3342 "%d. %d.", &int1, &int2);
3343 tt_int_op(r,OP_EQ, 0);
3344 #endif /* SIZEOF_INT == 4 || ... */
3346 #if SIZEOF_LONG == 4
3347 /* %lu */
3348 /* UINT32_MAX should work */
3349 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
3350 tt_int_op(4294967295UL,OP_EQ, ulng);
3352 /* But UINT32_MAX + 1 shouldn't work */
3353 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
3354 /* but parsing only 9... */
3355 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
3356 tt_int_op(429496729UL,OP_EQ, ulng);
3358 /* %lx */
3359 /* UINT32_MAX should work */
3360 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
3361 tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
3363 /* But UINT32_MAX + 1 shouldn't work */
3364 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
3366 /* %ld */
3367 /* INT32_MIN and INT32_MAX should work */
3368 r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
3369 tt_int_op(r,OP_EQ, 2);
3370 tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
3371 tt_int_op(lng2,OP_EQ, 2147483647L);
3373 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3374 r = tor_sscanf("-2147483649.", "%ld.", &lng1);
3375 tt_int_op(r,OP_EQ, 0);
3377 r = tor_sscanf("2147483648.", "%ld.", &lng1);
3378 tt_int_op(r,OP_EQ, 0);
3380 /* and the first failure stops further processing */
3381 r = tor_sscanf("-2147483648. 2147483648.",
3382 "%ld. %ld.", &lng1, &lng2);
3383 tt_int_op(r,OP_EQ, 1);
3385 r = tor_sscanf("-2147483649. 2147483647.",
3386 "%ld. %ld.", &lng1, &lng2);
3387 tt_int_op(r,OP_EQ, 0);
3389 r = tor_sscanf("2147483648. -2147483649.",
3390 "%ld. %ld.", &lng1, &lng2);
3391 tt_int_op(r,OP_EQ, 0);
3392 #elif SIZEOF_LONG == 8
3393 /* %lu */
3394 /* UINT64_MAX should work */
3395 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
3396 tt_int_op(18446744073709551615UL,OP_EQ, ulng);
3398 /* But UINT64_MAX + 1 shouldn't work */
3399 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
3400 /* but parsing only 19... */
3401 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
3402 tt_int_op(1844674407370955161UL,OP_EQ, ulng);
3404 /* %lx */
3405 /* UINT64_MAX should work */
3406 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
3407 tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
3409 /* But UINT64_MAX + 1 shouldn't work */
3410 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
3412 /* %ld */
3413 /* INT64_MIN and INT64_MAX should work */
3414 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3415 "%ld. %ld.", &lng1, &lng2);
3416 tt_int_op(r,OP_EQ, 2);
3417 tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
3418 tt_int_op(lng2,OP_EQ, 9223372036854775807L);
3420 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3421 r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
3422 tt_int_op(r,OP_EQ, 0);
3424 r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
3425 tt_int_op(r,OP_EQ, 0);
3427 /* and the first failure stops further processing */
3428 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3429 "%ld. %ld.", &lng1, &lng2);
3430 tt_int_op(r,OP_EQ, 1);
3432 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3433 "%ld. %ld.", &lng1, &lng2);
3434 tt_int_op(r,OP_EQ, 0);
3436 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3437 "%ld. %ld.", &lng1, &lng2);
3438 tt_int_op(r,OP_EQ, 0);
3439 #endif /* SIZEOF_LONG == 4 || ... */
3441 r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
3442 "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
3443 tt_int_op(r,OP_EQ, 4);
3444 test_feq(d1, 123.456);
3445 test_feq(d2, .000007);
3446 test_feq(d3, -900123123.2000787);
3447 test_feq(d4, 3.2);
3449 /* missing float */
3450 r = tor_sscanf("3 ", "%d %lf", &int1, &d1);
3451 tt_int_op(r, OP_EQ, 1);
3452 tt_int_op(int1, OP_EQ, 3);
3454 /* not a float */
3455 r = tor_sscanf("999 notafloat", "%d %lf", &int1, &d1);
3456 tt_int_op(r, OP_EQ, 1);
3457 tt_int_op(int1, OP_EQ, 999);
3459 /* %s but no buffer. */
3460 char *nullbuf = NULL;
3461 r = tor_sscanf("hello", "%3s", nullbuf);
3462 tt_int_op(r, OP_EQ, 0);
3464 done:
3465 tor_free(huge);
3468 #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
3469 #define tt_ci_char_op(a,op,b) \
3470 tt_char_op(TOR_TOLOWER((int)a),op,TOR_TOLOWER((int)b))
3472 #ifndef HAVE_STRNLEN
3473 static size_t
3474 strnlen(const char *s, size_t len)
3476 const char *p = memchr(s, 0, len);
3477 if (!p)
3478 return len;
3479 return p - s;
3481 #endif /* !defined(HAVE_STRNLEN) */
3483 static void
3484 test_util_format_time_interval(void *arg)
3486 /* use the same sized buffer and integers as tor uses */
3487 #define DBUF_SIZE 64
3488 char dbuf[DBUF_SIZE];
3489 #define T_ "%ld"
3490 long sec, min, hour, day;
3492 /* we don't care about the exact spelling of the
3493 * second(s), minute(s), hour(s), day(s) labels */
3494 #define LABEL_SIZE 21
3495 #define L_ "%20s"
3496 char label_s[LABEL_SIZE];
3497 char label_m[LABEL_SIZE];
3498 char label_h[LABEL_SIZE];
3499 char label_d[LABEL_SIZE];
3501 #define TL_ T_ " " L_
3503 int r;
3505 (void)arg;
3507 /* In these tests, we're not picky about
3508 * spelling or abbreviations */
3510 /* seconds: 0, 1, 9, 10, 59 */
3512 /* ignore exact spelling of "second(s)"*/
3513 format_time_interval(dbuf, sizeof(dbuf), 0);
3514 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3515 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3516 tt_int_op(r,OP_EQ, 2);
3517 tt_ci_char_op(label_s[0],OP_EQ, 's');
3518 tt_int_op(sec,OP_EQ, 0);
3520 format_time_interval(dbuf, sizeof(dbuf), 1);
3521 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3522 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3523 tt_int_op(r,OP_EQ, 2);
3524 tt_ci_char_op(label_s[0],OP_EQ, 's');
3525 tt_int_op(sec,OP_EQ, 1);
3527 format_time_interval(dbuf, sizeof(dbuf), 10);
3528 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3529 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3530 tt_int_op(r,OP_EQ, 2);
3531 tt_ci_char_op(label_s[0],OP_EQ, 's');
3532 tt_int_op(sec,OP_EQ, 10);
3534 format_time_interval(dbuf, sizeof(dbuf), 59);
3535 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3536 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3537 tt_int_op(r,OP_EQ, 2);
3538 tt_ci_char_op(label_s[0],OP_EQ, 's');
3539 tt_int_op(sec,OP_EQ, 59);
3541 /* negative seconds are reported as their absolute value */
3543 format_time_interval(dbuf, sizeof(dbuf), -4);
3544 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3545 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3546 tt_int_op(r,OP_EQ, 2);
3547 tt_ci_char_op(label_s[0],OP_EQ, 's');
3548 tt_int_op(sec,OP_EQ, 4);
3549 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3551 format_time_interval(dbuf, sizeof(dbuf), -32);
3552 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3553 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3554 tt_int_op(r,OP_EQ, 2);
3555 tt_ci_char_op(label_s[0],OP_EQ, 's');
3556 tt_int_op(sec,OP_EQ, 32);
3557 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3559 /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
3561 /* ignore trailing "0 second(s)", if present */
3562 format_time_interval(dbuf, sizeof(dbuf), 60);
3563 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3564 r = tor_sscanf(dbuf, TL_, &min, label_m);
3565 tt_int_op(r,OP_EQ, 2);
3566 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3567 tt_int_op(min,OP_EQ, 1);
3568 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3570 /* ignore exact spelling of "minute(s)," and "second(s)" */
3571 format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
3572 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3573 r = tor_sscanf(dbuf, TL_ " " TL_,
3574 &min, label_m, &sec, label_s);
3575 tt_int_op(r,OP_EQ, 4);
3576 tt_int_op(min,OP_EQ, 1);
3577 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3578 tt_int_op(sec,OP_EQ, 1);
3579 tt_ci_char_op(label_s[0],OP_EQ, 's');
3580 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3582 format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
3583 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3584 r = tor_sscanf(dbuf, TL_ " " TL_,
3585 &min, label_m, &sec, label_s);
3586 tt_int_op(r,OP_EQ, 4);
3587 tt_int_op(min,OP_EQ, 1);
3588 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3589 tt_int_op(sec,OP_EQ, 59);
3590 tt_ci_char_op(label_s[0],OP_EQ, 's');
3592 /* ignore trailing "0 second(s)", if present */
3593 format_time_interval(dbuf, sizeof(dbuf), 60*2);
3594 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3595 r = tor_sscanf(dbuf, TL_, &min, label_m);
3596 tt_int_op(r,OP_EQ, 2);
3597 tt_int_op(min,OP_EQ, 2);
3598 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3600 /* ignore exact spelling of "minute(s)," and "second(s)" */
3601 format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
3602 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3603 r = tor_sscanf(dbuf, TL_ " " TL_,
3604 &min, label_m, &sec, label_s);
3605 tt_int_op(r,OP_EQ, 4);
3606 tt_int_op(min,OP_EQ, 2);
3607 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3608 tt_int_op(sec,OP_EQ, 1);
3609 tt_ci_char_op(label_s[0],OP_EQ, 's');
3611 format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
3612 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3613 r = tor_sscanf(dbuf, TL_ " " TL_,
3614 &min, label_m, &sec, label_s);
3615 tt_int_op(r,OP_EQ, 4);
3616 tt_int_op(min,OP_EQ, 59);
3617 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3618 tt_int_op(sec,OP_EQ, 59);
3619 tt_ci_char_op(label_s[0],OP_EQ, 's');
3621 /* negative minutes are reported as their absolute value */
3623 /* ignore trailing "0 second(s)", if present */
3624 format_time_interval(dbuf, sizeof(dbuf), -3*60);
3625 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3626 r = tor_sscanf(dbuf, TL_, &min, label_m);
3627 tt_int_op(r,OP_EQ, 2);
3628 tt_int_op(min,OP_EQ, 3);
3629 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3631 /* ignore exact spelling of "minute(s)," and "second(s)" */
3632 format_time_interval(dbuf, sizeof(dbuf), -96);
3633 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3634 r = tor_sscanf(dbuf, TL_ " " TL_,
3635 &min, label_m, &sec, label_s);
3636 tt_int_op(r,OP_EQ, 4);
3637 tt_int_op(min,OP_EQ, 1);
3638 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3639 tt_int_op(sec,OP_EQ, 36);
3640 tt_ci_char_op(label_s[0],OP_EQ, 's');
3642 format_time_interval(dbuf, sizeof(dbuf), -2815);
3643 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3644 r = tor_sscanf(dbuf, TL_ " " TL_,
3645 &min, label_m, &sec, label_s);
3646 tt_int_op(r,OP_EQ, 4);
3647 tt_int_op(min,OP_EQ, 46);
3648 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3649 tt_int_op(sec,OP_EQ, 55);
3650 tt_ci_char_op(label_s[0],OP_EQ, 's');
3652 /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
3653 /* always ignore trailing seconds, if present */
3655 /* ignore trailing "0 minute(s)" etc., if present */
3656 format_time_interval(dbuf, sizeof(dbuf), 60*60);
3657 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3658 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3659 tt_int_op(r,OP_EQ, 2);
3660 tt_int_op(hour,OP_EQ, 1);
3661 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3663 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
3664 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3665 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3666 tt_int_op(r,OP_EQ, 2);
3667 tt_int_op(hour,OP_EQ, 1);
3668 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3670 /* ignore exact spelling of "hour(s)," etc. */
3671 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
3672 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3673 r = tor_sscanf(dbuf, TL_ " " TL_,
3674 &hour, label_h, &min, label_m);
3675 tt_int_op(r,OP_EQ, 4);
3676 tt_int_op(hour,OP_EQ, 1);
3677 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3678 tt_int_op(min,OP_EQ, 1);
3679 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3681 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
3682 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3683 r = tor_sscanf(dbuf, TL_ " " TL_,
3684 &hour, label_h, &min, label_m);
3685 tt_int_op(r,OP_EQ, 4);
3686 tt_int_op(hour,OP_EQ, 23);
3687 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3688 tt_int_op(min,OP_EQ, 59);
3689 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3691 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
3692 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3693 r = tor_sscanf(dbuf, TL_ " " TL_,
3694 &hour, label_h, &min, label_m);
3695 tt_int_op(r,OP_EQ, 4);
3696 tt_int_op(hour,OP_EQ, 23);
3697 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3698 tt_int_op(min,OP_EQ, 59);
3699 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3701 /* negative hours are reported as their absolute value */
3703 /* ignore exact spelling of "hour(s)," etc., if present */
3704 format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
3705 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3706 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3707 tt_int_op(r,OP_EQ, 2);
3708 tt_int_op(hour,OP_EQ, 2);
3709 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3711 format_time_interval(dbuf, sizeof(dbuf), -75804);
3712 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3713 r = tor_sscanf(dbuf, TL_ " " TL_,
3714 &hour, label_h, &min, label_m);
3715 tt_int_op(r,OP_EQ, 4);
3716 tt_int_op(hour,OP_EQ, 21);
3717 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3718 tt_int_op(min,OP_EQ, 3);
3719 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3721 /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
3722 /* always ignore trailing seconds, if present */
3724 /* ignore trailing "0 hours(s)" etc., if present */
3725 format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
3726 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3727 r = tor_sscanf(dbuf, TL_, &day, label_d);
3728 tt_int_op(r,OP_EQ, 2);
3729 tt_int_op(day,OP_EQ, 1);
3730 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3732 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
3733 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3734 r = tor_sscanf(dbuf, TL_, &day, label_d);
3735 tt_int_op(r,OP_EQ, 2);
3736 tt_int_op(day,OP_EQ, 1);
3737 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3739 /* ignore exact spelling of "days(s)," etc. */
3740 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
3741 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3742 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3743 &day, label_d, &hour, label_h, &min, label_m);
3744 if (r == -1) {
3745 /* ignore 0 hours(s), if present */
3746 r = tor_sscanf(dbuf, TL_ " " TL_,
3747 &day, label_d, &min, label_m);
3749 tt_assert(r == 4 || r == 6);
3750 tt_int_op(day,OP_EQ, 1);
3751 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3752 if (r == 6) {
3753 tt_int_op(hour,OP_EQ, 0);
3754 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3756 tt_int_op(min,OP_EQ, 1);
3757 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3759 /* ignore trailing "0 minutes(s)" etc., if present */
3760 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
3761 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3762 r = tor_sscanf(dbuf, TL_ " " TL_,
3763 &day, label_d, &hour, label_h);
3764 tt_int_op(r,OP_EQ, 4);
3765 tt_int_op(day,OP_EQ, 1);
3766 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3767 tt_int_op(hour,OP_EQ, 1);
3768 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3770 /* negative days are reported as their absolute value */
3772 format_time_interval(dbuf, sizeof(dbuf), -21936184);
3773 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3774 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3775 &day, label_d, &hour, label_h, &min, label_m);
3776 tt_int_op(r,OP_EQ, 6);
3777 tt_int_op(day,OP_EQ, 253);
3778 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3779 tt_int_op(hour,OP_EQ, 21);
3780 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3781 tt_int_op(min,OP_EQ, 23);
3782 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3784 /* periods > 1 year are reported in days (warn?) */
3786 /* ignore exact spelling of "days(s)," etc., if present */
3787 format_time_interval(dbuf, sizeof(dbuf), 758635154);
3788 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3789 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3790 &day, label_d, &hour, label_h, &min, label_m);
3791 tt_int_op(r,OP_EQ, 6);
3792 tt_int_op(day,OP_EQ, 8780);
3793 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3794 tt_int_op(hour,OP_EQ, 11);
3795 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3796 tt_int_op(min,OP_EQ, 59);
3797 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3799 /* negative periods > 1 year are reported in days (warn?) */
3801 format_time_interval(dbuf, sizeof(dbuf), -1427014922);
3802 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3803 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3804 &day, label_d, &hour, label_h, &min, label_m);
3805 tt_int_op(r,OP_EQ, 6);
3806 tt_int_op(day,OP_EQ, 16516);
3807 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3808 tt_int_op(hour,OP_EQ, 9);
3809 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3810 tt_int_op(min,OP_EQ, 2);
3811 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3813 #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
3815 /* We can try INT32_MIN/MAX */
3816 /* Always ignore second(s) */
3818 /* INT32_MAX */
3819 format_time_interval(dbuf, sizeof(dbuf), 2147483647);
3820 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3821 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3822 &day, label_d, &hour, label_h, &min, label_m);
3823 tt_int_op(r,OP_EQ, 6);
3824 tt_int_op(day,OP_EQ, 24855);
3825 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3826 tt_int_op(hour,OP_EQ, 3);
3827 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3828 tt_int_op(min,OP_EQ, 14);
3829 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3830 /* and 7 seconds - ignored */
3832 /* INT32_MIN: check that we get the absolute value of interval,
3833 * which doesn't actually fit in int32_t.
3834 * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
3835 format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
3836 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3837 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3838 &day, label_d, &hour, label_h, &min, label_m);
3839 tt_int_op(r,OP_EQ, 6);
3840 tt_int_op(day,OP_EQ, 24855);
3841 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3842 tt_int_op(hour,OP_EQ, 3);
3843 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3844 tt_int_op(min,OP_EQ, 14);
3845 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3846 /* and 7 or 8 seconds - ignored */
3848 #endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */
3850 #if SIZEOF_LONG == 8
3852 /* We can try INT64_MIN/MAX */
3853 /* Always ignore second(s) */
3855 /* INT64_MAX */
3856 format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
3857 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3858 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3859 &day, label_d, &hour, label_h, &min, label_m);
3860 tt_int_op(r,OP_EQ, 6);
3861 tt_int_op(day,OP_EQ, 106751991167300L);
3862 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3863 tt_int_op(hour,OP_EQ, 15);
3864 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3865 tt_int_op(min,OP_EQ, 30);
3866 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3867 /* and 7 seconds - ignored */
3869 /* INT64_MIN: check that we get the absolute value of interval,
3870 * which doesn't actually fit in int64_t.
3871 * We expect INT64_MAX */
3872 format_time_interval(dbuf, sizeof(dbuf),
3873 -9223372036854775807L - 1L);
3874 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3875 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3876 &day, label_d, &hour, label_h, &min, label_m);
3877 tt_int_op(r,OP_EQ, 6);
3878 tt_int_op(day,OP_EQ, 106751991167300L);
3879 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3880 tt_int_op(hour,OP_EQ, 15);
3881 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3882 tt_int_op(min,OP_EQ, 30);
3883 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3884 /* and 7 or 8 seconds - ignored */
3886 #endif /* SIZEOF_LONG == 8 */
3888 done:
3892 #undef tt_char_op
3893 #undef tt_ci_char_op
3894 #undef DBUF_SIZE
3895 #undef T_
3896 #undef LABEL_SIZE
3897 #undef L_
3898 #undef TL_
3900 static void
3901 test_util_path_is_relative(void *arg)
3903 /* OS-independent tests */
3904 (void)arg;
3905 tt_int_op(1,OP_EQ, path_is_relative(""));
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"));
3909 tt_int_op(1,OP_EQ, path_is_relative("../dir"));
3911 tt_int_op(0,OP_EQ, path_is_relative("/"));
3912 tt_int_op(0,OP_EQ, path_is_relative("/dir"));
3913 tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
3915 /* Windows */
3916 #ifdef _WIN32
3917 /* I don't have Windows so I can't test this, hence the "#ifdef
3918 0". These are tests that look useful, so please try to get them
3919 running and uncomment if it all works as it should */
3920 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3921 tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
3922 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
3923 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
3924 tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
3926 tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
3927 tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
3928 tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
3929 #endif /* defined(_WIN32) */
3931 done:
3935 /** Run unittests for memory area allocator */
3936 static void
3937 test_util_memarea(void *arg)
3939 memarea_t *area = memarea_new();
3940 char *p1, *p2, *p3, *p1_orig;
3941 void *malloced_ptr = NULL;
3942 int i;
3944 #ifdef DISABLE_MEMORY_SENTINELS
3945 /* If memory sentinels are disabled, this whole module is just an alias for
3946 malloc(), which is free to lay out memory most any way it wants. */
3947 if (1)
3948 tt_skip();
3949 #endif /* defined(DISABLE_MEMORY_SENTINELS) */
3951 (void)arg;
3952 tt_assert(area);
3954 p1_orig = p1 = memarea_alloc(area,64);
3955 p2 = memarea_alloc_zero(area,52);
3956 p3 = memarea_alloc(area,11);
3958 tt_assert(memarea_owns_ptr(area, p1));
3959 tt_assert(memarea_owns_ptr(area, p2));
3960 tt_assert(memarea_owns_ptr(area, p3));
3961 /* Make sure we left enough space. */
3962 tt_assert(p1+64 <= p2);
3963 tt_assert(p2+52 <= p3);
3964 /* Make sure we aligned. */
3965 tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
3966 tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
3967 tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
3968 tt_assert(!memarea_owns_ptr(area, p3+8192));
3969 tt_assert(!memarea_owns_ptr(area, p3+30));
3970 tt_assert(fast_mem_is_zero(p2, 52));
3971 /* Make sure we don't overalign. */
3972 p1 = memarea_alloc(area, 1);
3973 p2 = memarea_alloc(area, 1);
3974 tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
3976 malloced_ptr = tor_malloc(64);
3977 tt_assert(!memarea_owns_ptr(area, malloced_ptr));
3978 tor_free(malloced_ptr);
3981 /* memarea_memdup */
3983 malloced_ptr = tor_malloc(64);
3984 crypto_rand((char*)malloced_ptr, 64);
3985 p1 = memarea_memdup(area, malloced_ptr, 64);
3986 tt_assert(p1 != malloced_ptr);
3987 tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
3988 tor_free(malloced_ptr);
3991 /* memarea_strdup. */
3992 p1 = memarea_strdup(area,"");
3993 p2 = memarea_strdup(area, "abcd");
3994 tt_assert(p1);
3995 tt_assert(p2);
3996 tt_str_op(p1,OP_EQ, "");
3997 tt_str_op(p2,OP_EQ, "abcd");
3999 /* memarea_strndup. */
4001 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
4002 /* (From Turandot, act 3.) */
4003 size_t len = strlen(s);
4004 p1 = memarea_strndup(area, s, 1000);
4005 p2 = memarea_strndup(area, s, 10);
4006 tt_str_op(p1,OP_EQ, s);
4007 tt_assert(p2 >= p1 + len + 1);
4008 tt_mem_op(s,OP_EQ, p2, 10);
4009 tt_int_op(p2[10],OP_EQ, '\0');
4010 p3 = memarea_strndup(area, s, len);
4011 tt_str_op(p3,OP_EQ, s);
4012 p3 = memarea_strndup(area, s, len-1);
4013 tt_mem_op(s,OP_EQ, p3, len-1);
4014 tt_int_op(p3[len-1],OP_EQ, '\0');
4017 memarea_clear(area);
4018 p1 = memarea_alloc(area, 1);
4019 tt_ptr_op(p1,OP_EQ, p1_orig);
4020 memarea_clear(area);
4021 size_t total = 0, initial_allocation, allocation2, dummy;
4022 memarea_get_stats(area, &initial_allocation, &dummy);
4024 /* Check for running over an area's size. */
4025 for (i = 0; i < 4096; ++i) {
4026 size_t n = crypto_rand_int(6);
4027 p1 = memarea_alloc(area, n);
4028 total += n;
4029 tt_assert(memarea_owns_ptr(area, p1));
4031 memarea_assert_ok(area);
4032 memarea_get_stats(area, &allocation2, &dummy);
4033 /* Make sure we can allocate a too-big object. */
4034 p1 = memarea_alloc_zero(area, 9000);
4035 p2 = memarea_alloc_zero(area, 16);
4036 total += 9000;
4037 total += 16;
4038 tt_assert(memarea_owns_ptr(area, p1));
4039 tt_assert(memarea_owns_ptr(area, p2));
4041 /* Now test stats... */
4042 size_t allocated = 0, used = 0;
4043 memarea_get_stats(area, &allocated, &used);
4044 tt_int_op(used, OP_LE, allocated);
4045 tt_int_op(used, OP_GE, total); /* not EQ, because of alignment and headers*/
4046 tt_int_op(allocated, OP_GT, allocation2);
4048 tt_int_op(allocation2, OP_GT, initial_allocation);
4050 memarea_clear(area);
4051 memarea_get_stats(area, &allocated, &used);
4052 tt_int_op(used, OP_LT, 128); /* Not 0, because of header */
4053 tt_int_op(allocated, OP_EQ, initial_allocation);
4055 done:
4056 memarea_drop_all(area);
4057 tor_free(malloced_ptr);
4060 /** Run unit tests for utility functions to get file names relative to
4061 * the data directory. */
4062 static void
4063 test_util_datadir(void *arg)
4065 char buf[1024];
4066 char *f = NULL;
4067 char *temp_dir = NULL;
4069 (void)arg;
4070 temp_dir = get_datadir_fname(NULL);
4071 f = get_datadir_fname("state");
4072 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
4073 tt_str_op(f,OP_EQ, buf);
4074 tor_free(f);
4075 f = get_datadir_fname2("cache", "thingy");
4076 tor_snprintf(buf, sizeof(buf),
4077 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
4078 tt_str_op(f,OP_EQ, buf);
4079 tor_free(f);
4080 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
4081 tor_snprintf(buf, sizeof(buf),
4082 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
4083 tt_str_op(f,OP_EQ, buf);
4084 tor_free(f);
4085 f = get_datadir_fname_suffix("cache", ".foo");
4086 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
4087 temp_dir);
4088 tt_str_op(f,OP_EQ, buf);
4090 done:
4091 tor_free(f);
4092 tor_free(temp_dir);
4095 static void
4096 test_util_strtok(void *arg)
4098 char buf[128];
4099 char buf2[128];
4100 int i;
4101 char *cp1, *cp2;
4103 (void)arg;
4104 for (i = 0; i < 3; i++) {
4105 const char *pad1="", *pad2="";
4106 switch (i) {
4107 case 0:
4108 break;
4109 case 1:
4110 pad1 = " ";
4111 pad2 = "!";
4112 break;
4113 case 2:
4114 pad1 = " ";
4115 pad2 = ";!";
4116 break;
4118 tor_snprintf(buf, sizeof(buf), "%s", pad1);
4119 tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
4120 tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL);
4121 tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL);
4123 tor_snprintf(buf, sizeof(buf),
4124 "%sGraved on the dark in gestures of descent%s", pad1, pad1);
4125 tor_snprintf(buf2, sizeof(buf2),
4126 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
4127 /* -- "Year's End", Richard Wilbur */
4129 tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4130 tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
4131 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
4132 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
4133 tt_str_op("on",OP_EQ, S1());
4134 tt_str_op("the",OP_EQ, S1());
4135 tt_str_op("dark",OP_EQ, S1());
4136 tt_str_op("seemed",OP_EQ, S2());
4137 tt_str_op("their",OP_EQ, S2());
4138 tt_str_op("own",OP_EQ, S2());
4139 tt_str_op("in",OP_EQ, S1());
4140 tt_str_op("gestures",OP_EQ, S1());
4141 tt_str_op("of",OP_EQ, S1());
4142 tt_str_op("most",OP_EQ, S2());
4143 tt_str_op("perfect",OP_EQ, S2());
4144 tt_str_op("descent",OP_EQ, S1());
4145 tt_str_op("monument",OP_EQ, S2());
4146 tt_ptr_op(NULL,OP_EQ, S1());
4147 tt_ptr_op(NULL,OP_EQ, S2());
4150 buf[0] = 0;
4151 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4152 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
4154 strlcpy(buf, "Howdy!", sizeof(buf));
4155 tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
4156 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
4158 strlcpy(buf, " ", sizeof(buf));
4159 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4160 strlcpy(buf, " ", sizeof(buf));
4161 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4163 strlcpy(buf, "something ", sizeof(buf));
4164 tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4165 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
4166 done:
4170 static void
4171 test_util_find_str_at_start_of_line(void *ptr)
4173 const char *long_string =
4174 "howdy world. how are you? i hope it's fine.\n"
4175 "hello kitty\n"
4176 "third line";
4177 char *line2 = strchr(long_string,'\n')+1;
4178 char *line3 = strchr(line2,'\n')+1;
4179 const char *short_string = "hello kitty\n"
4180 "second line\n";
4181 char *short_line2 = strchr(short_string,'\n')+1;
4183 (void)ptr;
4185 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
4186 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
4187 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
4188 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
4189 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
4190 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
4191 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
4192 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
4193 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
4194 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
4195 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
4196 tt_ptr_op(line2,OP_EQ,
4197 find_str_at_start_of_line(long_string, "hello kitty\n"));
4198 tt_ptr_op(line2,OP_EQ,
4199 find_str_at_start_of_line(long_string, "hello kitty\nt"));
4200 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
4201 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
4202 tt_ptr_op(NULL, OP_EQ,
4203 find_str_at_start_of_line(long_string, "third line\n"));
4204 tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
4205 "second line\n"));
4206 done:
4210 static void
4211 test_util_tor_strreplacechar(void *ptr)
4213 (void)ptr;
4214 char empty[] = "";
4215 char not_contain[] = "bbb";
4216 char contains[] = "bab";
4217 char contains_all[] = "aaa";
4219 tor_strreplacechar(empty, 'a', 'b');
4220 tt_str_op(empty, OP_EQ, "");
4222 tor_strreplacechar(not_contain, 'a', 'b');
4223 tt_str_op(not_contain, OP_EQ, "bbb");
4225 tor_strreplacechar(contains, 'a', 'b');
4226 tt_str_op(contains, OP_EQ, "bbb");
4228 tor_strreplacechar(contains_all, 'a', 'b');
4229 tt_str_op(contains_all, OP_EQ, "bbb");
4231 done:
4235 static void
4236 test_util_string_is_C_identifier(void *ptr)
4238 (void)ptr;
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("_string_is_C_identifier"));
4242 tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
4243 tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
4244 tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
4245 tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
4246 tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
4247 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4248 tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
4249 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4251 tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
4252 tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
4253 tt_int_op(0,OP_EQ, string_is_C_identifier(""));
4254 tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
4255 tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
4256 tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
4257 tt_int_op(0,OP_EQ, string_is_C_identifier("í"));
4258 tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
4260 done:
4264 static void
4265 test_util_string_is_utf8(void *ptr)
4267 (void)ptr;
4269 tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0));
4270 tt_int_op(1, OP_EQ, string_is_utf8("", 1));
4271 tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3));
4272 tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3));
4273 tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7));
4274 tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9));
4276 /* Test the utf8_no_bom function */
4277 tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFF", 3));
4278 tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFFFE", 3));
4279 tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFFlove", 7));
4280 tt_int_op(1, OP_EQ, string_is_utf8_no_bom("loveandrespect",
4281 strlen("loveandrespect")));
4283 // Validate exactly 'len' bytes.
4284 tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2));
4285 tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6));
4287 // Reject sequences with missing bytes.
4288 tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1));
4289 tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1));
4290 tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2));
4291 tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2));
4292 tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3));
4293 tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3));
4294 tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4));
4296 // Reject encodings that are overly long.
4297 tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2));
4298 tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2));
4299 tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3));
4300 tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3));
4301 tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4));
4302 tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4));
4304 // Reject UTF-16 surrogate halves.
4305 tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3));
4306 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3));
4307 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
4308 tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
4310 // The minimum legal codepoint, 0x00.
4311 tt_int_op(1, OP_EQ, string_is_utf8("\0", 1));
4313 // The maximum legal codepoint, 0x10FFFF.
4314 tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
4315 tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
4317 /* Test cases that vary between programming languages /
4318 * UTF-8 implementations.
4319 * Source: POC||GTFO 19, page 43
4320 * https://www.alchemistowl.org/pocorgtfo/
4323 // Invalid (in most implementations)
4324 // surrogate
4325 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x81", 3));
4326 // nullsurrog
4327 tt_int_op(0, OP_EQ, string_is_utf8("\x30\x00\xed\xa0\x81", 5));
4328 // threehigh
4329 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
4330 // fourhigh
4331 tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\xbf\xbf", 4));
4332 // fivebyte
4333 tt_int_op(0, OP_EQ, string_is_utf8("\xfb\x80\x80\x80\x80", 5));
4334 // sixbyte
4335 tt_int_op(0, OP_EQ, string_is_utf8("\xfd\x80\x80\x80\x80", 5));
4336 // sixhigh
4337 tt_int_op(0, OP_EQ, string_is_utf8("\xfd\xbf\xbf\xbf\xbf", 5));
4339 // Valid (in most implementations)
4340 // fourbyte
4341 tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x8d\x88", 4));
4342 // fourbyte2
4343 tt_int_op(1, OP_EQ, string_is_utf8("\xf0\xbf\xbf\xbf", 4));
4344 // nullbyte
4345 tt_int_op(1, OP_EQ, string_is_utf8("\x30\x31\x32\x00\x33", 5));
4347 done:
4351 static void
4352 test_util_asprintf(void *ptr)
4354 #define LOREMIPSUM \
4355 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
4356 char *cp=NULL, *cp2=NULL;
4357 int r;
4358 (void)ptr;
4360 /* simple string */
4361 r = tor_asprintf(&cp, "simple string 100%% safe");
4362 tt_assert(cp);
4363 tt_str_op("simple string 100% safe",OP_EQ, cp);
4364 tt_int_op(strlen(cp),OP_EQ, r);
4365 tor_free(cp);
4367 /* empty string */
4368 r = tor_asprintf(&cp, "%s", "");
4369 tt_assert(cp);
4370 tt_str_op("",OP_EQ, cp);
4371 tt_int_op(strlen(cp),OP_EQ, r);
4372 tor_free(cp);
4374 /* numbers (%i) */
4375 r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
4376 tt_assert(cp);
4377 tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
4378 tt_int_op(strlen(cp),OP_EQ, r);
4379 /* don't free cp; next test uses it. */
4381 /* numbers (%d) */
4382 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
4383 tt_assert(cp2);
4384 tt_int_op(strlen(cp2),OP_EQ, r);
4385 tt_str_op("First=101, Second=202",OP_EQ, cp2);
4386 tt_assert(cp != cp2);
4387 tor_free(cp);
4388 tor_free(cp2);
4390 /* Glass-box test: a string exactly 128 characters long. */
4391 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
4392 tt_assert(cp);
4393 tt_int_op(128,OP_EQ, r);
4394 tt_int_op(cp[128], OP_EQ, '\0');
4395 tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
4396 tor_free(cp);
4398 /* String longer than 128 characters */
4399 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
4400 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
4401 tt_assert(cp);
4402 tt_int_op(strlen(cp),OP_EQ, r);
4403 tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
4405 done:
4406 tor_free(cp);
4407 tor_free(cp2);
4410 static void
4411 test_util_listdir(void *ptr)
4413 smartlist_t *dir_contents = NULL;
4414 char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
4415 int r;
4416 (void)ptr;
4418 fname1 = tor_strdup(get_fname("hopscotch"));
4419 fname2 = tor_strdup(get_fname("mumblety-peg"));
4420 fname3 = tor_strdup(get_fname(".hidden-file"));
4421 dir1 = tor_strdup(get_fname("some-directory"));
4422 dirname = tor_strdup(get_fname(NULL));
4424 tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
4425 tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
4426 tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
4427 #ifdef _WIN32
4428 r = mkdir(dir1);
4429 #else
4430 r = mkdir(dir1, 0700);
4431 #endif
4432 if (r) {
4433 fprintf(stderr, "Can't create directory %s:", dir1);
4434 perror("");
4435 exit(1);
4438 dir_contents = tor_listdir(dirname);
4439 tt_assert(dir_contents);
4440 /* make sure that each filename is listed. */
4441 tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
4442 tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
4443 tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
4444 tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
4446 tt_assert(!smartlist_contains_string(dir_contents, "."));
4447 tt_assert(!smartlist_contains_string(dir_contents, ".."));
4449 done:
4450 tor_free(fname1);
4451 tor_free(fname2);
4452 tor_free(fname3);
4453 tor_free(dir1);
4454 tor_free(dirname);
4455 if (dir_contents) {
4456 SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
4457 smartlist_free(dir_contents);
4461 static void
4462 test_util_glob(void *ptr)
4464 (void)ptr;
4466 #ifdef HAVE_GLOB
4467 smartlist_t *results = NULL;
4468 int r, i;
4469 char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
4470 char *expected = NULL, *pattern = NULL;
4471 // used for cleanup
4472 char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
4473 char *forbidden_forbidden = NULL;
4475 dirname = tor_strdup(get_fname("test_glob"));
4476 tt_ptr_op(dirname, OP_NE, NULL);
4478 #ifdef _WIN32
4479 r = mkdir(dirname);
4480 #else
4481 r = mkdir(dirname, 0700);
4482 #endif
4483 if (r) {
4484 fprintf(stderr, "Can't create directory %s:", dirname);
4485 perror("");
4486 exit(1);
4489 tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
4490 tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
4491 tor_asprintf(&dir1_forbidden,
4492 "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
4493 tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
4494 tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
4495 tor_asprintf(&dir2_forbidden,
4496 "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
4497 tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
4498 tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
4499 tor_asprintf(&forbidden_forbidden,
4500 "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
4501 #ifndef _WIN32
4502 tt_int_op(0, OP_EQ, chmod(forbidden, 0700));
4503 #endif
4504 tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
4505 #ifndef _WIN32
4506 tt_int_op(0, OP_EQ, chmod(forbidden, 0));
4507 #endif
4509 #define TEST(input) \
4510 do { \
4511 tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
4512 results = tor_glob(pattern); \
4513 tor_free(pattern); \
4514 tt_assert(results); \
4515 smartlist_sort_strings(results); \
4516 } while (0);
4518 #define EXPECT(result) \
4519 do { \
4520 tt_int_op(smartlist_len(results), OP_EQ, \
4521 sizeof(result)/sizeof(*result)); \
4522 i = 0; \
4523 SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
4524 tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
4525 tt_str_op(f, OP_EQ, expected); \
4526 i++; \
4527 tor_free(expected); \
4528 } SMARTLIST_FOREACH_END(f); \
4529 SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4530 smartlist_free(results); \
4531 } while (0);
4533 #define EXPECT_EMPTY() \
4534 do { \
4535 tt_int_op(smartlist_len(results), OP_EQ, 0); \
4536 SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4537 smartlist_free(results); \
4538 } while (0);
4540 // wildcards at beginning
4541 const char *results_test1[] = {"dir2", "file2"};
4542 TEST("*2");
4543 EXPECT(results_test1);
4545 // wildcards at end
4546 const char *results_test2[] = {"dir1", "dir2"};
4547 TEST("d*");
4548 EXPECT(results_test2);
4550 // wildcards at beginning and end
4551 #ifdef _WIN32
4552 // dot files are not ignored on Windows
4553 const char *results_test3[] = {".test-hidden", "dir1", "dir2", "file1",
4554 "file2", "forbidden"};
4555 #else
4556 const char *results_test3[] = {"dir1", "dir2", "file1", "file2",
4557 "forbidden"};
4558 #endif /* defined(_WIN32) */
4559 TEST("*i*");
4560 EXPECT(results_test3);
4562 // wildcards in middle
4563 const char *results_test4[] = {"dir1", "dir2"};
4564 TEST("d?r*");
4565 EXPECT(results_test4);
4567 // test file that does not exist
4568 TEST("not-exist");
4569 EXPECT_EMPTY();
4571 // test wildcard that matches nothing
4572 TEST("*not-exist*");
4573 EXPECT_EMPTY();
4575 // test path separator at end - no wildcards
4576 const char *results_test7[] = {"dir1"};
4577 TEST("dir1");
4578 EXPECT(results_test7);
4580 const char *results_test8[] = {"dir1"};
4581 TEST("dir1"PATH_SEPARATOR);
4582 EXPECT(results_test8);
4584 const char *results_test9[] = {"file1"};
4585 TEST("file1");
4586 EXPECT(results_test9);
4588 TEST("file1"PATH_SEPARATOR);
4589 EXPECT_EMPTY();
4591 // test path separator at end - with wildcards and linux path separator
4592 const char *results_test11[] = {"dir1", "dir2", "forbidden"};
4593 TEST("*/");
4594 EXPECT(results_test11);
4596 #ifdef _WIN32
4597 // dot files are not ignored on Windows
4598 const char *results_test12[] = {".test-hidden", "dir1", "dir2", "empty",
4599 "file1", "file2", "forbidden"};
4600 #else
4601 const char *results_test12[] = {"dir1", "dir2", "empty", "file1", "file2",
4602 "forbidden"};
4603 #endif /* defined(_WIN32) */
4604 TEST("*");
4605 EXPECT(results_test12);
4607 // wildcards on folder and file and linux path separator
4608 const char *results_test13[] = {"dir1"PATH_SEPARATOR"dir1",
4609 "dir1"PATH_SEPARATOR"dir2",
4610 "dir1"PATH_SEPARATOR"file1",
4611 "dir1"PATH_SEPARATOR"file2",
4612 "dir2"PATH_SEPARATOR"dir1",
4613 "dir2"PATH_SEPARATOR"dir2",
4614 "dir2"PATH_SEPARATOR"file1",
4615 "dir2"PATH_SEPARATOR"file2"};
4616 TEST("?i*/?i*");
4617 EXPECT(results_test13);
4619 // wildcards on file only
4620 const char *results_test14[] = {"dir1"PATH_SEPARATOR"dir1",
4621 "dir1"PATH_SEPARATOR"dir2",
4622 "dir1"PATH_SEPARATOR"file1",
4623 "dir1"PATH_SEPARATOR"file2"};
4624 TEST("dir1"PATH_SEPARATOR"?i*");
4625 EXPECT(results_test14);
4627 // wildcards on folder only
4628 const char *results_test15[] = {"dir1"PATH_SEPARATOR"file1",
4629 "dir2"PATH_SEPARATOR"file1"};
4630 TEST("?i*"PATH_SEPARATOR"file1");
4631 EXPECT(results_test15);
4633 // wildcards after file name
4634 TEST("file1"PATH_SEPARATOR"*");
4635 EXPECT_EMPTY();
4637 #ifndef _WIN32
4638 // test wildcard escaping
4639 TEST("\\*");
4640 EXPECT_EMPTY();
4642 if (getuid() != 0) {
4643 // test forbidden directory, if we're not root.
4644 // (Root will be able to see this directory anyway.)
4645 tor_asprintf(&pattern, "%s"PATH_SEPARATOR"*"PATH_SEPARATOR"*", dirname);
4646 results = tor_glob(pattern);
4647 tor_free(pattern);
4648 tt_assert(!results);
4650 #endif /* !defined(_WIN32) */
4652 #undef TEST
4653 #undef EXPECT
4654 #undef EXPECT_EMPTY
4656 done:
4657 #ifndef _WIN32
4658 (void) chmod(forbidden, 0700);
4659 (void) chmod(dir1_forbidden, 0700);
4660 (void) chmod(dir2_forbidden, 0700);
4661 (void) chmod(forbidden_forbidden, 0700);
4662 #endif /* !defined(_WIN32) */
4663 tor_free(dir1);
4664 tor_free(dir2);
4665 tor_free(forbidden);
4666 tor_free(dirname);
4667 tor_free(dir1_forbidden);
4668 tor_free(dir2_forbidden);
4669 tor_free(forbidden_forbidden);
4670 tor_free(expected);
4671 tor_free(pattern);
4672 if (results) {
4673 SMARTLIST_FOREACH(results, char *, f, tor_free(f));
4674 smartlist_free(results);
4676 #else /* !defined(HAVE_GLOB) */
4677 tt_skip();
4678 done:
4679 return;
4680 #endif /* defined(HAVE_GLOB) */
4683 static void
4684 test_util_get_glob_opened_files(void *ptr)
4686 (void)ptr;
4688 #ifdef HAVE_GLOB
4689 smartlist_t *results = NULL;
4690 int r, i;
4691 char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
4692 char *expected = NULL, *pattern = NULL;
4693 // used for cleanup
4694 char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
4695 char *forbidden_forbidden = NULL;
4697 dirname = tor_strdup(get_fname("test_get_glob_opened_files"));
4698 tt_ptr_op(dirname, OP_NE, NULL);
4700 #ifdef _WIN32
4701 r = mkdir(dirname);
4702 #else
4703 r = mkdir(dirname, 0700);
4704 #endif
4705 if (r) {
4706 fprintf(stderr, "Can't create directory %s:", dirname);
4707 perror("");
4708 exit(1);
4711 tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
4712 tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
4713 tor_asprintf(&dir1_forbidden,
4714 "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
4715 tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
4716 tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
4717 tor_asprintf(&dir2_forbidden,
4718 "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
4719 tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
4720 tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
4721 tor_asprintf(&forbidden_forbidden,
4722 "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
4723 #ifndef _WIN32
4724 chmod(forbidden, 0700);
4725 #endif
4726 tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
4727 #ifndef _WIN32
4728 chmod(forbidden, 0);
4729 #endif
4731 #define TEST(input) \
4732 do { \
4733 if (*input) { \
4734 tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
4735 } else { /* do not add path separator if empty string */ \
4736 tor_asprintf(&pattern, "%s", dirname); \
4738 results = get_glob_opened_files(pattern); \
4739 tor_free(pattern); \
4740 tt_assert(results); \
4741 smartlist_sort_strings(results); \
4742 } while (0);
4744 #define EXPECT(result) \
4745 do { \
4746 tt_int_op(smartlist_len(results), OP_EQ, \
4747 sizeof(result)/sizeof(*result)); \
4748 i = 0; \
4749 SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
4750 if (*result[i]) { \
4751 tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
4752 } else { /* do not add path separator if empty string */ \
4753 tor_asprintf(&expected, "%s", dirname); \
4755 tt_str_op(f, OP_EQ, expected); \
4756 i++; \
4757 tor_free(expected); \
4758 } SMARTLIST_FOREACH_END(f); \
4759 SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4760 smartlist_free(results); \
4761 } while (0);
4763 #define EXPECT_EMPTY() \
4764 do { \
4765 tt_int_op(smartlist_len(results), OP_EQ, 0); \
4766 SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4767 smartlist_free(results); \
4768 } while (0);
4770 // all files on folder
4771 const char *results_test1[] = {""}; // only the folder is read
4772 TEST("*");
4773 EXPECT(results_test1);
4775 // same as before but ending in path separator
4776 const char *results_test2[] = {""}; // only the folder is read
4777 TEST("*"PATH_SEPARATOR);
4778 EXPECT(results_test2);
4780 // wildcards in multiple path components
4781 #ifndef _WIN32
4782 const char *results_test3[] = {"", "dir1", "dir2", "empty", "file1", "file2",
4783 "forbidden"};
4784 #else
4785 // dot files are not special on windows
4786 const char *results_test3[] = {"", ".test-hidden", "dir1", "dir2", "empty",
4787 "file1", "file2", "forbidden"};
4788 #endif /* !defined(_WIN32) */
4789 TEST("*"PATH_SEPARATOR"*");
4790 EXPECT(results_test3);
4792 // same as before but ending in path separator
4793 #ifndef _WIN32
4794 const char *results_test4[] = {"", "dir1", "dir2", "empty", "file1", "file2",
4795 "forbidden"};
4796 #else
4797 // dot files are not special on windows
4798 const char *results_test4[] = {"", ".test-hidden", "dir1", "dir2", "empty",
4799 "file1", "file2", "forbidden"};
4800 #endif /* !defined(_WIN32) */
4801 TEST("*"PATH_SEPARATOR"*"PATH_SEPARATOR);
4802 EXPECT(results_test4);
4804 // no glob - folder
4805 TEST("");
4806 EXPECT_EMPTY();
4808 // same as before but ending in path separator
4809 TEST(PATH_SEPARATOR);
4810 EXPECT_EMPTY();
4812 // no glob - file
4813 TEST("file1");
4814 EXPECT_EMPTY();
4816 // same as before but ending in path separator and linux path separator
4817 TEST("file1/");
4818 EXPECT_EMPTY();
4820 // file but with wildcard after
4821 const char *results_test9[] = {"file1"};
4822 TEST("file1"PATH_SEPARATOR"*");
4823 EXPECT(results_test9);
4825 // dir inside dir and linux path separator
4826 TEST("dir1/dir1");
4827 EXPECT_EMPTY();
4829 // same as before but ending in path separator
4830 TEST("dir1"PATH_SEPARATOR"dir1"PATH_SEPARATOR);
4831 EXPECT_EMPTY();
4833 // no glob - empty
4834 TEST("empty");
4835 EXPECT_EMPTY();
4837 // same as before but ending in path separator
4838 TEST("empty"PATH_SEPARATOR);
4839 EXPECT_EMPTY();
4841 // no glob - does not exist
4842 TEST("not_exist");
4843 EXPECT_EMPTY();
4845 #undef TEST
4846 #undef EXPECT
4847 #undef EXPECT_EMPTY
4849 done:
4850 #ifndef _WIN32
4852 int chmod_failed = 0;
4853 if (forbidden)
4854 chmod_failed |= chmod(forbidden, 0700);
4855 if (dir1_forbidden)
4856 chmod_failed |= chmod(dir1_forbidden, 0700);
4857 if (dir2_forbidden)
4858 chmod_failed |= chmod(dir2_forbidden, 0700);
4859 if (forbidden_forbidden)
4860 chmod_failed |= chmod(forbidden_forbidden, 0700);
4861 if (chmod_failed) {
4862 TT_FAIL(("unable to chmod a file on cleanup: %s", strerror(errno)));
4865 #endif /* !defined(_WIN32) */
4866 tor_free(dir1);
4867 tor_free(dir2);
4868 tor_free(forbidden);
4869 tor_free(dirname);
4870 tor_free(dir1_forbidden);
4871 tor_free(dir2_forbidden);
4872 tor_free(forbidden_forbidden);
4873 tor_free(expected);
4874 tor_free(pattern);
4875 if (results) {
4876 SMARTLIST_FOREACH(results, char *, f, tor_free(f));
4877 smartlist_free(results);
4879 #else /* !defined(HAVE_GLOB) */
4880 tt_skip();
4881 done:
4882 return;
4883 #endif /* defined(HAVE_GLOB) */
4886 static void
4887 test_util_parent_dir(void *ptr)
4889 char *cp;
4890 (void)ptr;
4892 #define T(output,expect_ok,input) \
4893 do { \
4894 int ok; \
4895 cp = tor_strdup(input); \
4896 ok = get_parent_directory(cp); \
4897 tt_int_op(expect_ok, OP_EQ, ok); \
4898 if (ok==0) \
4899 tt_str_op(output, OP_EQ, cp); \
4900 tor_free(cp); \
4901 } while (0);
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("./home/wombat", 0, "./home/wombat/knish/");
4907 T("/", 0, "/home");
4908 T("/", 0, "/home//");
4909 T(".", 0, "./wombat");
4910 T(".", 0, "./wombat/");
4911 T(".", 0, "./wombat//");
4912 T("wombat", 0, "wombat/foo");
4913 T("wombat/..", 0, "wombat/../foo");
4914 T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
4915 T("wombat/.", 0, "wombat/./foo");
4916 T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
4917 T("wombat", 0, "wombat/..//");
4918 T("wombat", 0, "wombat/foo/");
4919 T("wombat", 0, "wombat/.foo");
4920 T("wombat", 0, "wombat/.foo/");
4922 T("wombat", -1, "");
4923 T("w", -1, "");
4924 T("wombat", 0, "wombat/knish");
4926 T("/", 0, "/");
4927 T("/", 0, "////");
4929 done:
4930 tor_free(cp);
4933 static void
4934 test_util_ftruncate(void *ptr)
4936 char *buf = NULL;
4937 const char *fname;
4938 int fd = -1;
4939 const char *message = "Hello world";
4940 const char *message2 = "Hola mundo";
4941 struct stat st;
4943 (void) ptr;
4945 fname = get_fname("ftruncate");
4947 fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
4948 tt_int_op(fd, OP_GE, 0);
4950 /* Make the file be there. */
4951 tt_int_op(strlen(message), OP_EQ,
4952 write_all_to_fd(fd, message, strlen(message)));
4953 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
4954 tt_int_op(0, OP_EQ, fstat(fd, &st));
4955 tt_int_op((int)st.st_size, OP_EQ, strlen(message));
4957 /* Truncate and see if it got truncated */
4958 tt_int_op(0, OP_EQ, tor_ftruncate(fd));
4959 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
4960 tt_int_op(0, OP_EQ, fstat(fd, &st));
4961 tt_int_op((int)st.st_size, OP_EQ, 0);
4963 /* Replace, and see if it got replaced */
4964 tt_int_op(strlen(message2), OP_EQ,
4965 write_all_to_fd(fd, message2, strlen(message2)));
4966 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
4967 tt_int_op(0, OP_EQ, fstat(fd, &st));
4968 tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
4970 close(fd);
4971 fd = -1;
4973 buf = read_file_to_str(fname, 0, NULL);
4974 tt_str_op(message2, OP_EQ, buf);
4976 done:
4977 if (fd >= 0)
4978 close(fd);
4979 tor_free(buf);
4982 static void
4983 test_util_num_cpus(void *arg)
4985 (void)arg;
4986 int num = compute_num_cpus();
4987 if (num < 0)
4988 tt_skip();
4990 tt_int_op(num, OP_GE, 1);
4991 tt_int_op(num, OP_LE, 16);
4993 done:
4997 #ifdef _WIN32
4998 static void
4999 test_util_load_win_lib(void *ptr)
5001 HANDLE h = load_windows_system_library(_T("advapi32.dll"));
5002 (void) ptr;
5004 tt_assert(h);
5005 done:
5006 if (h)
5007 FreeLibrary(h);
5009 #endif /* defined(_WIN32) */
5012 * Test for format_hex_number_sigsafe()
5015 static void
5016 test_util_format_hex_number(void *ptr)
5018 int i, len;
5019 char buf[33];
5020 const struct {
5021 const char *str;
5022 unsigned int x;
5023 } test_data[] = {
5024 {"0", 0},
5025 {"1", 1},
5026 {"273A", 0x273a},
5027 {"FFFF", 0xffff},
5028 {"7FFFFFFF", 0x7fffffff},
5029 {"FFFFFFFF", 0xffffffff},
5030 #if UINT_MAX >= 0xffffffff
5031 {"31BC421D", 0x31bc421d},
5032 {"FFFFFFFF", 0xffffffff},
5033 #endif
5034 {NULL, 0}
5037 (void)ptr;
5039 for (i = 0; test_data[i].str != NULL; ++i) {
5040 len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
5041 tt_int_op(len,OP_NE, 0);
5042 tt_int_op(len,OP_EQ, strlen(buf));
5043 tt_str_op(buf,OP_EQ, test_data[i].str);
5046 tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
5047 tt_str_op(buf,OP_EQ, "FFFF");
5048 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
5049 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
5051 done:
5052 return;
5056 * Test for format_hex_number_sigsafe()
5059 static void
5060 test_util_format_dec_number(void *ptr)
5062 int i, len;
5063 char buf[33];
5064 const struct {
5065 const char *str;
5066 unsigned int x;
5067 } test_data[] = {
5068 {"0", 0},
5069 {"1", 1},
5070 {"1234", 1234},
5071 {"12345678", 12345678},
5072 {"99999999", 99999999},
5073 {"100000000", 100000000},
5074 {"4294967295", 4294967295u},
5075 #if UINT_MAX > 0xffffffff
5076 {"18446744073709551615", 18446744073709551615u },
5077 #endif
5078 {NULL, 0}
5081 (void)ptr;
5083 for (i = 0; test_data[i].str != NULL; ++i) {
5084 len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
5085 tt_int_op(len,OP_NE, 0);
5086 tt_int_op(len,OP_EQ, strlen(buf));
5087 tt_str_op(buf,OP_EQ, test_data[i].str);
5089 len = format_dec_number_sigsafe(test_data[i].x, buf,
5090 (int)(strlen(test_data[i].str) + 1));
5091 tt_int_op(len,OP_EQ, strlen(buf));
5092 tt_str_op(buf,OP_EQ, test_data[i].str);
5095 tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
5096 tt_str_op(buf,OP_EQ, "7331");
5097 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
5098 tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
5099 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
5101 done:
5102 return;
5105 #define MAX_SPLIT_LINE_COUNT 4
5106 struct split_lines_test_t {
5107 const char *orig_line; // Line to be split (may contain \0's)
5108 int orig_length; // Length of orig_line
5109 const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
5112 static void
5113 test_util_di_ops(void *arg)
5115 #define LT -1
5116 #define GT 1
5117 #define EQ 0
5118 const struct {
5119 const char *a; int want_sign; const char *b;
5120 } examples[] = {
5121 { "Foo", EQ, "Foo" },
5122 { "foo", GT, "bar", },
5123 { "foobar", EQ ,"foobar" },
5124 { "foobar", LT, "foobaw" },
5125 { "foobar", GT, "f00bar" },
5126 { "foobar", GT, "boobar" },
5127 { "", EQ, "" },
5128 { NULL, 0, NULL },
5131 int i;
5133 (void)arg;
5134 for (i = 0; examples[i].a; ++i) {
5135 size_t len = strlen(examples[i].a);
5136 int eq1, eq2, neq1, neq2, cmp1, cmp2;
5137 tt_int_op(len,OP_EQ, strlen(examples[i].b));
5138 /* We do all of the operations, with operands in both orders. */
5139 eq1 = tor_memeq(examples[i].a, examples[i].b, len);
5140 eq2 = tor_memeq(examples[i].b, examples[i].a, len);
5141 neq1 = tor_memneq(examples[i].a, examples[i].b, len);
5142 neq2 = tor_memneq(examples[i].b, examples[i].a, len);
5143 cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
5144 cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
5146 /* Check for correctness of cmp1 */
5147 if (cmp1 < 0 && examples[i].want_sign != LT)
5148 TT_DIE(("Assertion failed."));
5149 else if (cmp1 > 0 && examples[i].want_sign != GT)
5150 TT_DIE(("Assertion failed."));
5151 else if (cmp1 == 0 && examples[i].want_sign != EQ)
5152 TT_DIE(("Assertion failed."));
5154 /* Check for consistency of everything else with cmp1 */
5155 tt_int_op(eq1,OP_EQ, eq2);
5156 tt_int_op(neq1,OP_EQ, neq2);
5157 tt_int_op(cmp1,OP_EQ, -cmp2);
5158 tt_int_op(eq1,OP_EQ, cmp1 == 0);
5159 tt_int_op(neq1,OP_EQ, !eq1);
5163 uint8_t zz = 0;
5164 uint8_t ii = 0;
5165 int z;
5167 /* exhaustively test tor_memeq and tor_memcmp
5168 * against each possible single-byte numeric difference
5169 * some arithmetic bugs only appear with certain bit patterns */
5170 for (z = 0; z < 256; z++) {
5171 for (i = 0; i < 256; i++) {
5172 ii = (uint8_t)i;
5173 zz = (uint8_t)z;
5174 tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
5175 tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
5176 zz > ii ? GT : EQ);
5177 tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
5178 ii < zz ? LT : EQ);
5183 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
5184 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
5185 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
5186 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
5187 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
5188 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
5189 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
5190 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
5191 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
5193 done:
5197 static void
5198 test_util_memcpy_iftrue_timei(void *arg)
5200 (void)arg;
5201 char buf1[25];
5202 char buf2[25];
5203 char buf3[25];
5205 for (int i = 0; i < 100; ++i) {
5206 crypto_rand(buf1, sizeof(buf1));
5207 crypto_rand(buf2, sizeof(buf2));
5208 memcpy(buf3, buf1, sizeof(buf1));
5210 /* We just copied buf1 into buf3. Now we're going to copy buf2 into buf2,
5211 iff our coin flip comes up heads. */
5212 bool coinflip = crypto_rand_int(2) == 0;
5214 memcpy_if_true_timei(coinflip, buf3, buf2, sizeof(buf3));
5216 if (coinflip) {
5217 tt_mem_op(buf3, OP_EQ, buf2, sizeof(buf2));
5218 } else {
5219 tt_mem_op(buf3, OP_EQ, buf1, sizeof(buf1));
5222 done:
5226 static void
5227 test_util_di_map(void *arg)
5229 (void)arg;
5230 di_digest256_map_t *dimap = NULL;
5231 uint8_t key1[] = "Robert Anton Wilson ";
5232 uint8_t key2[] = "Martin Gardner, _Fads&fallacies";
5233 uint8_t key3[] = "Tom Lehrer, _Be Prepared_. ";
5234 uint8_t key4[] = "Ursula Le Guin,_A Wizard of... ";
5236 char dflt_entry[] = "'You have made a good beginning', but no more";
5238 tt_int_op(32, OP_EQ, sizeof(key1));
5239 tt_int_op(32, OP_EQ, sizeof(key2));
5240 tt_int_op(32, OP_EQ, sizeof(key3));
5242 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry));
5244 char *str1 = tor_strdup("You are precisely as big as what you love"
5245 " and precisely as small as what you allow"
5246 " to annoy you.");
5247 char *str2 = tor_strdup("Let us hope that Lysenko's success in Russia will"
5248 " serve for many generations to come as another"
5249 " reminder to the world of how quickly and easily"
5250 " a science can be corrupted when ignorant"
5251 " political leaders deem themselves competent"
5252 " to arbitrate scientific disputes");
5253 char *str3 = tor_strdup("Don't write naughty words on walls "
5254 "if you can't spell.");
5256 dimap_add_entry(&dimap, key1, str1);
5257 dimap_add_entry(&dimap, key2, str2);
5258 dimap_add_entry(&dimap, key3, str3);
5260 tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry));
5261 tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry));
5262 tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry));
5263 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry));
5265 done:
5266 dimap_free(dimap, tor_free_);
5270 * Test counting high bits
5272 static void
5273 test_util_n_bits_set(void *ptr)
5275 (void)ptr;
5276 tt_int_op(0,OP_EQ, n_bits_set_u8(0));
5277 tt_int_op(1,OP_EQ, n_bits_set_u8(1));
5278 tt_int_op(3,OP_EQ, n_bits_set_u8(7));
5279 tt_int_op(1,OP_EQ, n_bits_set_u8(8));
5280 tt_int_op(2,OP_EQ, n_bits_set_u8(129));
5281 tt_int_op(8,OP_EQ, n_bits_set_u8(255));
5282 done:
5287 * Test LHS whitespace (and comment) eater
5289 static void
5290 test_util_eat_whitespace(void *ptr)
5292 const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
5293 char str[80];
5294 size_t i;
5296 (void)ptr;
5298 /* Try one leading ws */
5299 strlcpy(str, "fuubaar", sizeof(str));
5300 for (i = 0; i < sizeof(ws); ++i) {
5301 str[0] = ws[i];
5302 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
5303 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5304 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
5305 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5307 str[0] = '\n';
5308 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
5309 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5310 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5311 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5313 /* Empty string */
5314 strlcpy(str, "", sizeof(str));
5315 tt_ptr_op(str,OP_EQ, eat_whitespace(str));
5316 tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
5317 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5318 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
5320 /* Only ws */
5321 strlcpy(str, " \t\r\n", sizeof(str));
5322 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5323 tt_ptr_op(str + strlen(str),OP_EQ,
5324 eat_whitespace_eos(str, str + strlen(str)));
5325 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
5326 eat_whitespace_no_nl(str));
5327 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
5328 eat_whitespace_eos_no_nl(str, str + strlen(str)));
5330 strlcpy(str, " \t\r ", sizeof(str));
5331 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5332 tt_ptr_op(str + strlen(str),OP_EQ,
5333 eat_whitespace_eos(str, str + strlen(str)));
5334 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
5335 tt_ptr_op(str + strlen(str),OP_EQ,
5336 eat_whitespace_eos_no_nl(str, str + strlen(str)));
5338 /* Multiple ws */
5339 strlcpy(str, "fuubaar", sizeof(str));
5340 for (i = 0; i < sizeof(ws); ++i)
5341 str[i] = ws[i];
5342 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
5343 tt_ptr_op(str + sizeof(ws),OP_EQ,
5344 eat_whitespace_eos(str, str + strlen(str)));
5345 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
5346 tt_ptr_op(str + sizeof(ws),OP_EQ,
5347 eat_whitespace_eos_no_nl(str, str + strlen(str)));
5349 /* Eat comment */
5350 strlcpy(str, "# Comment \n No Comment", sizeof(str));
5351 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
5352 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5353 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5354 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5356 /* Eat comment & ws mix */
5357 strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
5358 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
5359 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5360 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
5361 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5363 /* Eat entire comment */
5364 strlcpy(str, "#Comment", sizeof(str));
5365 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5366 tt_ptr_op(str + strlen(str),OP_EQ,
5367 eat_whitespace_eos(str, str + strlen(str)));
5368 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5369 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5371 /* Blank line, then comment */
5372 strlcpy(str, " \t\n # Comment", sizeof(str));
5373 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5374 tt_ptr_op(str + strlen(str),OP_EQ,
5375 eat_whitespace_eos(str, str + strlen(str)));
5376 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
5377 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5379 done:
5383 /** Return a newly allocated smartlist containing the lines of text in
5384 * <b>lines</b>. The returned strings are heap-allocated, and must be
5385 * freed by the caller.
5387 * XXXX? Move to container.[hc] ? */
5388 static smartlist_t *
5389 smartlist_new_from_text_lines(const char *lines)
5391 smartlist_t *sl = smartlist_new();
5392 char *last_line;
5394 smartlist_split_string(sl, lines, "\n", 0, 0);
5396 last_line = smartlist_pop_last(sl);
5397 if (last_line != NULL && *last_line != '\0') {
5398 smartlist_add(sl, last_line);
5399 } else {
5400 tor_free(last_line);
5403 return sl;
5406 /** Test smartlist_new_from_text_lines */
5407 static void
5408 test_util_sl_new_from_text_lines(void *ptr)
5410 (void)ptr;
5412 { /* Normal usage */
5413 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
5414 int sl_len = smartlist_len(sl);
5416 tt_want_int_op(sl_len, OP_EQ, 3);
5418 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5419 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
5420 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
5422 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5423 smartlist_free(sl);
5426 { /* No final newline */
5427 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
5428 int sl_len = smartlist_len(sl);
5430 tt_want_int_op(sl_len, OP_EQ, 3);
5432 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5433 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
5434 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
5436 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5437 smartlist_free(sl);
5440 { /* No newlines */
5441 smartlist_t *sl = smartlist_new_from_text_lines("foo");
5442 int sl_len = smartlist_len(sl);
5444 tt_want_int_op(sl_len, OP_EQ, 1);
5446 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5448 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5449 smartlist_free(sl);
5452 { /* No text at all */
5453 smartlist_t *sl = smartlist_new_from_text_lines("");
5454 int sl_len = smartlist_len(sl);
5456 tt_want_int_op(sl_len, OP_EQ, 0);
5458 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5459 smartlist_free(sl);
5463 static void
5464 test_util_envnames(void *ptr)
5466 (void) ptr;
5468 tt_assert(environment_variable_names_equal("abc", "abc"));
5469 tt_assert(environment_variable_names_equal("abc", "abc="));
5470 tt_assert(environment_variable_names_equal("abc", "abc=def"));
5471 tt_assert(environment_variable_names_equal("abc=def", "abc"));
5472 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
5474 tt_assert(environment_variable_names_equal("abc", "abc"));
5475 tt_assert(environment_variable_names_equal("abc", "abc="));
5476 tt_assert(environment_variable_names_equal("abc", "abc=def"));
5477 tt_assert(environment_variable_names_equal("abc=def", "abc"));
5478 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
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=", "abcd"));
5483 tt_assert(!environment_variable_names_equal("abc=", "def"));
5484 tt_assert(!environment_variable_names_equal("abc=", "def="));
5485 tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
5487 tt_assert(!environment_variable_names_equal("", "a=def"));
5488 /* A bit surprising. */
5489 tt_assert(environment_variable_names_equal("", "=def"));
5490 tt_assert(environment_variable_names_equal("=y", "=x"));
5492 done:
5496 /** Test process_environment_make */
5497 static void
5498 test_util_make_environment(void *ptr)
5500 const char *env_vars_string =
5501 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5502 "HOME=/home/foozer\n";
5503 const char expected_windows_env_block[] =
5504 "HOME=/home/foozer\000"
5505 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
5506 "\000";
5507 size_t expected_windows_env_block_len =
5508 sizeof(expected_windows_env_block) - 1;
5510 smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
5511 smartlist_t *env_vars_sorted = smartlist_new();
5512 smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
5514 process_environment_t *env;
5516 (void)ptr;
5518 env = process_environment_make(env_vars);
5520 /* Check that the Windows environment block is correct. */
5521 tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
5522 expected_windows_env_block_len));
5524 /* Now for the Unixoid environment block. We don't care which order
5525 * these environment variables are in, so we sort both lists first. */
5527 smartlist_add_all(env_vars_sorted, env_vars);
5530 char **v;
5531 for (v = env->unixoid_environment_block; *v; ++v) {
5532 smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
5536 smartlist_sort_strings(env_vars_sorted);
5537 smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
5539 tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
5540 smartlist_len(env_vars_in_unixoid_env_block_sorted));
5542 int len = smartlist_len(env_vars_sorted);
5543 int i;
5545 if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
5546 len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
5549 for (i = 0; i < len; ++i) {
5550 tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
5551 smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
5555 /* Clean up. */
5556 smartlist_free(env_vars_in_unixoid_env_block_sorted);
5557 smartlist_free(env_vars_sorted);
5559 SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
5560 smartlist_free(env_vars);
5562 process_environment_free(env);
5565 /** Test set_environment_variable_in_smartlist */
5566 static void
5567 test_util_set_env_var_in_sl(void *ptr)
5569 /* The environment variables in these strings are in arbitrary
5570 * order; we sort the resulting lists before comparing them.
5572 * (They *will not* end up in the order shown in
5573 * expected_resulting_env_vars_string.) */
5575 const char *base_env_vars_string =
5576 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5577 "HOME=/home/foozer\n"
5578 "TERM=xterm\n"
5579 "SHELL=/bin/ksh\n"
5580 "USER=foozer\n"
5581 "LOGNAME=foozer\n"
5582 "USERNAME=foozer\n"
5583 "LANG=en_US.utf8\n"
5586 const char *new_env_vars_string =
5587 "TERM=putty\n"
5588 "DISPLAY=:18.0\n"
5591 const char *expected_resulting_env_vars_string =
5592 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5593 "HOME=/home/foozer\n"
5594 "TERM=putty\n"
5595 "SHELL=/bin/ksh\n"
5596 "USER=foozer\n"
5597 "LOGNAME=foozer\n"
5598 "USERNAME=foozer\n"
5599 "LANG=en_US.utf8\n"
5600 "DISPLAY=:18.0\n"
5603 smartlist_t *merged_env_vars =
5604 smartlist_new_from_text_lines(base_env_vars_string);
5605 smartlist_t *new_env_vars =
5606 smartlist_new_from_text_lines(new_env_vars_string);
5607 smartlist_t *expected_resulting_env_vars =
5608 smartlist_new_from_text_lines(expected_resulting_env_vars_string);
5610 /* Elements of merged_env_vars are heap-allocated, and must be
5611 * freed. Some of them are (or should) be freed by
5612 * set_environment_variable_in_smartlist.
5614 * Elements of new_env_vars are heap-allocated, but are copied into
5615 * merged_env_vars, so they are not freed separately at the end of
5616 * the function.
5618 * Elements of expected_resulting_env_vars are heap-allocated, and
5619 * must be freed. */
5621 (void)ptr;
5623 SMARTLIST_FOREACH(new_env_vars, char *, env_var,
5624 set_environment_variable_in_smartlist(merged_env_vars,
5625 env_var,
5626 tor_free_,
5627 1));
5629 smartlist_sort_strings(merged_env_vars);
5630 smartlist_sort_strings(expected_resulting_env_vars);
5632 tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
5633 smartlist_len(expected_resulting_env_vars));
5635 int len = smartlist_len(merged_env_vars);
5636 int i;
5638 if (smartlist_len(expected_resulting_env_vars) < len) {
5639 len = smartlist_len(expected_resulting_env_vars);
5642 for (i = 0; i < len; ++i) {
5643 tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
5644 smartlist_get(expected_resulting_env_vars, i));
5648 /* Clean up. */
5649 SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
5650 smartlist_free(merged_env_vars);
5652 smartlist_free(new_env_vars);
5654 SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
5655 smartlist_free(expected_resulting_env_vars);
5658 static void
5659 test_util_weak_random(void *arg)
5661 int i, j, n[16];
5662 tor_weak_rng_t rng;
5663 (void) arg;
5665 tor_init_weak_random(&rng, (unsigned)time(NULL));
5667 for (i = 1; i <= 256; ++i) {
5668 for (j=0;j<100;++j) {
5669 int r = tor_weak_random_range(&rng, i);
5670 tt_int_op(0, OP_LE, r);
5671 tt_int_op(r, OP_LT, i);
5675 memset(n,0,sizeof(n));
5676 for (j=0;j<8192;++j) {
5677 n[tor_weak_random_range(&rng, 16)]++;
5680 for (i=0;i<16;++i)
5681 tt_int_op(n[i], OP_GT, 0);
5682 done:
5686 static void
5687 test_util_mathlog(void *arg)
5689 double d;
5690 (void) arg;
5692 d = tor_mathlog(2.718281828);
5693 tt_double_op(fabs(d - 1.0), OP_LT, .000001);
5694 d = tor_mathlog(10);
5695 tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
5696 done:
5700 static void
5701 test_util_fraction(void *arg)
5703 uint64_t a,b;
5704 (void)arg;
5706 a = 99; b = 30;
5707 simplify_fraction64(&a,&b);
5708 tt_u64_op(a, OP_EQ, 33);
5709 tt_u64_op(b, OP_EQ, 10);
5711 a = 3000000; b = 10000000;
5712 simplify_fraction64(&a,&b);
5713 tt_u64_op(a, OP_EQ, 3);
5714 tt_u64_op(b, OP_EQ, 10);
5716 a = 0; b = 15;
5717 simplify_fraction64(&a,&b);
5718 tt_u64_op(a, OP_EQ, 0);
5719 tt_u64_op(b, OP_EQ, 1);
5721 done:
5725 static void
5726 test_util_round_to_next_multiple_of(void *arg)
5728 (void)arg;
5730 tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0);
5731 tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0);
5733 tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99);
5734 tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105);
5735 tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99);
5737 tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ,
5738 UINT64_MAX);
5740 tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0);
5741 tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0);
5743 tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99);
5744 tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105);
5745 tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99);
5747 tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ,
5748 UINT32_MAX);
5750 tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0);
5751 tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0);
5753 tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99);
5754 tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105);
5755 tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99);
5757 tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ,
5758 UINT_MAX);
5759 done:
5763 static void
5764 test_util_laplace(void *arg)
5766 /* Sample values produced using Python's SciPy:
5768 * >>> from scipy.stats import laplace
5769 * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
5770 ... loc = 24, scale = 24)
5771 * array([ nan, -inf, -69.88855213, 24. ,
5772 * 24.48486498, 117.88855213, inf, nan])
5774 const double mu = 24.0, b = 24.0;
5775 const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
5776 (void)arg;
5778 tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0));
5779 tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01));
5780 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5));
5781 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51));
5782 tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99));
5784 /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
5785 * ... loc = 0, scale = 50)
5786 * array([ -inf, -80.47189562, -34.65735903, 0. ,
5787 * 34.65735903, 80.47189562, 195.60115027])
5789 tt_i64_op(INT64_MIN + 20, OP_EQ,
5790 add_laplace_noise(20, 0.0, delta_f, epsilon));
5792 tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon));
5793 tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon));
5794 tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon));
5795 tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon));
5796 tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon));
5797 tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon));
5799 /* Test extreme values of signal with maximally negative values of noise
5800 * 1.0000000000000002 is the smallest number > 1
5801 * 0.0000000000000002 is the double epsilon (error when calculating near 1)
5802 * this is approximately 1/(2^52)
5803 * per https://en.wikipedia.org/wiki/Double_precision
5804 * (let's not descend into the world of subnormals)
5805 * >>> laplace.ppf([0, 0.0000000000000002], loc = 0, scale = 1)
5806 * array([ -inf, -35.45506713])
5808 const double noscale_df = 1.0, noscale_eps = 1.0;
5810 tt_i64_op(INT64_MIN, OP_EQ,
5811 add_laplace_noise(0, 0.0, noscale_df, noscale_eps));
5813 /* is it clipped to INT64_MIN? */
5814 tt_i64_op(INT64_MIN, OP_EQ,
5815 add_laplace_noise(-1, 0.0, noscale_df, noscale_eps));
5816 tt_i64_op(INT64_MIN, OP_EQ,
5817 add_laplace_noise(INT64_MIN, 0.0,
5818 noscale_df, noscale_eps));
5819 /* ... even when scaled? */
5820 tt_i64_op(INT64_MIN, OP_EQ,
5821 add_laplace_noise(0, 0.0, delta_f, epsilon));
5822 tt_i64_op(INT64_MIN, OP_EQ,
5823 add_laplace_noise(0, 0.0,
5824 DBL_MAX, 1));
5825 tt_i64_op(INT64_MIN, OP_EQ,
5826 add_laplace_noise(INT64_MIN, 0.0,
5827 DBL_MAX, 1));
5829 /* does it play nice with INT64_MAX? */
5830 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5831 add_laplace_noise(INT64_MAX, 0.0,
5832 noscale_df, noscale_eps));
5834 /* do near-zero fractional values work? */
5835 const double min_dbl_error = 0.0000000000000002;
5837 tt_i64_op(-35, OP_EQ,
5838 add_laplace_noise(0, min_dbl_error,
5839 noscale_df, noscale_eps));
5840 tt_i64_op(INT64_MIN, OP_EQ,
5841 add_laplace_noise(INT64_MIN, min_dbl_error,
5842 noscale_df, noscale_eps));
5843 tt_i64_op((-35 + INT64_MAX), OP_EQ,
5844 add_laplace_noise(INT64_MAX, min_dbl_error,
5845 noscale_df, noscale_eps));
5846 tt_i64_op(INT64_MIN, OP_EQ,
5847 add_laplace_noise(0, min_dbl_error,
5848 DBL_MAX, 1));
5849 tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ,
5850 add_laplace_noise(INT64_MAX, min_dbl_error,
5851 DBL_MAX, 1));
5852 tt_i64_op(INT64_MIN, OP_EQ,
5853 add_laplace_noise(INT64_MIN, min_dbl_error,
5854 DBL_MAX, 1));
5856 /* does it play nice with INT64_MAX? */
5857 tt_i64_op((INT64_MAX - 35), OP_EQ,
5858 add_laplace_noise(INT64_MAX, min_dbl_error,
5859 noscale_df, noscale_eps));
5861 /* Test extreme values of signal with maximally positive values of noise
5862 * 1.0000000000000002 is the smallest number > 1
5863 * 0.9999999999999998 is the greatest number < 1 by calculation
5864 * per https://en.wikipedia.org/wiki/Double_precision
5865 * >>> laplace.ppf([1.0, 0.9999999999999998], loc = 0, scale = 1)
5866 * array([inf, 35.35050621])
5867 * but the function rejects p == 1.0, so we just use max_dbl_lt_one
5869 const double max_dbl_lt_one = 0.9999999999999998;
5871 /* do near-one fractional values work? */
5872 tt_i64_op(35, OP_EQ,
5873 add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps));
5875 /* is it clipped to INT64_MAX? */
5876 tt_i64_op(INT64_MAX, OP_EQ,
5877 add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one,
5878 noscale_df, noscale_eps));
5879 tt_i64_op(INT64_MAX, OP_EQ,
5880 add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one,
5881 noscale_df, noscale_eps));
5882 tt_i64_op(INT64_MAX, OP_EQ,
5883 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5884 noscale_df, noscale_eps));
5885 /* ... even when scaled? */
5886 tt_i64_op(INT64_MAX, OP_EQ,
5887 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5888 delta_f, epsilon));
5889 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5890 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5891 DBL_MAX, 1));
5892 tt_i64_op(INT64_MAX, OP_EQ,
5893 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5894 DBL_MAX, 1));
5895 /* does it play nice with INT64_MIN? */
5896 tt_i64_op((INT64_MIN + 35), OP_EQ,
5897 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5898 noscale_df, noscale_eps));
5900 done:
5904 static void
5905 test_util_clamp_double_to_int64(void *arg)
5907 (void)arg;
5909 tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL));
5910 tt_i64_op(INT64_MIN, OP_EQ,
5911 clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0));
5912 tt_i64_op(INT64_MIN, OP_EQ,
5913 clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0));
5914 tt_i64_op(((uint64_t) -1) << 53, OP_EQ,
5915 clamp_double_to_int64(-1.0 * pow(2.0, 53.0)));
5916 tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ,
5917 clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0));
5918 tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0));
5919 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9));
5920 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1));
5921 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0));
5922 tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL));
5923 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1));
5924 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9));
5925 tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0));
5926 tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ,
5927 clamp_double_to_int64(pow(2.0, 53.0) - 1.0));
5928 tt_i64_op(((int64_t) 1) << 53, OP_EQ,
5929 clamp_double_to_int64(pow(2.0, 53.0)));
5930 tt_i64_op(INT64_MAX, OP_EQ,
5931 clamp_double_to_int64(pow(2.0, 63.0)));
5932 tt_i64_op(INT64_MAX, OP_EQ,
5933 clamp_double_to_int64(pow(2.0, 64.0)));
5934 tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL));
5936 done:
5940 #ifdef FD_CLOEXEC
5941 #define CAN_CHECK_CLOEXEC
5942 static int
5943 fd_is_cloexec(tor_socket_t fd)
5945 int flags = fcntl(fd, F_GETFD, 0);
5946 return (flags & FD_CLOEXEC) != 0;
5948 #endif /* defined(FD_CLOEXEC) */
5950 #ifndef _WIN32
5951 #define CAN_CHECK_NONBLOCK
5952 static int
5953 fd_is_nonblocking(tor_socket_t fd)
5955 int flags = fcntl(fd, F_GETFL, 0);
5956 return (flags & O_NONBLOCK) != 0;
5958 #endif /* !defined(_WIN32) */
5960 #define ERRNO_IS_EPROTO(e) (e == SOCK_ERRNO(EPROTONOSUPPORT))
5961 #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
5963 /* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
5964 static void
5965 test_util_socket(void *arg)
5967 const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
5968 tor_socket_t fd1 = TOR_INVALID_SOCKET;
5969 tor_socket_t fd2 = TOR_INVALID_SOCKET;
5970 tor_socket_t fd3 = TOR_INVALID_SOCKET;
5971 tor_socket_t fd4 = TOR_INVALID_SOCKET;
5972 int n = get_n_open_sockets();
5974 TT_BLATHER(("Starting with %d open sockets.", n));
5976 (void)arg;
5978 fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
5979 int err = tor_socket_errno(fd1);
5980 if (fd1 < 0 && (err == SOCK_ERRNO(EPROTONOSUPPORT) ||
5981 err == SOCK_ERRNO(EAFNOSUPPORT))) {
5982 /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
5983 goto done;
5985 fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
5986 tt_assert(SOCKET_OK(fd1));
5987 tt_assert(SOCKET_OK(fd2));
5988 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5989 //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
5990 //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
5991 fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
5992 fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
5993 tt_assert(SOCKET_OK(fd3));
5994 tt_assert(SOCKET_OK(fd4));
5995 tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
5997 #ifdef CAN_CHECK_CLOEXEC
5998 tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
5999 tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
6000 tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
6001 tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
6002 #endif /* defined(CAN_CHECK_CLOEXEC) */
6003 #ifdef CAN_CHECK_NONBLOCK
6004 tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
6005 tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
6006 tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
6007 tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
6008 #endif /* defined(CAN_CHECK_NONBLOCK) */
6010 tor_assert(tor_close_socket == tor_close_socket__real);
6012 /* we use close_socket__real here so that coverity can tell that we are
6013 * really closing these sockets. */
6014 tor_close_socket__real(fd1);
6015 tor_close_socket__real(fd2);
6016 fd1 = fd2 = TOR_INVALID_SOCKET;
6017 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
6018 tor_close_socket__real(fd3);
6019 tor_close_socket__real(fd4);
6020 fd3 = fd4 = TOR_INVALID_SOCKET;
6021 tt_int_op(get_n_open_sockets(), OP_EQ, n);
6023 done:
6024 if (SOCKET_OK(fd1))
6025 tor_close_socket__real(fd1);
6026 if (SOCKET_OK(fd2))
6027 tor_close_socket__real(fd2);
6028 if (SOCKET_OK(fd3))
6029 tor_close_socket__real(fd3);
6030 if (SOCKET_OK(fd4))
6031 tor_close_socket__real(fd4);
6034 #if 0
6035 static int
6036 is_there_a_localhost(int family)
6038 tor_socket_t s;
6039 s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP);
6040 tor_assert(SOCKET_OK(s));
6042 int result = 0;
6043 if (family == AF_INET) {
6044 struct sockaddr_in s_in;
6045 memset(&s_in, 0, sizeof(s_in));
6046 s_in.sin_family = AF_INET;
6047 s_in.sin_addr.s_addr = htonl(0x7f000001);
6048 s_in.sin_port = 0;
6050 if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) {
6051 result = 1;
6053 } else if (family == AF_INET6) {
6054 struct sockaddr_in6 sin6;
6055 memset(&sin6, 0, sizeof(sin6));
6056 sin6.sin6_family = AF_INET6;
6057 sin6.sin6_addr.s6_addr[15] = 1;
6058 sin6.sin6_port = 0;
6060 tor_close_socket(s);
6062 return result;
6064 #endif /* 0 */
6066 /* Test for socketpair and ersatz_socketpair(). We test them both, since
6067 * the latter is a tolerably good way to exercise tor_accept_socket(). */
6068 static void
6069 test_util_socketpair(void *arg)
6071 const int ersatz = !strcmp(arg, "1");
6072 int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
6073 ersatz ? tor_ersatz_socketpair : tor_socketpair;
6074 int n = get_n_open_sockets();
6075 tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
6076 const int family = AF_UNIX;
6077 int socketpair_result = 0;
6079 socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
6081 #ifdef __FreeBSD__
6082 /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail.
6083 * Otherwise, we risk exposing a socketpair on a routable IP address. (Some
6084 * BSD jails use a routable address for localhost. Fortunately, they have
6085 * the real AF_UNIX socketpair.) */
6086 if (ersatz && socketpair_result < 0) {
6087 /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL.
6088 * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */
6089 tt_skip();
6091 #endif /* defined(__FreeBSD__) */
6092 #ifdef ENETUNREACH
6093 if (ersatz && socketpair_result == -ENETUNREACH) {
6094 /* We can also fail with -ENETUNREACH if we have no network stack at
6095 * all. */
6096 tt_skip();
6098 #endif /* defined(ENETUNREACH) */
6099 tt_int_op(0, OP_EQ, socketpair_result);
6101 tt_assert(SOCKET_OK(fds[0]));
6102 tt_assert(SOCKET_OK(fds[1]));
6103 if (ersatz)
6104 tt_int_op(get_n_open_sockets(), OP_EQ, n);
6105 else
6106 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
6107 #ifdef CAN_CHECK_CLOEXEC
6108 tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, !ersatz);
6109 tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, !ersatz);
6110 #endif
6111 #ifdef CAN_CHECK_NONBLOCK
6112 tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
6113 tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
6114 #endif
6116 done:
6117 if (ersatz) {
6118 if (SOCKET_OK(fds[0]))
6119 tor_close_socket_simple(fds[0]);
6120 if (SOCKET_OK(fds[1]))
6121 tor_close_socket_simple(fds[1]);
6122 } else {
6123 if (SOCKET_OK(fds[0]))
6124 tor_close_socket(fds[0]);
6125 if (SOCKET_OK(fds[1]))
6126 tor_close_socket(fds[1]);
6130 #undef SOCKET_EPROTO
6132 static void
6133 test_util_max_mem(void *arg)
6135 size_t memory1, memory2;
6136 int r, r2;
6137 (void) arg;
6139 r = get_total_system_memory(&memory1);
6140 r2 = get_total_system_memory(&memory2);
6141 tt_int_op(r, OP_EQ, r2);
6142 tt_uint_op(memory2, OP_EQ, memory1);
6144 TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1)));
6146 if (r==0) {
6147 /* You have at least a megabyte. */
6148 tt_uint_op(memory1, OP_GT, (1<<20));
6149 } else {
6150 /* You do not have a petabyte. */
6151 #if SIZEOF_SIZE_T >= 8
6152 tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50));
6153 #endif
6156 done:
6160 static void
6161 test_util_dest_validation_edgecase(void *arg)
6163 (void)arg;
6165 tt_assert(!string_is_valid_dest(NULL));
6166 tt_assert(!string_is_valid_dest(""));
6168 done:
6169 return;
6172 static void
6173 test_util_hostname_validation(void *arg)
6175 (void)arg;
6177 // Lets try valid hostnames first.
6178 tt_assert(string_is_valid_nonrfc_hostname("torproject.org"));
6179 tt_assert(string_is_valid_nonrfc_hostname("ocw.mit.edu"));
6180 tt_assert(string_is_valid_nonrfc_hostname("i.4cdn.org"));
6181 tt_assert(string_is_valid_nonrfc_hostname("stanford.edu"));
6182 tt_assert(string_is_valid_nonrfc_hostname("multiple-words-with-hypens.jp"));
6184 // Subdomain name cannot start with '-' or '_'.
6185 tt_assert(!string_is_valid_nonrfc_hostname("-torproject.org"));
6186 tt_assert(!string_is_valid_nonrfc_hostname("subdomain.-domain.org"));
6187 tt_assert(!string_is_valid_nonrfc_hostname("-subdomain.domain.org"));
6188 tt_assert(!string_is_valid_nonrfc_hostname("___abc.org"));
6190 // Hostnames cannot contain non-alphanumeric characters.
6191 tt_assert(!string_is_valid_nonrfc_hostname("%%domain.\\org."));
6192 tt_assert(!string_is_valid_nonrfc_hostname("***x.net"));
6193 tt_assert(!string_is_valid_nonrfc_hostname("\xff\xffxyz.org"));
6194 tt_assert(!string_is_valid_nonrfc_hostname("word1 word2.net"));
6196 // Test workaround for nytimes.com stupidity, technically invalid,
6197 // but we allow it since they are big, even though they are failing to
6198 // comply with a ~30 year old standard.
6199 tt_assert(string_is_valid_nonrfc_hostname("core3_euw1.fabrik.nytimes.com"));
6201 // Firefox passes FQDNs with trailing '.'s directly to the SOCKS proxy,
6202 // which is redundant since the spec states DOMAINNAME addresses are fully
6203 // qualified. While unusual, this should be tollerated.
6204 tt_assert(string_is_valid_nonrfc_hostname("core9_euw1.fabrik.nytimes.com."));
6205 tt_assert(!string_is_valid_nonrfc_hostname(
6206 "..washingtonpost.is.better.com"));
6207 tt_assert(!string_is_valid_nonrfc_hostname("so.is..ft.com"));
6208 tt_assert(!string_is_valid_nonrfc_hostname("..."));
6210 // XXX: do we allow single-label DNS names?
6211 // We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
6212 // but only test pathologically malformed trailing '.' cases for now.
6213 tt_assert(!string_is_valid_nonrfc_hostname("."));
6214 tt_assert(!string_is_valid_nonrfc_hostname(".."));
6216 // IP address strings are not hostnames.
6217 tt_assert(!string_is_valid_nonrfc_hostname("8.8.8.8"));
6218 tt_assert(!string_is_valid_nonrfc_hostname("[2a00:1450:401b:800::200e]"));
6219 tt_assert(!string_is_valid_nonrfc_hostname("2a00:1450:401b:800::200e"));
6221 // We allow alphanumeric TLDs. For discussion, see ticket #25055.
6222 tt_assert(string_is_valid_nonrfc_hostname("lucky.13"));
6223 tt_assert(string_is_valid_nonrfc_hostname("luck.y13"));
6224 tt_assert(string_is_valid_nonrfc_hostname("luck.y13."));
6226 // We allow punycode TLDs. For examples, see
6227 // https://data.iana.org/TLD/tlds-alpha-by-domain.txt
6228 tt_assert(string_is_valid_nonrfc_hostname("example.xn--l1acc"));
6230 done:
6231 return;
6234 static void
6235 test_util_ipv4_validation(void *arg)
6237 (void)arg;
6239 tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
6240 tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
6242 tt_assert(!string_is_valid_ipv4_address("abcd"));
6243 tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
6244 tt_assert(!string_is_valid_ipv4_address("8.8."));
6246 done:
6247 return;
6250 static void
6251 test_util_ipv6_validation(void *arg)
6253 (void)arg;
6255 tt_assert(string_is_valid_ipv6_address("2a00:1450:401b:800::200e"));
6256 tt_assert(!string_is_valid_ipv6_address("11:22::33:44:"));
6258 done:
6259 return;
6262 static void
6263 test_util_writepid(void *arg)
6265 (void) arg;
6267 char *contents = NULL;
6268 const char *fname = get_fname("tmp_pid");
6269 unsigned long pid;
6270 char c;
6272 write_pidfile(fname);
6274 contents = read_file_to_str(fname, 0, NULL);
6275 tt_assert(contents);
6277 int n = tor_sscanf(contents, "%lu\n%c", &pid, &c);
6278 tt_int_op(n, OP_EQ, 1);
6280 #ifdef _WIN32
6281 tt_uint_op(pid, OP_EQ, _getpid());
6282 #else
6283 tt_uint_op(pid, OP_EQ, getpid());
6284 #endif
6286 done:
6287 tor_free(contents);
6290 static void
6291 test_util_get_avail_disk_space(void *arg)
6293 (void) arg;
6294 int64_t val;
6296 /* No answer for nonexistent directory */
6297 val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa");
6298 tt_i64_op(val, OP_EQ, -1);
6300 /* Try the current directory */
6301 val = tor_get_avail_disk_space(".");
6303 #if !defined(HAVE_STATVFS) && !defined(_WIN32)
6304 tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */
6305 #else
6306 tt_i64_op(val, OP_GT, 0); /* You have some space. */
6307 tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */
6308 #endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */
6310 done:
6314 /** Helper: Change the atime and mtime of a file. */
6315 static void
6316 set_file_mtime(const char *fname, time_t when)
6318 struct utimbuf u = { when, when };
6319 struct stat st;
6320 tt_int_op(0, OP_EQ, utime(fname, &u));
6321 tt_int_op(0, OP_EQ, stat(fname, &st));
6322 /* Let's hope that utime/stat give the same second as a round-trip? */
6323 tt_i64_op(st.st_mtime, OP_EQ, when);
6324 done:
6328 static void
6329 test_util_touch_file(void *arg)
6331 (void) arg;
6332 const char *fname = get_fname("touch");
6334 const time_t now = time(NULL);
6335 struct stat st;
6336 write_bytes_to_file(fname, "abc", 3, 1);
6337 tt_int_op(0, OP_EQ, stat(fname, &st));
6338 /* A subtle point: the filesystem time is not necessarily equal to the
6339 * system clock time, since one can be using a monotonic clock, or coarse
6340 * monotonic clock, or whatever. So we might wind up with an mtime a few
6341 * microseconds ago. Let's just give it a lot of wiggle room. */
6342 tt_i64_op(st.st_mtime, OP_GE, now - 1);
6344 const time_t five_sec_ago = now - 5;
6345 set_file_mtime(fname, five_sec_ago);
6347 /* Finally we can touch the file */
6348 tt_int_op(0, OP_EQ, touch_file(fname));
6349 tt_int_op(0, OP_EQ, stat(fname, &st));
6350 tt_i64_op(st.st_mtime, OP_GE, now-1);
6352 done:
6356 #ifndef DISABLE_PWDB_TESTS
6357 static void
6358 test_util_pwdb(void *arg)
6360 (void) arg;
6361 const struct passwd *me = NULL, *me2, *me3;
6362 char *name = NULL;
6363 char *dir = NULL;
6365 /* Uncached case. */
6366 /* Let's assume that we exist. */
6367 me = tor_getpwuid(getuid());
6368 tt_ptr_op(me, OP_NE, NULL);
6369 name = tor_strdup(me->pw_name);
6371 /* Uncached case */
6372 me2 = tor_getpwnam(name);
6373 tt_ptr_op(me2, OP_NE, NULL);
6374 tt_int_op(me2->pw_uid, OP_EQ, getuid());
6376 /* Cached case */
6377 me3 = tor_getpwuid(getuid());
6378 tt_ptr_op(me3, OP_NE, NULL);
6379 tt_str_op(me3->pw_name, OP_EQ, name);
6381 me3 = tor_getpwnam(name);
6382 tt_ptr_op(me3, OP_NE, NULL);
6383 tt_int_op(me3->pw_uid, OP_EQ, getuid());
6385 dir = get_user_homedir(name);
6386 tt_ptr_op(dir, OP_NE, NULL);
6388 /* Try failing cases. First find a user that doesn't exist by name */
6389 char randbytes[4];
6390 char badname[9];
6391 int i, found=0;
6392 for (i = 0; i < 100; ++i) {
6393 crypto_rand(randbytes, sizeof(randbytes));
6394 base16_encode(badname, sizeof(badname), randbytes, sizeof(randbytes));
6395 if (tor_getpwnam(badname) == NULL) {
6396 found = 1;
6397 break;
6400 tt_assert(found);
6401 tor_free(dir);
6403 /* We should do a LOG_ERR */
6404 setup_full_capture_of_logs(LOG_ERR);
6405 dir = get_user_homedir(badname);
6406 tt_ptr_op(dir, OP_EQ, NULL);
6407 expect_log_msg_containing("not found");
6408 tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1);
6409 teardown_capture_of_logs();
6411 /* Now try to find a user that doesn't exist by ID. */
6412 found = 0;
6413 for (i = 0; i < 1000; ++i) {
6414 uid_t u;
6415 crypto_rand((char*)&u, sizeof(u));
6416 if (tor_getpwuid(u) == NULL) {
6417 found = 1;
6418 break;
6421 tt_assert(found);
6423 done:
6424 tor_free(name);
6425 tor_free(dir);
6426 teardown_capture_of_logs();
6428 #endif /* !defined(DISABLE_PWDB_TESTS) */
6430 static void
6431 test_util_calloc_check(void *arg)
6433 (void) arg;
6434 /* Easy cases that are good. */
6435 tt_assert(size_mul_check(0,0));
6436 tt_assert(size_mul_check(0,100));
6437 tt_assert(size_mul_check(100,0));
6438 tt_assert(size_mul_check(100,100));
6440 /* Harder cases that are still good. */
6441 tt_assert(size_mul_check(SIZE_MAX, 1));
6442 tt_assert(size_mul_check(1, SIZE_MAX));
6443 tt_assert(size_mul_check(SIZE_MAX / 10, 9));
6444 tt_assert(size_mul_check(11, SIZE_MAX / 12));
6445 const size_t sqrt_size_max_p1 = ((size_t)1) << (sizeof(size_t) * 4);
6446 tt_assert(size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1 - 1));
6448 /* Cases that overflow */
6449 tt_assert(! size_mul_check(SIZE_MAX, 2));
6450 tt_assert(! size_mul_check(2, SIZE_MAX));
6451 tt_assert(! size_mul_check(SIZE_MAX / 10, 11));
6452 tt_assert(! size_mul_check(11, SIZE_MAX / 10));
6453 tt_assert(! size_mul_check(SIZE_MAX / 8, 9));
6454 tt_assert(! size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1));
6456 done:
6460 static void
6461 test_util_monotonic_time(void *arg)
6463 (void)arg;
6465 monotime_t mt1, mt2;
6466 monotime_coarse_t mtc1, mtc2;
6467 uint64_t nsec1, nsec2, usec1, msec1;
6468 uint64_t nsecc1, nsecc2, usecc1, msecc1;
6469 uint32_t stamp1, stamp2;
6471 monotime_init();
6473 monotime_get(&mt1);
6474 monotime_coarse_get(&mtc1);
6475 nsec1 = monotime_absolute_nsec();
6476 usec1 = monotime_absolute_usec();
6477 msec1 = monotime_absolute_msec();
6478 nsecc1 = monotime_coarse_absolute_nsec();
6479 usecc1 = monotime_coarse_absolute_usec();
6480 msecc1 = monotime_coarse_absolute_msec();
6481 stamp1 = monotime_coarse_to_stamp(&mtc1);
6483 tor_sleep_msec(200);
6485 monotime_get(&mt2);
6486 monotime_coarse_get(&mtc2);
6487 nsec2 = monotime_absolute_nsec();
6488 nsecc2 = monotime_coarse_absolute_nsec();
6489 stamp2 = monotime_coarse_to_stamp(&mtc2);
6491 /* We need to be a little careful here since we don't know the system load.
6493 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_GE, 175);
6494 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_LT, 1000);
6495 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_GE, 125);
6496 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_LT, 1000);
6497 tt_u64_op(nsec2-nsec1, OP_GE, 175000000);
6498 tt_u64_op(nsec2-nsec1, OP_LT, 1000000000);
6499 tt_u64_op(nsecc2-nsecc1, OP_GE, 125000000);
6500 tt_u64_op(nsecc2-nsecc1, OP_LT, 1000000000);
6502 tt_u64_op(msec1, OP_GE, nsec1 / 1000000);
6503 tt_u64_op(usec1, OP_GE, nsec1 / 1000);
6504 tt_u64_op(msecc1, OP_GE, nsecc1 / 1000000);
6505 tt_u64_op(usecc1, OP_GE, nsecc1 / 1000);
6506 tt_u64_op(msec1, OP_LE, nsec1 / 1000000 + 10);
6507 tt_u64_op(usec1, OP_LE, nsec1 / 1000 + 10000);
6508 tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 10);
6509 tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 10000);
6511 uint64_t coarse_stamp_diff =
6512 monotime_coarse_stamp_units_to_approx_msec(stamp2-stamp1);
6513 tt_u64_op(coarse_stamp_diff, OP_GE, 120);
6514 tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
6517 uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
6518 uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
6519 tt_u64_op(ms, OP_GE, 4950);
6520 tt_u64_op(ms, OP_LT, 5050);
6523 done:
6527 static void
6528 test_util_monotonic_time_ratchet(void *arg)
6530 (void)arg;
6531 monotime_init();
6532 monotime_reset_ratchets_for_testing();
6534 /* win32, performance counter ratchet. */
6535 tt_i64_op(100, OP_EQ, ratchet_performance_counter(100));
6536 tt_i64_op(101, OP_EQ, ratchet_performance_counter(101));
6537 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(2000));
6538 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(100));
6539 tt_i64_op(2005, OP_EQ, ratchet_performance_counter(105));
6540 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1105));
6541 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1000));
6542 tt_i64_op(3010, OP_EQ, ratchet_performance_counter(1005));
6544 /* win32, GetTickCounts32 ratchet-and-rollover-detector. */
6545 const int64_t R = ((int64_t)1) << 32;
6546 tt_i64_op(5, OP_EQ, ratchet_coarse_performance_counter(5));
6547 tt_i64_op(1000, OP_EQ, ratchet_coarse_performance_counter(1000));
6548 tt_i64_op(5+R, OP_EQ, ratchet_coarse_performance_counter(5));
6549 tt_i64_op(10+R, OP_EQ, ratchet_coarse_performance_counter(10));
6550 tt_i64_op(4+R*2, OP_EQ, ratchet_coarse_performance_counter(4));
6552 /* gettimeofday regular ratchet. */
6553 struct timeval tv_in = {0,0}, tv_out;
6554 tv_in.tv_usec = 9000;
6556 ratchet_timeval(&tv_in, &tv_out);
6557 tt_int_op(tv_out.tv_usec, OP_EQ, 9000);
6558 tt_i64_op(tv_out.tv_sec, OP_EQ, 0);
6560 tv_in.tv_sec = 1337;
6561 tv_in.tv_usec = 0;
6562 ratchet_timeval(&tv_in, &tv_out);
6563 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
6564 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6566 tv_in.tv_sec = 1336;
6567 tv_in.tv_usec = 500000;
6568 ratchet_timeval(&tv_in, &tv_out);
6569 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
6570 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6572 tv_in.tv_sec = 1337;
6573 tv_in.tv_usec = 0;
6574 ratchet_timeval(&tv_in, &tv_out);
6575 tt_int_op(tv_out.tv_usec, OP_EQ, 500000);
6576 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6578 tv_in.tv_sec = 1337;
6579 tv_in.tv_usec = 600000;
6580 ratchet_timeval(&tv_in, &tv_out);
6581 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
6582 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
6584 tv_in.tv_sec = 1000;
6585 tv_in.tv_usec = 1000;
6586 ratchet_timeval(&tv_in, &tv_out);
6587 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
6588 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
6590 tv_in.tv_sec = 2000;
6591 tv_in.tv_usec = 2000;
6592 ratchet_timeval(&tv_in, &tv_out);
6593 tt_int_op(tv_out.tv_usec, OP_EQ, 101000);
6594 tt_i64_op(tv_out.tv_sec, OP_EQ, 2338);
6596 done:
6600 static void
6601 test_util_monotonic_time_zero(void *arg)
6603 (void) arg;
6604 monotime_t t1;
6605 monotime_coarse_t ct1;
6606 monotime_init();
6607 /* Check 1: The current time is not zero. */
6608 monotime_get(&t1);
6609 monotime_coarse_get(&ct1);
6610 tt_assert(!monotime_is_zero(&t1));
6611 tt_assert(!monotime_coarse_is_zero(&ct1));
6613 /* Check 2: The _zero() makes the time zero. */
6614 monotime_zero(&t1);
6615 monotime_coarse_zero(&ct1);
6616 tt_assert(monotime_is_zero(&t1));
6617 tt_assert(monotime_coarse_is_zero(&ct1));
6618 done:
6622 static void
6623 test_util_monotonic_time_add_msec(void *arg)
6625 (void) arg;
6626 monotime_t t1, t2;
6627 monotime_coarse_t ct1, ct2;
6628 monotime_init();
6630 monotime_get(&t1);
6631 monotime_coarse_get(&ct1);
6633 /* adding zero does nothing */
6634 monotime_add_msec(&t2, &t1, 0);
6635 monotime_coarse_add_msec(&ct2, &ct1, 0);
6636 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 0);
6637 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 0);
6639 /* Add 1337 msec; see if the diff function agree */
6640 monotime_add_msec(&t2, &t1, 1337);
6641 monotime_coarse_add_msec(&ct2, &ct1, 1337);
6642 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
6643 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
6644 // The 32-bit variant must be within 1% of the regular one.
6645 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
6646 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
6648 /* Add 1337 msec twice more; make sure that any second rollover issues
6649 * worked. */
6650 monotime_add_msec(&t2, &t2, 1337);
6651 monotime_coarse_add_msec(&ct2, &ct2, 1337);
6652 monotime_add_msec(&t2, &t2, 1337);
6653 monotime_coarse_add_msec(&ct2, &ct2, 1337);
6654 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
6655 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
6656 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
6657 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
6659 done:
6663 static void
6664 test_util_nowrap_math(void *arg)
6666 (void)arg;
6668 tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
6669 tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
6670 tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
6671 tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
6672 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
6673 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
6674 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
6676 tt_u64_op(0, OP_EQ, tor_mul_u64_nowrap(0, 0));
6677 tt_u64_op(1, OP_EQ, tor_mul_u64_nowrap(1, 1));
6678 tt_u64_op(2, OP_EQ, tor_mul_u64_nowrap(2, 1));
6679 tt_u64_op(4, OP_EQ, tor_mul_u64_nowrap(2, 2));
6680 tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, 1));
6681 tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(2, UINT64_MAX));
6682 tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, UINT64_MAX));
6684 done:
6688 static void
6689 test_util_htonll(void *arg)
6691 (void)arg;
6692 #ifdef WORDS_BIGENDIAN
6693 const uint64_t res_be = 0x8877665544332211;
6694 #else
6695 const uint64_t res_le = 0x1122334455667788;
6696 #endif
6698 tt_u64_op(0, OP_EQ, tor_htonll(0));
6699 tt_u64_op(0, OP_EQ, tor_ntohll(0));
6700 tt_u64_op(UINT64_MAX, OP_EQ, tor_htonll(UINT64_MAX));
6701 tt_u64_op(UINT64_MAX, OP_EQ, tor_ntohll(UINT64_MAX));
6703 #ifdef WORDS_BIGENDIAN
6704 tt_u64_op(res_be, OP_EQ, tor_htonll(0x8877665544332211));
6705 tt_u64_op(res_be, OP_EQ, tor_ntohll(0x8877665544332211));
6706 #else
6707 tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211));
6708 tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211));
6709 #endif /* defined(WORDS_BIGENDIAN) */
6711 done:
6715 static void
6716 test_util_get_unquoted_path(void *arg)
6718 (void)arg;
6720 char *r = NULL;
6722 r = get_unquoted_path("\""); // "
6723 tt_ptr_op(r, OP_EQ, NULL);
6724 tor_free(r);
6726 r = get_unquoted_path("\"\"\""); // """
6727 tt_ptr_op(r, OP_EQ, NULL);
6728 tor_free(r);
6730 r = get_unquoted_path("\\\""); // \"
6731 tt_ptr_op(r, OP_EQ, NULL);
6732 tor_free(r);
6734 r = get_unquoted_path("\\\"\\\""); // \"\"
6735 tt_ptr_op(r, OP_EQ, NULL);
6736 tor_free(r);
6738 r = get_unquoted_path("A\\B\\C\""); // A\B\C"
6739 tt_ptr_op(r, OP_EQ, NULL);
6740 tor_free(r);
6742 r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
6743 tt_ptr_op(r, OP_EQ, NULL);
6744 tor_free(r);
6746 r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
6747 tt_ptr_op(r, OP_EQ, NULL);
6748 tor_free(r);
6750 r = get_unquoted_path("A\\B\"C"); // A\B"C
6751 tt_ptr_op(r, OP_EQ, NULL);
6752 tor_free(r);
6754 r = get_unquoted_path("");
6755 tt_str_op(r, OP_EQ, "");
6756 tor_free(r);
6758 r = get_unquoted_path("\"\""); // ""
6759 tt_str_op(r, OP_EQ, "");
6760 tor_free(r);
6762 r = get_unquoted_path("A\\B\\C"); // A\B\C
6763 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6764 tor_free(r);
6766 r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
6767 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6768 tor_free(r);
6770 r = get_unquoted_path("\"\\\""); // "\"
6771 tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
6772 tor_free(r);
6774 r = get_unquoted_path("\"\\\"\""); // "\""
6775 tt_str_op(r, OP_EQ, "\""); // "
6776 tor_free(r);
6778 r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
6779 tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
6780 tor_free(r);
6782 r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
6783 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6784 tor_free(r);
6786 r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
6787 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6789 done:
6790 tor_free(r);
6793 static void
6794 test_util_map_anon(void *arg)
6796 (void)arg;
6797 char *ptr = NULL;
6798 size_t sz = 16384;
6799 unsigned inherit=0;
6801 /* Basic checks. */
6802 ptr = tor_mmap_anonymous(sz, 0, &inherit);
6803 tt_ptr_op(ptr, OP_NE, 0);
6804 tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
6805 ptr[sz-1] = 3;
6806 tt_int_op(ptr[0], OP_EQ, 0);
6807 tt_int_op(ptr[sz-2], OP_EQ, 0);
6808 tt_int_op(ptr[sz-1], OP_EQ, 3);
6810 /* Try again, with a private (non-swappable) mapping. */
6811 tor_munmap_anonymous(ptr, sz);
6812 ptr = tor_mmap_anonymous(sz, ANONMAP_PRIVATE, &inherit);
6813 tt_ptr_op(ptr, OP_NE, 0);
6814 tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
6815 ptr[sz-1] = 10;
6816 tt_int_op(ptr[0], OP_EQ, 0);
6817 tt_int_op(ptr[sz/2], OP_EQ, 0);
6818 tt_int_op(ptr[sz-1], OP_EQ, 10);
6820 /* Now let's test a drop-on-fork mapping. */
6821 tor_munmap_anonymous(ptr, sz);
6822 ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT, &inherit);
6823 tt_ptr_op(ptr, OP_NE, 0);
6824 ptr[sz-1] = 10;
6825 tt_int_op(ptr[0], OP_EQ, 0);
6826 tt_int_op(ptr[sz/2], OP_EQ, 0);
6827 tt_int_op(ptr[sz-1], OP_EQ, 10);
6829 done:
6830 tor_munmap_anonymous(ptr, sz);
6833 static void
6834 test_util_map_anon_nofork(void *arg)
6836 (void)arg;
6837 #ifdef _WIN32
6838 /* The operating system doesn't support forking. */
6839 tt_skip();
6840 done:
6842 #else /* !defined(_WIN32) */
6843 /* We have the right OS support. We're going to try marking the buffer as
6844 * either zero-on-fork or as drop-on-fork, whichever is supported. Then we
6845 * will fork and send a byte back to the parent process. This will either
6846 * crash, or send zero. */
6848 char *ptr = NULL;
6849 const char TEST_VALUE = 0xd0;
6850 size_t sz = 16384;
6851 int pipefd[2] = {-1, -1};
6852 unsigned inherit=0;
6854 tor_munmap_anonymous(ptr, sz);
6855 ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT, &inherit);
6856 tt_ptr_op(ptr, OP_NE, 0);
6857 memset(ptr, (uint8_t)TEST_VALUE, sz);
6859 tt_int_op(0, OP_EQ, pipe(pipefd));
6860 pid_t child = fork();
6861 if (child == 0) {
6862 /* We're in the child. */
6863 close(pipefd[0]);
6864 ssize_t r = write(pipefd[1], &ptr[sz-1], 1); /* This may crash. */
6865 close(pipefd[1]);
6866 if (r < 0)
6867 exit(1);
6868 exit(0);
6870 tt_int_op(child, OP_GT, 0);
6871 /* In the parent. */
6872 close(pipefd[1]);
6873 pipefd[1] = -1;
6874 char buf[1];
6875 ssize_t r = read(pipefd[0], buf, 1);
6877 if (inherit == INHERIT_RES_ZERO) {
6878 // We should be seeing clear-on-fork behavior.
6879 tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
6880 tt_int_op(buf[0], OP_EQ, 0); // that byte should be zero.
6881 } else if (inherit == INHERIT_RES_DROP) {
6882 // We should be seeing noinherit behavior.
6883 tt_int_op(r, OP_LE, 0); // child said nothing; it should have crashed.
6884 } else {
6885 // noinherit isn't implemented.
6886 tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
6887 tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
6888 tt_int_op(buf[0], OP_EQ, TEST_VALUE); // that byte should be TEST_VALUE.
6891 int ws;
6892 waitpid(child, &ws, 0);
6894 #ifndef NOINHERIT_CAN_FAIL
6895 /* Only if NOINHERIT_CAN_FAIL should it be possible for us to get
6896 * INHERIT_KEEP behavior in this case. */
6897 tt_int_op(inherit, OP_NE, INHERIT_RES_KEEP);
6898 #else
6899 if (inherit == INHERIT_RES_KEEP) {
6900 /* Call this test "skipped", not "passed", since noinherit wasn't
6901 * implemented. */
6902 tt_skip();
6904 #endif /* !defined(NOINHERIT_CAN_FAIL) */
6906 done:
6907 tor_munmap_anonymous(ptr, sz);
6908 if (pipefd[0] >= 0) {
6909 close(pipefd[0]);
6911 if (pipefd[1] >= 0) {
6912 close(pipefd[1]);
6914 #endif /* defined(_WIN32) */
6917 #ifndef COCCI
6918 #define UTIL_LEGACY(name) \
6919 { (#name), test_util_ ## name , 0, NULL, NULL }
6921 #define UTIL_TEST(name, flags) \
6922 { (#name), test_util_ ## name, flags, NULL, NULL }
6924 #define COMPRESS(name, identifier) \
6925 { ("compress/" #name), test_util_compress, 0, &compress_setup, \
6926 (char*)(identifier) }
6928 #define COMPRESS_CONCAT(name, identifier) \
6929 { ("compress_concat/" #name), test_util_decompress_concatenated, 0, \
6930 &compress_setup, \
6931 (char*)(identifier) }
6933 #define COMPRESS_JUNK(name, identifier) \
6934 { ("compress_junk/" #name), test_util_decompress_junk, 0, \
6935 &compress_setup, \
6936 (char*)(identifier) }
6938 #define COMPRESS_DOS(name, identifier) \
6939 { ("compress_dos/" #name), test_util_decompress_dos, 0, \
6940 &compress_setup, \
6941 (char*)(identifier) }
6943 #ifdef _WIN32
6944 #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
6945 #else
6946 #define UTIL_TEST_WIN_ONLY(n, f) { (#n), NULL, TT_SKIP, NULL, NULL }
6947 #endif
6949 #ifdef DISABLE_PWDB_TESTS
6950 #define UTIL_TEST_PWDB(n, f) { (#n), NULL, TT_SKIP, NULL, NULL }
6951 #else
6952 #define UTIL_TEST_PWDB(n, f) UTIL_TEST(n, (f))
6953 #endif
6954 #endif /* !defined(COCCI) */
6956 struct testcase_t util_tests[] = {
6957 UTIL_LEGACY(time),
6958 UTIL_TEST(parse_http_time, 0),
6959 UTIL_LEGACY(config_line),
6960 UTIL_LEGACY(config_line_quotes),
6961 UTIL_LEGACY(config_line_comment_character),
6962 UTIL_LEGACY(config_line_escaped_content),
6963 UTIL_LEGACY(config_line_crlf),
6964 UTIL_TEST(config_line_partition, 0),
6965 UTIL_TEST_PWDB(expand_filename, 0),
6966 UTIL_LEGACY(escape_string_socks),
6967 UTIL_LEGACY(string_is_key_value),
6968 UTIL_LEGACY(strmisc),
6969 UTIL_TEST(parse_integer, 0),
6970 UTIL_LEGACY(pow2),
6971 COMPRESS(zlib, "deflate"),
6972 COMPRESS(gzip, "gzip"),
6973 COMPRESS(lzma, "x-tor-lzma"),
6974 COMPRESS(zstd, "x-zstd"),
6975 COMPRESS(zstd_nostatic, "x-zstd:nostatic"),
6976 COMPRESS(none, "identity"),
6977 COMPRESS_CONCAT(zlib, "deflate"),
6978 COMPRESS_CONCAT(gzip, "gzip"),
6979 COMPRESS_CONCAT(lzma, "x-tor-lzma"),
6980 COMPRESS_CONCAT(zstd, "x-zstd"),
6981 COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"),
6982 COMPRESS_CONCAT(none, "identity"),
6983 COMPRESS_JUNK(zlib, "deflate"),
6984 COMPRESS_JUNK(gzip, "gzip"),
6985 COMPRESS_JUNK(lzma, "x-tor-lzma"),
6986 COMPRESS_DOS(zlib, "deflate"),
6987 COMPRESS_DOS(gzip, "gzip"),
6988 COMPRESS_DOS(lzma, "x-tor-lzma"),
6989 COMPRESS_DOS(zstd, "x-zstd"),
6990 COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"),
6991 UTIL_TEST(gzip_compression_bomb, TT_FORK),
6992 UTIL_LEGACY(datadir),
6993 UTIL_LEGACY(memarea),
6994 UTIL_LEGACY(control_formats),
6995 UTIL_LEGACY(mmap),
6996 UTIL_TEST(sscanf, TT_FORK),
6997 UTIL_LEGACY(format_time_interval),
6998 UTIL_LEGACY(path_is_relative),
6999 UTIL_LEGACY(strtok),
7000 UTIL_LEGACY(di_ops),
7001 UTIL_TEST(memcpy_iftrue_timei, 0),
7002 UTIL_TEST(di_map, 0),
7003 UTIL_TEST(round_to_next_multiple_of, 0),
7004 UTIL_TEST(laplace, 0),
7005 UTIL_TEST(clamp_double_to_int64, 0),
7006 UTIL_TEST(find_str_at_start_of_line, 0),
7007 UTIL_TEST(tor_strreplacechar, 0),
7008 UTIL_TEST(string_is_C_identifier, 0),
7009 UTIL_TEST(string_is_utf8, 0),
7010 UTIL_TEST(asprintf, 0),
7011 UTIL_TEST(listdir, 0),
7012 UTIL_TEST(glob, 0),
7013 UTIL_TEST(get_glob_opened_files, 0),
7014 UTIL_TEST(parent_dir, 0),
7015 UTIL_TEST(ftruncate, 0),
7016 UTIL_TEST(nowrap_math, 0),
7017 UTIL_TEST(num_cpus, 0),
7018 UTIL_TEST_WIN_ONLY(load_win_lib, 0),
7019 UTIL_TEST(format_hex_number, 0),
7020 UTIL_TEST(format_dec_number, 0),
7021 UTIL_TEST(n_bits_set, 0),
7022 UTIL_TEST(eat_whitespace, 0),
7023 UTIL_TEST(sl_new_from_text_lines, 0),
7024 UTIL_TEST(envnames, 0),
7025 UTIL_TEST(make_environment, 0),
7026 UTIL_TEST(set_env_var_in_sl, 0),
7027 UTIL_TEST(read_file_eof_tiny_limit, 0),
7028 UTIL_TEST(read_file_eof_one_loop_a, 0),
7029 UTIL_TEST(read_file_eof_one_loop_b, 0),
7030 UTIL_TEST(read_file_eof_two_loops, 0),
7031 UTIL_TEST(read_file_eof_two_loops_b, 0),
7032 UTIL_TEST(read_file_eof_zero_bytes, 0),
7033 UTIL_TEST(read_file_endlines, 0),
7034 UTIL_TEST(write_chunks_to_file, 0),
7035 UTIL_TEST(write_str_if_changed, 0),
7036 UTIL_TEST(mathlog, 0),
7037 UTIL_TEST(fraction, 0),
7038 UTIL_TEST(weak_random, 0),
7039 { "tor_isinf", test_tor_isinf, TT_FORK, NULL, NULL },
7040 { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
7041 (void*)"4" },
7042 { "socket_ipv6", test_util_socket, TT_FORK,
7043 &passthrough_setup, (void*)"6" },
7044 { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
7045 (void*)"0" },
7046 { "socketpair_ersatz", test_util_socketpair, TT_FORK,
7047 &passthrough_setup, (void*)"1" },
7048 UTIL_TEST(max_mem, 0),
7049 UTIL_TEST(hostname_validation, 0),
7050 UTIL_TEST(dest_validation_edgecase, 0),
7051 UTIL_TEST(ipv4_validation, 0),
7052 UTIL_TEST(ipv6_validation, 0),
7053 UTIL_TEST(writepid, 0),
7054 UTIL_TEST(get_avail_disk_space, 0),
7055 UTIL_TEST(touch_file, 0),
7056 UTIL_TEST_PWDB(pwdb, TT_FORK),
7057 UTIL_TEST(calloc_check, 0),
7058 UTIL_TEST(monotonic_time, 0),
7059 UTIL_TEST(monotonic_time_ratchet, TT_FORK),
7060 UTIL_TEST(monotonic_time_zero, 0),
7061 UTIL_TEST(monotonic_time_add_msec, 0),
7062 UTIL_TEST(timegm_real, 0),
7063 UTIL_TEST(htonll, 0),
7064 UTIL_TEST(get_unquoted_path, 0),
7065 UTIL_TEST(map_anon, 0),
7066 UTIL_TEST(map_anon_nofork, 0),
7067 END_OF_TESTCASES