Remove unused function: dns_randfn_() in dns.c.
[tor.git] / src / test / test_util.c
blob7f07370998b44a816a0c95eb365e6d21a17a8df4
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "orconfig.h"
7 #define COMPAT_PRIVATE
8 #define COMPAT_TIME_PRIVATE
9 #define CONTROL_PRIVATE
10 #define UTIL_PRIVATE
11 #define UTIL_MALLOC_PRIVATE
12 #define SOCKET_PRIVATE
13 #define SUBPROCESS_PRIVATE
14 #include "lib/testsupport/testsupport.h"
15 #include "core/or/or.h"
16 #include "lib/container/buffers.h"
17 #include "app/config/config.h"
18 #include "feature/control/control.h"
19 #include "feature/client/transports.h"
20 #include "lib/crypt_ops/crypto_format.h"
21 #include "lib/crypt_ops/crypto_rand.h"
22 #include "test/test.h"
23 #include "lib/memarea/memarea.h"
24 #include "lib/process/waitpid.h"
25 #include "test/log_test_helpers.h"
26 #include "lib/compress/compress.h"
27 #include "lib/compress/compress_zstd.h"
28 #include "lib/encoding/keyval.h"
29 #include "lib/fdio/fdio.h"
30 #include "lib/fs/winlib.h"
31 #include "lib/process/env.h"
32 #include "lib/process/pidfile.h"
33 #include "lib/process/subprocess.h"
34 #include "lib/intmath/weakrng.h"
35 #include "lib/thread/numcpus.h"
36 #include "lib/math/fp.h"
37 #include "lib/math/laplace.h"
38 #include "lib/meminfo/meminfo.h"
39 #include "lib/time/tvdiff.h"
40 #include "lib/encoding/confline.h"
41 #include "lib/net/socketpair.h"
43 #ifdef HAVE_PWD_H
44 #include <pwd.h>
45 #endif
46 #ifdef HAVE_SYS_UTIME_H
47 #include <sys/utime.h>
48 #endif
49 #ifdef HAVE_UTIME_H
50 #include <utime.h>
51 #endif
52 #ifdef HAVE_SYS_STAT_H
53 #include <sys/stat.h>
54 #endif
55 #ifdef HAVE_FCNTL_H
56 #include <fcntl.h>
57 #endif
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
62 #ifdef _WIN32
63 #include <tchar.h>
64 #endif
65 #include <math.h>
66 #include <ctype.h>
67 #include <float.h>
69 #define INFINITY_DBL ((double)INFINITY)
70 #define NAN_DBL ((double)NAN)
72 /* XXXX this is a minimal wrapper to make the unit tests compile with the
73 * changed tor_timegm interface. */
74 static time_t
75 tor_timegm_wrapper(const struct tm *tm)
77 time_t t;
78 if (tor_timegm(tm, &t) < 0)
79 return -1;
80 return t;
83 #define tor_timegm tor_timegm_wrapper
85 static void
86 test_util_read_until_eof_impl(const char *fname, size_t file_len,
87 size_t read_limit)
89 char *fifo_name = NULL;
90 char *test_str = NULL;
91 char *str = NULL;
92 size_t sz = 9999999;
93 int fd = -1;
94 int r;
96 fifo_name = tor_strdup(get_fname(fname));
97 test_str = tor_malloc(file_len);
98 crypto_rand(test_str, file_len);
100 r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
101 tt_int_op(r, OP_EQ, 0);
103 fd = open(fifo_name, O_RDONLY|O_BINARY);
104 tt_int_op(fd, OP_GE, 0);
105 str = read_file_to_str_until_eof(fd, read_limit, &sz);
106 tt_ptr_op(str, OP_NE, NULL);
108 if (read_limit < file_len)
109 tt_int_op(sz, OP_EQ, read_limit);
110 else
111 tt_int_op(sz, OP_EQ, file_len);
113 tt_mem_op(test_str, OP_EQ, str, sz);
114 tt_int_op(str[sz], OP_EQ, '\0');
116 done:
117 unlink(fifo_name);
118 tor_free(fifo_name);
119 tor_free(test_str);
120 tor_free(str);
121 if (fd >= 0)
122 close(fd);
125 static void
126 test_util_read_file_eof_tiny_limit(void *arg)
128 (void)arg;
129 // purposely set limit shorter than what we wrote to the FIFO to
130 // test the maximum, and that it puts the NUL in the right spot
132 test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
135 static void
136 test_util_read_file_eof_one_loop_a(void *arg)
138 (void)arg;
139 test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
142 static void
143 test_util_read_file_eof_one_loop_b(void *arg)
145 (void)arg;
146 test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
149 static void
150 test_util_read_file_eof_two_loops(void *arg)
152 (void)arg;
153 // write more than 1024 bytes to the FIFO to test two passes through
154 // the loop in the method; if the re-alloc size is changed this
155 // should be updated as well.
157 test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
160 static void
161 test_util_read_file_eof_two_loops_b(void *arg)
163 (void)arg;
165 test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
168 static void
169 test_util_read_file_eof_zero_bytes(void *arg)
171 (void)arg;
172 // zero-byte fifo
173 test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
176 static void
177 test_util_read_file_endlines(void *arg)
179 (void)arg;
181 char *fname = NULL;
182 char *read_content = NULL;
183 int r = -1;
185 /* Write a file that contains both \n and \r\n as line ending. */
186 const char *file_content = "foo bar\n"
187 "foo bar baz\r\n"
188 "foo bar\r\n";
190 const char *expected_file_content = "foo bar\n"
191 "foo bar baz\n"
192 "foo bar\n";
194 fname = tor_strdup(get_fname("file_with_crlf_ending"));
196 r = write_bytes_to_file(fname, file_content, strlen(file_content), 1);
197 tt_int_op(r, OP_EQ, 0);
199 /* Read the file in text mode: we strip \r's from the files on both Windows
200 * and UNIX. */
201 read_content = read_file_to_str(fname, 0, NULL);
203 tt_ptr_op(read_content, OP_NE, NULL);
204 tt_int_op(strlen(read_content), OP_EQ, strlen(expected_file_content));
205 tt_str_op(read_content, OP_EQ, expected_file_content);
207 tor_free(read_content);
209 /* Read the file in binary mode: we should preserve the \r here. */
210 read_content = read_file_to_str(fname, RFTS_BIN, NULL);
212 tt_ptr_op(read_content, OP_NE, NULL);
213 tt_int_op(strlen(read_content), OP_EQ, strlen(file_content));
214 tt_str_op(read_content, OP_EQ, file_content);
216 tor_free(read_content);
218 done:
219 unlink(fname);
220 tor_free(fname);
221 tor_free(read_content);
224 /* Test the basic expected behaviour for write_chunks_to_file.
225 * NOTE: This will need to be updated if we ever change the tempfile location
226 * or extension */
227 static void
228 test_util_write_chunks_to_file(void *arg)
230 char *fname = NULL;
231 char *tempname = NULL;
232 char *str = NULL;
233 int r;
234 struct stat st;
236 /* These should be two different sizes to ensure the data is different
237 * between the data file and the temp file's 'known string' */
238 int temp_str_len = 1024;
239 int data_str_len = 512;
240 char *data_str = tor_malloc(data_str_len);
241 char *temp_str = tor_malloc(temp_str_len);
243 smartlist_t *chunks = smartlist_new();
244 sized_chunk_t c = {data_str, data_str_len/2};
245 sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
246 (void)arg;
248 crypto_rand(temp_str, temp_str_len);
249 crypto_rand(data_str, data_str_len);
251 // Ensure it can write multiple chunks
253 smartlist_add(chunks, &c);
254 smartlist_add(chunks, &c2);
257 * Check if it writes using a tempfile
259 fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
260 tor_asprintf(&tempname, "%s.tmp", fname);
262 // write a known string to a file where the tempfile will be
263 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
264 tt_int_op(r, OP_EQ, 0);
266 // call write_chunks_to_file
267 r = write_chunks_to_file(fname, chunks, 1, 0);
268 tt_int_op(r, OP_EQ, 0);
270 // assert the file has been written (expected size)
271 str = read_file_to_str(fname, RFTS_BIN, &st);
272 tt_assert(str != NULL);
273 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
274 tt_mem_op(data_str, OP_EQ, str, data_str_len);
275 tor_free(str);
277 // assert that the tempfile is removed (should not leave artifacts)
278 str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
279 tt_assert(str == NULL);
281 // Remove old testfile for second test
282 r = unlink(fname);
283 tt_int_op(r, OP_EQ, 0);
284 tor_free(fname);
285 tor_free(tempname);
288 * Check if it skips using a tempfile with flags
290 fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
291 tor_asprintf(&tempname, "%s.tmp", fname);
293 // write a known string to a file where the tempfile will be
294 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
295 tt_int_op(r, OP_EQ, 0);
297 // call write_chunks_to_file with no_tempfile = true
298 r = write_chunks_to_file(fname, chunks, 1, 1);
299 tt_int_op(r, OP_EQ, 0);
301 // assert the file has been written (expected size)
302 str = read_file_to_str(fname, RFTS_BIN, &st);
303 tt_assert(str != NULL);
304 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
305 tt_mem_op(data_str, OP_EQ, str, data_str_len);
306 tor_free(str);
308 // assert the tempfile still contains the known string
309 str = read_file_to_str(tempname, RFTS_BIN, &st);
310 tt_assert(str != NULL);
311 tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
312 tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
314 done:
315 unlink(fname);
316 unlink(tempname);
317 smartlist_free(chunks);
318 tor_free(fname);
319 tor_free(tempname);
320 tor_free(str);
321 tor_free(data_str);
322 tor_free(temp_str);
325 #define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
326 /** test the minimum set of struct tm fields needed for a unique epoch value
327 * this is also the set we use to test tor_timegm */
328 #define TM_EQUAL(a, b) \
329 TT_STMT_BEGIN \
330 _TFE(a, b, tm_year); \
331 _TFE(a, b, tm_mon ); \
332 _TFE(a, b, tm_mday); \
333 _TFE(a, b, tm_hour); \
334 _TFE(a, b, tm_min ); \
335 _TFE(a, b, tm_sec ); \
336 TT_STMT_END
338 static void
339 test_util_time(void *arg)
341 struct timeval start, end;
342 struct tm a_time, b_time;
343 char timestr[128];
344 time_t t_res;
345 int i;
346 struct timeval tv;
348 /* Test tv_udiff and tv_mdiff */
350 (void)arg;
351 start.tv_sec = 5;
352 start.tv_usec = 5000;
354 end.tv_sec = 5;
355 end.tv_usec = 5000;
357 tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
358 tt_int_op(0L,OP_EQ, tv_mdiff(&start, &end));
359 tt_int_op(0L,OP_EQ, tv_udiff(&end, &start));
360 tt_int_op(0L,OP_EQ, tv_mdiff(&end, &start));
362 end.tv_usec = 7000;
364 tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
365 tt_int_op(2L,OP_EQ, tv_mdiff(&start, &end));
366 tt_int_op(-2000L,OP_EQ, tv_udiff(&end, &start));
367 tt_int_op(-2L,OP_EQ, tv_mdiff(&end, &start));
369 end.tv_sec = 6;
371 tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
372 tt_int_op(1002L,OP_EQ, tv_mdiff(&start, &end));
373 tt_int_op(-1002000L,OP_EQ, tv_udiff(&end, &start));
374 tt_int_op(-1002L,OP_EQ, tv_mdiff(&end, &start));
376 end.tv_usec = 0;
378 tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
379 tt_int_op(995L,OP_EQ, tv_mdiff(&start, &end));
380 tt_int_op(-995000L,OP_EQ, tv_udiff(&end, &start));
381 tt_int_op(-995L,OP_EQ, tv_mdiff(&end, &start));
383 end.tv_sec = 4;
385 tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
386 tt_int_op(-1005L,OP_EQ, tv_mdiff(&start, &end));
387 tt_int_op(1005000L,OP_EQ, tv_udiff(&end, &start));
388 tt_int_op(1005L,OP_EQ, tv_mdiff(&end, &start));
390 /* Negative tv_sec values, these will break on platforms where tv_sec is
391 * unsigned */
393 end.tv_sec = -10;
395 tt_int_op(-15005000L,OP_EQ, tv_udiff(&start, &end));
396 tt_int_op(-15005L,OP_EQ, tv_mdiff(&start, &end));
397 tt_int_op(15005000L,OP_EQ, tv_udiff(&end, &start));
398 tt_int_op(15005L,OP_EQ, tv_mdiff(&end, &start));
400 start.tv_sec = -100;
402 tt_int_op(89995000L,OP_EQ, tv_udiff(&start, &end));
403 tt_int_op(89995L,OP_EQ, tv_mdiff(&start, &end));
404 tt_int_op(-89995000L,OP_EQ, tv_udiff(&end, &start));
405 tt_int_op(-89995L,OP_EQ, tv_mdiff(&end, &start));
407 /* Test that tv_usec values round away from zero when converted to msec */
408 start.tv_sec = 0;
409 start.tv_usec = 0;
410 end.tv_sec = 10;
411 end.tv_usec = 499;
413 tt_int_op(10000499L, OP_EQ, tv_udiff(&start, &end));
414 tt_int_op(10000L, OP_EQ, tv_mdiff(&start, &end));
415 tt_int_op(-10000499L, OP_EQ, tv_udiff(&end, &start));
416 tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
418 start.tv_sec = 0;
419 start.tv_usec = 0;
420 end.tv_sec = 10;
421 end.tv_usec = 500;
423 tt_int_op(10000500L, OP_EQ, tv_udiff(&start, &end));
424 tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
425 tt_int_op(-10000500L, OP_EQ, tv_udiff(&end, &start));
426 tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
428 start.tv_sec = 0;
429 start.tv_usec = 0;
430 end.tv_sec = 10;
431 end.tv_usec = 501;
433 tt_int_op(10000501L, OP_EQ, tv_udiff(&start, &end));
434 tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
435 tt_int_op(-10000501L, OP_EQ, tv_udiff(&end, &start));
436 tt_int_op(-10001L, OP_EQ, tv_mdiff(&end, &start));
438 /* Overflow conditions */
440 #ifdef _WIN32
441 /* Would you believe that tv_sec is a long on windows? Of course you would.*/
442 #define TV_SEC_MAX LONG_MAX
443 #define TV_SEC_MIN LONG_MIN
444 #else
445 /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
446 * Which means TIME_MAX is not actually the maximum value of tv_sec.
447 * But that's ok for the moment, because the code correctly performs 64-bit
448 * calculations internally, then catches the overflow. */
449 #define TV_SEC_MAX TIME_MAX
450 #define TV_SEC_MIN TIME_MIN
451 #endif /* defined(_WIN32) */
453 /* Assume tv_usec is an unsigned integer until proven otherwise */
454 #define TV_USEC_MAX UINT_MAX
455 #define TOR_USEC_PER_SEC 1000000
457 /* Overflows in the result type */
459 /* All comparisons work */
460 start.tv_sec = 0;
461 start.tv_usec = 0;
462 end.tv_sec = LONG_MAX/1000 - 2;
463 end.tv_usec = 0;
465 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
466 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
467 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
468 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
470 start.tv_sec = 0;
471 start.tv_usec = 0;
472 end.tv_sec = LONG_MAX/1000000 - 1;
473 end.tv_usec = 0;
475 tt_int_op(end.tv_sec*1000000L, OP_EQ, tv_udiff(&start, &end));
476 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
477 tt_int_op(-end.tv_sec*1000000L, OP_EQ, tv_udiff(&end, &start));
478 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
480 /* No comparisons work */
481 start.tv_sec = 0;
482 start.tv_usec = 0;
483 end.tv_sec = LONG_MAX/1000 + 1;
484 end.tv_usec = 0;
486 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
487 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
488 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
489 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
491 start.tv_sec = 0;
492 start.tv_usec = 0;
493 end.tv_sec = LONG_MAX/1000000 + 1;
494 end.tv_usec = 0;
496 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
497 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
498 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
499 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
501 start.tv_sec = 0;
502 start.tv_usec = 0;
503 end.tv_sec = LONG_MAX/1000;
504 end.tv_usec = TOR_USEC_PER_SEC;
506 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
507 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
508 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
509 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
511 start.tv_sec = 0;
512 start.tv_usec = 0;
513 end.tv_sec = LONG_MAX/1000000;
514 end.tv_usec = TOR_USEC_PER_SEC;
516 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
517 tt_int_op((end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&start, &end));
518 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
519 tt_int_op(-(end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&end, &start));
521 /* Overflows on comparison to zero */
523 start.tv_sec = 0;
524 start.tv_usec = 0;
526 end.tv_sec = TV_SEC_MAX;
527 end.tv_usec = 0;
529 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
530 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
531 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
532 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
534 end.tv_sec = TV_SEC_MAX;
535 end.tv_usec = TOR_USEC_PER_SEC;
537 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
538 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
539 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
540 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
542 end.tv_sec = 0;
543 end.tv_usec = TV_USEC_MAX;
545 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
546 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
547 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
548 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
550 end.tv_sec = TV_SEC_MAX;
551 end.tv_usec = TV_USEC_MAX;
553 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
554 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
555 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
556 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
558 end.tv_sec = 0;
559 end.tv_usec = 0;
561 start.tv_sec = TV_SEC_MIN;
562 start.tv_usec = 0;
564 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
565 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
566 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
567 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
569 start.tv_sec = TV_SEC_MIN;
570 start.tv_usec = TOR_USEC_PER_SEC;
572 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
573 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
574 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
575 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
577 start.tv_sec = TV_SEC_MIN;
578 start.tv_usec = TV_USEC_MAX;
580 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
581 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
582 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
583 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
585 /* overflows on comparison to maxima / minima */
587 start.tv_sec = TV_SEC_MIN;
588 start.tv_usec = 0;
590 end.tv_sec = TV_SEC_MAX;
591 end.tv_usec = 0;
593 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
594 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
595 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
596 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
598 end.tv_sec = TV_SEC_MAX;
599 end.tv_usec = TOR_USEC_PER_SEC;
601 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
602 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
603 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
604 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
606 end.tv_sec = TV_SEC_MAX;
607 end.tv_usec = 0;
609 start.tv_sec = TV_SEC_MIN;
610 start.tv_usec = 0;
612 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
613 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
614 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
615 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
617 start.tv_sec = TV_SEC_MIN;
618 start.tv_usec = TOR_USEC_PER_SEC;
620 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
621 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
622 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
623 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
625 /* overflows on comparison to maxima / minima with extra usec */
627 start.tv_sec = TV_SEC_MIN;
628 start.tv_usec = TOR_USEC_PER_SEC;
630 end.tv_sec = TV_SEC_MAX;
631 end.tv_usec = 0;
633 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
634 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
635 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
636 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
638 end.tv_sec = TV_SEC_MAX;
639 end.tv_usec = TOR_USEC_PER_SEC;
641 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
642 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
643 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
644 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
646 end.tv_sec = TV_SEC_MAX;
647 end.tv_usec = TOR_USEC_PER_SEC;
649 start.tv_sec = TV_SEC_MIN;
650 start.tv_usec = 0;
652 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
653 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
654 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
655 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
657 start.tv_sec = TV_SEC_MIN;
658 start.tv_usec = TOR_USEC_PER_SEC;
660 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
661 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
662 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
663 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
665 /* Test tor_timegm & tor_gmtime_r */
667 /* The test values here are confirmed to be correct on a platform
668 * with a working timegm & gmtime_r. */
670 /* Start with known-zero a_time and b_time.
671 * This avoids passing uninitialised values to TM_EQUAL in a_time.
672 * Zeroing may not be needed for b_time, as long as tor_gmtime_r
673 * never reads the existing values in the structure.
674 * But we really don't want intermittently failing tests. */
675 memset(&a_time, 0, sizeof(struct tm));
676 memset(&b_time, 0, sizeof(struct tm));
678 a_time.tm_year = 2003-1900;
679 a_time.tm_mon = 7;
680 a_time.tm_mday = 30;
681 a_time.tm_hour = 6;
682 a_time.tm_min = 14;
683 a_time.tm_sec = 55;
684 t_res = 1062224095UL;
685 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
686 tor_gmtime_r(&t_res, &b_time);
687 TM_EQUAL(a_time, b_time);
689 a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
690 t_res = 1093846495UL;
691 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
692 tor_gmtime_r(&t_res, &b_time);
693 TM_EQUAL(a_time, b_time);
695 a_time.tm_mon = 1; /* Try a leap year, in feb. */
696 a_time.tm_mday = 10;
697 t_res = 1076393695UL;
698 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
699 tor_gmtime_r(&t_res, &b_time);
700 TM_EQUAL(a_time, b_time);
702 a_time.tm_mon = 0;
703 t_res = 1073715295UL;
704 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
705 tor_gmtime_r(&t_res, &b_time);
706 TM_EQUAL(a_time, b_time);
708 /* This value is in range with 32 bit and 64 bit time_t */
709 a_time.tm_year = 2037-1900;
710 t_res = 2115180895UL;
711 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
712 tor_gmtime_r(&t_res, &b_time);
713 TM_EQUAL(a_time, b_time);
715 /* This value is out of range with 32 bit time_t, but in range for 64 bit
716 * time_t */
717 a_time.tm_year = 2039-1900;
718 #if SIZEOF_TIME_T == 4
719 setup_full_capture_of_logs(LOG_WARN);
720 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
721 expect_single_log_msg_containing("Result does not fit in tor_timegm");
722 teardown_capture_of_logs();
723 #elif SIZEOF_TIME_T == 8
724 t_res = 2178252895UL;
725 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
726 tor_gmtime_r(&t_res, &b_time);
727 TM_EQUAL(a_time, b_time);
728 #endif /* SIZEOF_TIME_T == 4 || ... */
730 /* Test tor_timegm out of range */
732 /* The below tests will all cause a BUG message, so we capture, suppress,
733 * and detect. */
734 #define CAPTURE() do { \
735 setup_full_capture_of_logs(LOG_WARN); \
736 } while (0)
737 #define CHECK_TIMEGM_WARNING(msg) do { \
738 expect_single_log_msg_containing(msg); \
739 teardown_capture_of_logs(); \
740 } while (0)
741 #define CHECK_POSSIBLE_EINVAL() do { \
742 if (mock_saved_log_n_entries()) { \
743 expect_single_log_msg_containing("Invalid argument"); \
745 teardown_capture_of_logs(); \
746 } while (0)
748 #define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
749 CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")
751 /* year */
753 /* Wrong year < 1970 */
754 a_time.tm_year = 1969-1900;
755 CAPTURE();
756 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
757 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
759 a_time.tm_year = -1-1900;
760 CAPTURE();
761 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
762 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
764 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
765 a_time.tm_year = -1*(1 << 16);
766 CAPTURE();
767 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
768 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
770 /* one of the smallest tm_year values my 64 bit system supports:
771 * t_res = -9223372036854775LL without clamping */
772 a_time.tm_year = -292275055-1900;
773 CAPTURE();
774 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
775 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
777 a_time.tm_year = INT32_MIN;
778 CAPTURE();
779 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
780 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
781 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
783 #if SIZEOF_INT == 8
784 a_time.tm_year = -1*(1 << 48);
785 CAPTURE();
786 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
787 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
789 /* while unlikely, the system's gmtime(_r) could return
790 * a "correct" retrospective gregorian negative year value,
791 * which I'm pretty sure is:
792 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
793 * 730485 is the number of days in two millennia, including leap days */
794 a_time.tm_year = -292277022657-1900;
795 CAPTURE();
796 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
797 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
799 a_time.tm_year = INT64_MIN;
800 CAPTURE();
801 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
802 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
803 #endif /* SIZEOF_INT == 8 */
805 /* Wrong year >= INT32_MAX - 1900 */
806 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
807 a_time.tm_year = INT32_MAX-1900;
808 CAPTURE();
809 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
810 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
812 a_time.tm_year = INT32_MAX;
813 CAPTURE();
814 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
815 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
816 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
818 #if SIZEOF_INT == 8
819 /* one of the largest tm_year values my 64 bit system supports */
820 a_time.tm_year = 292278994-1900;
821 CAPTURE();
822 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
823 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
825 /* while unlikely, the system's gmtime(_r) could return
826 * a "correct" proleptic gregorian year value,
827 * which I'm pretty sure is:
828 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
829 * 730485 is the number of days in two millennia, including leap days */
830 a_time.tm_year = 292277026596-1900;
831 CAPTURE();
832 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
833 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
835 a_time.tm_year = INT64_MAX-1900;
836 CAPTURE();
837 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
838 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
840 a_time.tm_year = INT64_MAX;
841 CAPTURE();
842 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
843 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
844 #endif /* SIZEOF_INT == 8 */
846 /* month */
847 a_time.tm_year = 2007-1900; /* restore valid year */
849 a_time.tm_mon = 12; /* Wrong month, it's 0-based */
850 CAPTURE();
851 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
852 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
854 a_time.tm_mon = -1; /* Wrong month */
855 CAPTURE();
856 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
857 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
859 /* day */
860 a_time.tm_mon = 6; /* Try July */
861 a_time.tm_mday = 32; /* Wrong day */
862 CAPTURE();
863 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
864 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
866 a_time.tm_mon = 5; /* Try June */
867 a_time.tm_mday = 31; /* Wrong day */
868 CAPTURE();
869 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
870 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
872 a_time.tm_year = 2008-1900; /* Try a leap year */
873 a_time.tm_mon = 1; /* in feb. */
874 a_time.tm_mday = 30; /* Wrong day */
875 CAPTURE();
876 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
877 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
879 a_time.tm_year = 2011-1900; /* Try a non-leap year */
880 a_time.tm_mon = 1; /* in feb. */
881 a_time.tm_mday = 29; /* Wrong day */
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_mday = 0; /* Wrong day, it's 1-based (to be different) */
887 CAPTURE();
888 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
889 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
891 /* hour */
892 a_time.tm_mday = 3; /* restore valid month day */
894 a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
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_hour = -1; /* Wrong hour */
900 CAPTURE();
901 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
902 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
904 /* minute */
905 a_time.tm_hour = 22; /* restore valid hour */
907 a_time.tm_min = 60; /* Wrong minute, it's 0-based */
908 CAPTURE();
909 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
910 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
912 a_time.tm_min = -1; /* Wrong minute */
913 CAPTURE();
914 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
915 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
917 /* second */
918 a_time.tm_min = 37; /* restore valid minute */
920 a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
921 CAPTURE();
922 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
923 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
925 a_time.tm_sec = -1; /* Wrong second */
926 CAPTURE();
927 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
928 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
930 /* Test tor_gmtime_r out of range */
932 /* time_t < 0 yields a year clamped to 1 or 1970,
933 * depending on whether the implementation of the system gmtime(_r)
934 * sets struct tm (1) or not (1970) */
935 t_res = -1;
936 CAPTURE();
937 tor_gmtime_r(&t_res, &b_time);
938 CHECK_POSSIBLE_EINVAL();
939 tt_assert(b_time.tm_year == (1970-1900) ||
940 b_time.tm_year == (1969-1900));
942 if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
943 t_res = -1*(1 << 30);
944 CAPTURE();
945 tor_gmtime_r(&t_res, &b_time);
946 CHECK_POSSIBLE_EINVAL();
947 tt_assert(b_time.tm_year == (1970-1900) ||
948 b_time.tm_year == (1935-1900));
950 t_res = INT32_MIN;
951 CAPTURE();
952 tor_gmtime_r(&t_res, &b_time);
953 CHECK_POSSIBLE_EINVAL();
954 tt_assert(b_time.tm_year == (1970-1900) ||
955 b_time.tm_year == (1901-1900));
958 #if SIZEOF_TIME_T == 8
960 /* one of the smallest tm_year values my 64 bit system supports:
961 * b_time.tm_year == (-292275055LL-1900LL) without clamping */
962 t_res = -9223372036854775LL;
963 CAPTURE();
964 tor_gmtime_r(&t_res, &b_time);
965 CHECK_POSSIBLE_EINVAL();
966 tt_assert(b_time.tm_year == (1970-1900) ||
967 b_time.tm_year == (1-1900));
969 /* while unlikely, the system's gmtime(_r) could return
970 * a "correct" retrospective gregorian negative year value,
971 * which I'm pretty sure is:
972 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
973 * 730485 is the number of days in two millennia, including leap days
974 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
975 t_res = INT64_MIN;
976 CAPTURE();
977 tor_gmtime_r(&t_res, &b_time);
978 if (! (b_time.tm_year == (1970-1900) ||
979 b_time.tm_year == (1-1900))) {
980 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
982 if (b_time.tm_year != 1970-1900) {
983 CHECK_TIMEGM_WARNING("Rounding up to ");
984 } else {
985 teardown_capture_of_logs();
989 /* As above, but with localtime. */
990 t_res = -9223372036854775LL;
991 CAPTURE();
992 tor_localtime_r(&t_res, &b_time);
993 CHECK_POSSIBLE_EINVAL();
994 tt_assert(b_time.tm_year == (1970-1900) ||
995 b_time.tm_year == (1-1900));
997 /* while unlikely, the system's gmtime(_r) could return
998 * a "correct" retrospective gregorian negative year value,
999 * which I'm pretty sure is:
1000 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
1001 * 730485 is the number of days in two millennia, including leap days
1002 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
1003 t_res = INT64_MIN;
1004 CAPTURE();
1005 tor_localtime_r(&t_res, &b_time);
1006 if (! (b_time.tm_year == (1970-1900) ||
1007 b_time.tm_year == (1-1900))) {
1008 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
1010 if (b_time.tm_year != 1970-1900) {
1011 CHECK_TIMEGM_WARNING("Rounding up to ");
1012 } else {
1013 teardown_capture_of_logs();
1016 #endif /* SIZEOF_TIME_T == 8 */
1018 /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
1019 * depending on whether the implementation of the system gmtime(_r)
1020 * sets struct tm (9999) or not (2037) */
1021 #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
1023 t_res = 3*(1 << 29);
1024 tor_gmtime_r(&t_res, &b_time);
1025 tt_assert(b_time.tm_year == (2021-1900));
1027 t_res = INT32_MAX;
1028 tor_gmtime_r(&t_res, &b_time);
1029 tt_assert(b_time.tm_year == (2037-1900) ||
1030 b_time.tm_year == (2038-1900));
1033 /* as above but with localtime. */
1034 t_res = 3*(1 << 29);
1035 tor_localtime_r(&t_res, &b_time);
1036 tt_assert(b_time.tm_year == (2021-1900));
1038 t_res = INT32_MAX;
1039 tor_localtime_r(&t_res, &b_time);
1040 tt_assert(b_time.tm_year == (2037-1900) ||
1041 b_time.tm_year == (2038-1900));
1043 #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */
1045 #if SIZEOF_TIME_T == 8
1047 /* one of the largest tm_year values my 64 bit system supports:
1048 * b_time.tm_year == (292278994L-1900L) 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 == (2037-1900) ||
1054 b_time.tm_year == (9999-1900));
1056 /* while unlikely, the system's gmtime(_r) could return
1057 * a "correct" proleptic gregorian year value,
1058 * which I'm pretty sure is:
1059 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1060 * 730485 is the number of days in two millennia, including leap days
1061 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1062 t_res = INT64_MAX;
1063 CAPTURE();
1064 tor_gmtime_r(&t_res, &b_time);
1065 CHECK_TIMEGM_WARNING("Rounding down to ");
1067 tt_assert(b_time.tm_year == (2037-1900) ||
1068 b_time.tm_year == (9999-1900));
1071 /* As above but with localtime. */
1072 t_res = 9223372036854775LL;
1073 CAPTURE();
1074 tor_localtime_r(&t_res, &b_time);
1075 CHECK_POSSIBLE_EINVAL();
1076 tt_assert(b_time.tm_year == (2037-1900) ||
1077 b_time.tm_year == (9999-1900));
1079 /* while unlikely, the system's gmtime(_r) could return
1080 * a "correct" proleptic gregorian year value,
1081 * which I'm pretty sure is:
1082 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1083 * 730485 is the number of days in two millennia, including leap days
1084 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1085 t_res = INT64_MAX;
1086 CAPTURE();
1087 tor_localtime_r(&t_res, &b_time);
1088 CHECK_TIMEGM_WARNING("Rounding down to ");
1090 tt_assert(b_time.tm_year == (2037-1900) ||
1091 b_time.tm_year == (9999-1900));
1093 #endif /* SIZEOF_TIME_T == 8 */
1095 /* Test {format,parse}_rfc1123_time */
1097 format_rfc1123_time(timestr, 0);
1098 tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
1099 format_rfc1123_time(timestr, (time_t)1091580502UL);
1100 tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
1102 t_res = 0;
1103 i = parse_rfc1123_time(timestr, &t_res);
1104 tt_int_op(0,OP_EQ, i);
1105 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1107 /* This value is in range with 32 bit and 64 bit time_t */
1108 format_rfc1123_time(timestr, (time_t)2080000000UL);
1109 tt_str_op("Fri, 30 Nov 2035 01:46:40 GMT",OP_EQ, timestr);
1111 t_res = 0;
1112 i = parse_rfc1123_time(timestr, &t_res);
1113 tt_int_op(0,OP_EQ, i);
1114 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1116 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1117 * time_t */
1118 CAPTURE();
1119 format_rfc1123_time(timestr, (time_t)2150000000UL);
1120 CHECK_POSSIBLE_EINVAL();
1122 #if SIZEOF_TIME_T == 4
1123 #if 0
1124 /* Wrapping around will have made it this. */
1125 /* On windows, at least, this is clipped to 1 Jan 1970. ??? */
1126 tt_str_op("Sat, 11 Jan 1902 23:45:04 GMT",OP_EQ, timestr);
1127 #endif
1128 /* Make sure that the right date doesn't parse. */
1129 strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr));
1131 t_res = 0;
1132 CAPTURE();
1133 i = parse_rfc1123_time(timestr, &t_res);
1134 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1135 tt_int_op(-1,OP_EQ, i);
1136 #elif SIZEOF_TIME_T == 8
1137 tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr);
1139 t_res = 0;
1140 i = parse_rfc1123_time(timestr, &t_res);
1141 tt_int_op(0,OP_EQ, i);
1142 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1143 #endif /* SIZEOF_TIME_T == 4 || ... */
1145 /* The timezone doesn't matter */
1146 t_res = 0;
1147 tt_int_op(0,OP_EQ,
1148 parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
1149 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1150 tt_int_op(-1,OP_EQ,
1151 parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
1152 tt_int_op(-1,OP_EQ,
1153 parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
1154 tt_int_op(-1,OP_EQ,
1155 parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
1156 tt_int_op(-1,OP_EQ,
1157 parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
1158 tt_int_op(-1,OP_EQ,
1159 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
1160 tt_int_op(-1,OP_EQ,
1161 parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
1162 tt_int_op(-1,OP_EQ,
1163 parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
1164 tt_int_op(-1,OP_EQ,
1165 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
1166 tt_int_op(-1,OP_EQ,
1167 parse_rfc1123_time("Wed, 30 Mar 1900 23:59:59 GMT", &t_res));
1169 /* Leap year. */
1170 tt_int_op(-1,OP_EQ,
1171 parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
1172 tt_int_op(0,OP_EQ,
1173 parse_rfc1123_time("Wed, 29 Feb 2012 16:00:00 GMT", &t_res));
1175 /* Leap second plus one */
1176 tt_int_op(-1,OP_EQ,
1177 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
1179 /* Test parse_iso_time */
1181 t_res = 0;
1182 i = parse_iso_time("", &t_res);
1183 tt_int_op(-1,OP_EQ, i);
1184 t_res = 0;
1185 i = parse_iso_time("2004-08-32 00:48:22", &t_res);
1186 tt_int_op(-1,OP_EQ, i);
1187 t_res = 0;
1188 i = parse_iso_time("1969-08-03 00:48:22", &t_res);
1189 tt_int_op(-1,OP_EQ, i);
1191 t_res = 0;
1192 i = parse_iso_time("2004-08-04 00:48:22", &t_res);
1193 tt_int_op(0,OP_EQ, i);
1194 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1195 t_res = 0;
1196 i = parse_iso_time("2004-8-4 0:48:22", &t_res);
1197 tt_int_op(0,OP_EQ, i);
1198 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1200 /* This value is in range with 32 bit and 64 bit time_t */
1201 t_res = 0;
1202 i = parse_iso_time("2035-11-30 01:46:40", &t_res);
1203 tt_int_op(0,OP_EQ, i);
1204 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1206 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1207 * time_t */
1208 t_res = 0;
1209 #if SIZEOF_TIME_T == 4
1210 CAPTURE();
1211 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1212 tt_int_op(-1,OP_EQ, i);
1213 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1214 #elif SIZEOF_TIME_T == 8
1215 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1216 tt_int_op(0,OP_EQ, i);
1217 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1218 #endif /* SIZEOF_TIME_T == 4 || ... */
1220 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
1221 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
1222 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
1223 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
1224 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
1225 tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
1226 tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
1227 tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
1228 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
1229 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
1230 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
1232 /* but... that _is_ acceptable if we aren't being strict. */
1233 t_res = 0;
1234 i = parse_iso_time_("2004-08-04 00:48:22XYZ", &t_res, 0, 0);
1235 tt_int_op(0,OP_EQ, i);
1236 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1238 /* try nospace variant. */
1239 t_res = 0;
1240 i = parse_iso_time_nospace("2004-08-04T00:48:22", &t_res);
1241 tt_int_op(0,OP_EQ, i);
1242 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1244 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04T00:48:22", &t_res));
1245 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04 00:48:22", &t_res));
1246 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04x00:48:22", &t_res));
1247 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04x00:48:22", &t_res));
1249 /* Test tor_gettimeofday */
1251 end.tv_sec = 4;
1252 end.tv_usec = 999990;
1253 start.tv_sec = 1;
1254 start.tv_usec = 500;
1256 tor_gettimeofday(&start);
1257 /* now make sure time works. */
1258 tor_gettimeofday(&end);
1259 /* We might've timewarped a little. */
1260 tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
1262 /* Test format_iso_time */
1264 tv.tv_sec = (time_t)1326296338UL;
1265 tv.tv_usec = 3060;
1266 format_iso_time(timestr, (time_t)tv.tv_sec);
1267 tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
1268 /* The output of format_local_iso_time will vary by timezone, and setting
1269 our timezone for testing purposes would be a nontrivial flaky pain.
1270 Skip this test for now.
1271 format_local_iso_time(timestr, tv.tv_sec);
1272 test_streq("2012-01-11 10:38:58", timestr);
1274 format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
1275 tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
1276 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
1277 format_iso_time_nospace_usec(timestr, &tv);
1278 tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
1279 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
1281 tv.tv_usec = 0;
1282 /* This value is in range with 32 bit and 64 bit time_t */
1283 tv.tv_sec = (time_t)2080000000UL;
1284 format_iso_time(timestr, (time_t)tv.tv_sec);
1285 tt_str_op("2035-11-30 01:46:40",OP_EQ, timestr);
1287 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1288 * time_t */
1289 tv.tv_sec = (time_t)2150000000UL;
1290 CAPTURE();
1291 format_iso_time(timestr, (time_t)tv.tv_sec);
1292 CHECK_POSSIBLE_EINVAL();
1293 #if SIZEOF_TIME_T == 4
1294 /* format_iso_time should indicate failure on overflow, but it doesn't yet.
1295 * Hopefully #18480 will improve the failure semantics in this case.
1296 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1298 #elif SIZEOF_TIME_T == 8
1299 #ifndef _WIN32
1300 /* This SHOULD work on windows too; see bug #18665 */
1301 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1302 #endif
1303 #endif /* SIZEOF_TIME_T == 4 || ... */
1305 #undef CAPTURE
1306 #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE
1307 #undef CHECK_POSSIBLE_EINVAL
1309 done:
1310 teardown_capture_of_logs();
1313 static void
1314 test_util_parse_http_time(void *arg)
1316 struct tm a_time;
1317 char b[ISO_TIME_LEN+1];
1318 (void)arg;
1320 #define T(s) do { \
1321 format_iso_time(b, tor_timegm(&a_time)); \
1322 tt_str_op(b, OP_EQ, (s)); \
1323 b[0]='\0'; \
1324 } while (0)
1326 /* Test parse_http_time */
1328 tt_int_op(-1,OP_EQ,
1329 parse_http_time("", &a_time));
1330 tt_int_op(-1,OP_EQ,
1331 parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
1332 tt_int_op(-1,OP_EQ,
1333 parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
1334 tt_int_op(-1,OP_EQ,
1335 parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
1336 tt_int_op(-1,OP_EQ,
1337 parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
1338 tt_int_op(-1,OP_EQ,
1339 parse_http_time("Sunday, August the third", &a_time));
1340 tt_int_op(-1,OP_EQ,
1341 parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
1343 tt_int_op(0,OP_EQ,
1344 parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
1345 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1346 T("1994-08-04 00:48:22");
1347 tt_int_op(0,OP_EQ,
1348 parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
1349 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1350 T("1994-08-04 00:48:22");
1351 tt_int_op(0,OP_EQ,
1352 parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
1353 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1354 T("1994-08-04 00:48:22");
1355 tt_int_op(0,OP_EQ,
1356 parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
1357 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1358 T("1994-08-04 00:48:22");
1359 tt_int_op(0,OP_EQ,
1360 parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
1361 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1362 T("1994-08-04 00:48:22");
1363 tt_int_op(0,OP_EQ,
1364 parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
1365 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1366 T("1994-08-04 00:48:22");
1367 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
1368 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1369 T("1994-08-04 00:48:22");
1370 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
1371 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1372 T("1994-08-04 00:48:22");
1373 tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
1374 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1375 T("1994-08-04 00:48:22");
1376 tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
1377 tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
1378 T("2012-01-01 00:00:00");
1379 tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
1380 tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
1381 T("2012-12-31 00:00:00");
1383 /* This value is in range with 32 bit and 64 bit time_t */
1384 tt_int_op(0,OP_EQ,parse_http_time("Fri, 30 Nov 2035 01:46:40 GMT", &a_time));
1385 tt_int_op((time_t)2080000000UL,OP_EQ, tor_timegm(&a_time));
1386 T("2035-11-30 01:46:40");
1388 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1389 * time_t */
1390 #if SIZEOF_TIME_T == 4
1391 /* parse_http_time should indicate failure on overflow, but it doesn't yet.
1392 * Hopefully #18480 will improve the failure semantics in this case. */
1393 setup_full_capture_of_logs(LOG_WARN);
1394 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1395 tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time));
1396 expect_single_log_msg_containing("does not fit in tor_timegm");
1397 teardown_capture_of_logs();
1398 #elif SIZEOF_TIME_T == 8
1399 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1400 tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time));
1401 T("2038-02-17 06:13:20");
1402 #endif /* SIZEOF_TIME_T == 4 || ... */
1404 tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
1405 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
1406 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
1407 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
1408 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
1409 tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
1410 tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
1411 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
1413 #undef T
1414 done:
1415 teardown_capture_of_logs();
1418 static void
1419 test_util_config_line(void *arg)
1421 char buf[1024];
1422 char *k=NULL, *v=NULL;
1423 const char *str;
1425 /* Test parse_config_line_from_str */
1426 (void)arg;
1427 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
1428 "k2\n"
1429 "k3 \n" "\n" " \n" "#comment\n"
1430 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
1431 "kseven \"a quoted 'string\"\n"
1432 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
1433 "k9 a line that\\\n spans two lines.\n\n"
1434 "k10 more than\\\n one contin\\\nuation\n"
1435 "k11 \\\ncontinuation at the start\n"
1436 "k12 line with a\\\n#comment\n embedded\n"
1437 "k13\\\ncontinuation at the very start\n"
1438 "k14 a line that has a comment and # ends with a slash \\\n"
1439 "k15 this should be the next new line\n"
1440 "k16 a line that has a comment and # ends without a slash \n"
1441 "k17 this should be the next new line\n"
1442 , sizeof(buf));
1443 str = buf;
1445 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1446 tt_str_op(k,OP_EQ, "k");
1447 tt_str_op(v,OP_EQ, "v");
1448 tor_free(k); tor_free(v);
1449 tt_assert(!strcmpstart(str, "key value with"));
1451 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1452 tt_str_op(k,OP_EQ, "key");
1453 tt_str_op(v,OP_EQ, "value with spaces");
1454 tor_free(k); tor_free(v);
1455 tt_assert(!strcmpstart(str, "keykey"));
1457 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1458 tt_str_op(k,OP_EQ, "keykey");
1459 tt_str_op(v,OP_EQ, "val");
1460 tor_free(k); tor_free(v);
1461 tt_assert(!strcmpstart(str, "k2\n"));
1463 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1464 tt_str_op(k,OP_EQ, "k2");
1465 tt_str_op(v,OP_EQ, "");
1466 tor_free(k); tor_free(v);
1467 tt_assert(!strcmpstart(str, "k3 \n"));
1469 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1470 tt_str_op(k,OP_EQ, "k3");
1471 tt_str_op(v,OP_EQ, "");
1472 tor_free(k); tor_free(v);
1473 tt_assert(!strcmpstart(str, "#comment"));
1475 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1476 tt_str_op(k,OP_EQ, "k4");
1477 tt_str_op(v,OP_EQ, "");
1478 tor_free(k); tor_free(v);
1479 tt_assert(!strcmpstart(str, "k5#abc"));
1481 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1482 tt_str_op(k,OP_EQ, "k5");
1483 tt_str_op(v,OP_EQ, "");
1484 tor_free(k); tor_free(v);
1485 tt_assert(!strcmpstart(str, "k6"));
1487 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1488 tt_str_op(k,OP_EQ, "k6");
1489 tt_str_op(v,OP_EQ, "val");
1490 tor_free(k); tor_free(v);
1491 tt_assert(!strcmpstart(str, "kseven"));
1493 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1494 tt_str_op(k,OP_EQ, "kseven");
1495 tt_str_op(v,OP_EQ, "a quoted \'string");
1496 tor_free(k); tor_free(v);
1497 tt_assert(!strcmpstart(str, "k8 "));
1499 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1500 tt_str_op(k,OP_EQ, "k8");
1501 tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
1502 tor_free(k); tor_free(v);
1504 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1505 tt_str_op(k,OP_EQ, "k9");
1506 tt_str_op(v,OP_EQ, "a line that spans two lines.");
1507 tor_free(k); tor_free(v);
1509 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1510 tt_str_op(k,OP_EQ, "k10");
1511 tt_str_op(v,OP_EQ, "more than one continuation");
1512 tor_free(k); tor_free(v);
1514 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1515 tt_str_op(k,OP_EQ, "k11");
1516 tt_str_op(v,OP_EQ, "continuation at the start");
1517 tor_free(k); tor_free(v);
1519 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1520 tt_str_op(k,OP_EQ, "k12");
1521 tt_str_op(v,OP_EQ, "line with a embedded");
1522 tor_free(k); tor_free(v);
1524 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1525 tt_str_op(k,OP_EQ, "k13");
1526 tt_str_op(v,OP_EQ, "continuation at the very start");
1527 tor_free(k); tor_free(v);
1529 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1530 tt_str_op(k,OP_EQ, "k14");
1531 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1532 tor_free(k); tor_free(v);
1534 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1535 tt_str_op(k,OP_EQ, "k15");
1536 tt_str_op(v,OP_EQ, "this should be the next new line");
1537 tor_free(k); tor_free(v);
1539 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1540 tt_str_op(k,OP_EQ, "k16");
1541 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1542 tor_free(k); tor_free(v);
1544 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1545 tt_str_op(k,OP_EQ, "k17");
1546 tt_str_op(v,OP_EQ, "this should be the next new line");
1547 tor_free(k); tor_free(v);
1549 tt_str_op(str,OP_EQ, "");
1551 done:
1552 tor_free(k);
1553 tor_free(v);
1556 static void
1557 test_util_config_line_quotes(void *arg)
1559 char buf1[1024];
1560 char buf2[128];
1561 char buf3[128];
1562 char buf4[128];
1563 char *k=NULL, *v=NULL;
1564 const char *str;
1566 /* Test parse_config_line_from_str */
1567 (void)arg;
1568 strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
1569 "kTrailingGarbage \"quoted value\"trailing garbage\n"
1570 , sizeof(buf1));
1571 strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
1572 , sizeof(buf2));
1573 strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
1574 , sizeof(buf3));
1575 strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
1576 , sizeof(buf4));
1577 str = buf1;
1579 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1580 tt_str_op(k,OP_EQ, "kTrailingSpace");
1581 tt_str_op(v,OP_EQ, "quoted value");
1582 tor_free(k); tor_free(v);
1584 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1585 tt_ptr_op(str,OP_EQ, NULL);
1586 tor_free(k); tor_free(v);
1588 str = buf2;
1590 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1591 tt_ptr_op(str,OP_EQ, NULL);
1592 tor_free(k); tor_free(v);
1594 str = buf3;
1596 const char *err = NULL;
1597 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1598 tt_ptr_op(str,OP_EQ, NULL);
1599 tor_free(k); tor_free(v);
1600 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1602 str = buf4;
1604 err = NULL;
1605 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1606 tt_ptr_op(str,OP_EQ, NULL);
1607 tor_free(k); tor_free(v);
1608 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1610 done:
1611 tor_free(k);
1612 tor_free(v);
1615 static void
1616 test_util_config_line_comment_character(void *arg)
1618 char buf[1024];
1619 char *k=NULL, *v=NULL;
1620 const char *str;
1622 /* Test parse_config_line_from_str */
1623 (void)arg;
1624 strlcpy(buf, "k1 \"# in quotes\"\n"
1625 "k2 some value # some comment\n"
1626 "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
1627 , sizeof(buf));
1628 str = buf;
1630 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1631 tt_str_op(k,OP_EQ, "k1");
1632 tt_str_op(v,OP_EQ, "# in quotes");
1633 tor_free(k); tor_free(v);
1635 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1636 tt_str_op(k,OP_EQ, "k2");
1637 tt_str_op(v,OP_EQ, "some value");
1638 tor_free(k); tor_free(v);
1640 tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
1642 #if 0
1643 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1644 test_streq(k, "k3");
1645 test_streq(v, "/home/user/myTorNetwork#2");
1646 tor_free(k); tor_free(v);
1648 test_streq(str, "");
1649 #endif /* 0 */
1651 done:
1652 tor_free(k);
1653 tor_free(v);
1656 static void
1657 test_util_config_line_escaped_content(void *arg)
1659 char buf1[1024];
1660 char buf2[128];
1661 char buf3[128];
1662 char buf4[128];
1663 char buf5[128];
1664 char buf6[128];
1665 char *k=NULL, *v=NULL;
1666 const char *str;
1668 /* Test parse_config_line_from_str */
1669 (void)arg;
1670 strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
1671 "HexadecimalUpper \"\\x2A\"\n"
1672 "HexadecimalUpperX \"\\X2A\"\n"
1673 "Octal \"\\52\"\n"
1674 "Newline \"\\n\"\n"
1675 "Tab \"\\t\"\n"
1676 "CarriageReturn \"\\r\"\n"
1677 "DoubleQuote \"\\\"\"\n"
1678 "SimpleQuote \"\\'\"\n"
1679 "Backslash \"\\\\\"\n"
1680 "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
1681 , sizeof(buf1));
1683 strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
1684 , sizeof(buf2));
1686 strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
1687 , sizeof(buf3));
1689 strlcpy(buf4, "BrokenOctal \"\\8\"\n"
1690 , sizeof(buf4));
1692 strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
1693 , sizeof(buf5));
1695 strlcpy(buf6, "BrokenEscape \"\\"
1696 , sizeof(buf6));
1698 str = buf1;
1700 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1701 tt_str_op(k,OP_EQ, "HexadecimalLower");
1702 tt_str_op(v,OP_EQ, "*");
1703 tor_free(k); tor_free(v);
1705 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1706 tt_str_op(k,OP_EQ, "HexadecimalUpper");
1707 tt_str_op(v,OP_EQ, "*");
1708 tor_free(k); tor_free(v);
1710 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1711 tt_str_op(k,OP_EQ, "HexadecimalUpperX");
1712 tt_str_op(v,OP_EQ, "*");
1713 tor_free(k); tor_free(v);
1715 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1716 tt_str_op(k,OP_EQ, "Octal");
1717 tt_str_op(v,OP_EQ, "*");
1718 tor_free(k); tor_free(v);
1720 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1721 tt_str_op(k,OP_EQ, "Newline");
1722 tt_str_op(v,OP_EQ, "\n");
1723 tor_free(k); tor_free(v);
1725 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1726 tt_str_op(k,OP_EQ, "Tab");
1727 tt_str_op(v,OP_EQ, "\t");
1728 tor_free(k); tor_free(v);
1730 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1731 tt_str_op(k,OP_EQ, "CarriageReturn");
1732 tt_str_op(v,OP_EQ, "\r");
1733 tor_free(k); tor_free(v);
1735 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1736 tt_str_op(k,OP_EQ, "DoubleQuote");
1737 tt_str_op(v,OP_EQ, "\"");
1738 tor_free(k); tor_free(v);
1740 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1741 tt_str_op(k,OP_EQ, "SimpleQuote");
1742 tt_str_op(v,OP_EQ, "'");
1743 tor_free(k); tor_free(v);
1745 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1746 tt_str_op(k,OP_EQ, "Backslash");
1747 tt_str_op(v,OP_EQ, "\\");
1748 tor_free(k); tor_free(v);
1750 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1751 tt_str_op(k,OP_EQ, "Mix");
1752 tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
1753 tor_free(k); tor_free(v);
1754 tt_str_op(str,OP_EQ, "");
1756 str = buf2;
1758 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1759 tt_ptr_op(str,OP_EQ, NULL);
1760 tor_free(k); tor_free(v);
1762 str = buf3;
1764 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1765 tt_ptr_op(str,OP_EQ, NULL);
1766 tor_free(k); tor_free(v);
1768 str = buf4;
1770 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1771 tt_ptr_op(str,OP_EQ, NULL);
1772 tor_free(k); tor_free(v);
1774 #if 0
1775 str = buf5;
1777 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1778 tt_ptr_op(str, OP_EQ, NULL);
1779 tor_free(k); tor_free(v);
1780 #endif /* 0 */
1782 str = buf6;
1784 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1785 tt_ptr_op(str,OP_EQ, NULL);
1786 tor_free(k); tor_free(v);
1788 /* more things to try. */
1789 /* Bad hex: */
1790 strlcpy(buf1, "Foo \"\\x9g\"\n", sizeof(buf1));
1791 strlcpy(buf2, "Foo \"\\xg0\"\n", sizeof(buf2));
1792 strlcpy(buf3, "Foo \"\\xf\"\n", sizeof(buf3));
1793 /* bad escape */
1794 strlcpy(buf4, "Foo \"\\q\"\n", sizeof(buf4));
1795 /* missing endquote */
1796 strlcpy(buf5, "Foo \"hello\n", sizeof(buf5));
1797 /* extra stuff */
1798 strlcpy(buf6, "Foo \"hello\" world\n", sizeof(buf6));
1800 str=buf1;
1801 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1802 tt_ptr_op(str,OP_EQ, NULL);
1803 tor_free(k); tor_free(v);
1805 str=buf2;
1806 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1807 tt_ptr_op(str,OP_EQ, NULL);
1808 tor_free(k); tor_free(v);
1810 str=buf3;
1811 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1812 tt_ptr_op(str,OP_EQ, NULL);
1813 tor_free(k); tor_free(v);
1815 str=buf4;
1816 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1817 tt_ptr_op(str,OP_EQ, NULL);
1818 tor_free(k); tor_free(v);
1820 str=buf5;
1822 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1823 tt_ptr_op(str,OP_EQ, NULL);
1824 tor_free(k); tor_free(v);
1826 str=buf6;
1827 const char *err = NULL;
1828 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1829 tt_ptr_op(str,OP_EQ, NULL);
1830 tor_free(k); tor_free(v);
1831 tt_str_op(err,OP_EQ, "Excess data after quoted string");
1833 done:
1834 tor_free(k);
1835 tor_free(v);
1838 static void
1839 test_util_config_line_crlf(void *arg)
1841 char *k=NULL, *v=NULL;
1842 const char *err = NULL;
1843 (void)arg;
1844 const char *str =
1845 "Hello world\r\n"
1846 "Hello \"nice big world\"\r\n";
1848 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1849 tt_assert(str);
1850 tt_str_op(k,OP_EQ,"Hello");
1851 tt_str_op(v,OP_EQ,"world");
1852 tt_ptr_op(err, OP_EQ, NULL);
1853 tor_free(k); tor_free(v);
1855 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1856 tt_assert(str);
1857 tt_str_op(k,OP_EQ,"Hello");
1858 tt_str_op(v,OP_EQ,"nice big world");
1859 tt_ptr_op(err, OP_EQ, NULL);
1860 tor_free(k); tor_free(v);
1861 tt_str_op(str,OP_EQ, "");
1863 done:
1864 tor_free(k); tor_free(v);
1867 #ifndef _WIN32
1868 static void
1869 test_util_expand_filename(void *arg)
1871 char *str;
1873 (void)arg;
1874 setenv("HOME", "/home/itv", 1); /* For "internal test value" */
1876 str = expand_filename("");
1877 tt_str_op("",OP_EQ, str);
1878 tor_free(str);
1880 str = expand_filename("/normal/path");
1881 tt_str_op("/normal/path",OP_EQ, str);
1882 tor_free(str);
1884 str = expand_filename("/normal/trailing/path/");
1885 tt_str_op("/normal/trailing/path/",OP_EQ, str);
1886 tor_free(str);
1888 str = expand_filename("~");
1889 tt_str_op("/home/itv/",OP_EQ, str);
1890 tor_free(str);
1892 str = expand_filename("$HOME/nodice");
1893 tt_str_op("$HOME/nodice",OP_EQ, str);
1894 tor_free(str);
1896 str = expand_filename("~/");
1897 tt_str_op("/home/itv/",OP_EQ, str);
1898 tor_free(str);
1900 str = expand_filename("~/foobarqux");
1901 tt_str_op("/home/itv/foobarqux",OP_EQ, str);
1902 tor_free(str);
1904 str = expand_filename("~/../../etc/passwd");
1905 tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
1906 tor_free(str);
1908 str = expand_filename("~/trailing/");
1909 tt_str_op("/home/itv/trailing/",OP_EQ, str);
1910 tor_free(str);
1911 /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
1912 have to somehow inject/fake the get_user_homedir call) */
1914 /* $HOME ending in a trailing slash */
1915 setenv("HOME", "/home/itv/", 1);
1917 str = expand_filename("~");
1918 tt_str_op("/home/itv/",OP_EQ, str);
1919 tor_free(str);
1921 str = expand_filename("~/");
1922 tt_str_op("/home/itv/",OP_EQ, str);
1923 tor_free(str);
1925 str = expand_filename("~/foo");
1926 tt_str_op("/home/itv/foo",OP_EQ, str);
1927 tor_free(str);
1929 /* Try with empty $HOME */
1931 setenv("HOME", "", 1);
1933 str = expand_filename("~");
1934 tt_str_op("/",OP_EQ, str);
1935 tor_free(str);
1937 str = expand_filename("~/");
1938 tt_str_op("/",OP_EQ, str);
1939 tor_free(str);
1941 str = expand_filename("~/foobar");
1942 tt_str_op("/foobar",OP_EQ, str);
1943 tor_free(str);
1945 /* Try with $HOME unset */
1947 unsetenv("HOME");
1949 str = expand_filename("~");
1950 tt_str_op("/",OP_EQ, str);
1951 tor_free(str);
1953 str = expand_filename("~/");
1954 tt_str_op("/",OP_EQ, str);
1955 tor_free(str);
1957 str = expand_filename("~/foobar");
1958 tt_str_op("/foobar",OP_EQ, str);
1959 tor_free(str);
1961 done:
1962 tor_free(str);
1964 #endif /* !defined(_WIN32) */
1966 /** Test tor_escape_str_for_pt_args(). */
1967 static void
1968 test_util_escape_string_socks(void *arg)
1970 char *escaped_string = NULL;
1972 /** Simple backslash escape. */
1973 (void)arg;
1974 escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
1975 tt_assert(escaped_string);
1976 tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
1977 tor_free(escaped_string);
1979 /** Simple semicolon escape. */
1980 escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
1981 tt_assert(escaped_string);
1982 tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
1983 tor_free(escaped_string);
1985 /** Empty string. */
1986 escaped_string = tor_escape_str_for_pt_args("", ";\\");
1987 tt_assert(escaped_string);
1988 tt_str_op(escaped_string,OP_EQ, "");
1989 tor_free(escaped_string);
1991 /** Escape all characters. */
1992 escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
1993 tt_assert(escaped_string);
1994 tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
1995 tor_free(escaped_string);
1997 escaped_string = tor_escape_str_for_pt_args(";", ";\\");
1998 tt_assert(escaped_string);
1999 tt_str_op(escaped_string,OP_EQ, "\\;");
2000 tor_free(escaped_string);
2002 done:
2003 tor_free(escaped_string);
2006 static void
2007 test_util_string_is_key_value(void *ptr)
2009 (void)ptr;
2010 tt_assert(string_is_key_value(LOG_WARN, "key=value"));
2011 tt_assert(string_is_key_value(LOG_WARN, "k=v"));
2012 tt_assert(string_is_key_value(LOG_WARN, "key="));
2013 tt_assert(string_is_key_value(LOG_WARN, "x="));
2014 tt_assert(string_is_key_value(LOG_WARN, "xx="));
2015 tt_assert(!string_is_key_value(LOG_WARN, "=value"));
2016 tt_assert(!string_is_key_value(LOG_WARN, "=x"));
2017 tt_assert(!string_is_key_value(LOG_WARN, "="));
2019 /* ??? */
2020 /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
2021 done:
2025 /** Test basic string functionality. */
2026 static void
2027 test_util_strmisc(void *arg)
2029 char buf[1024];
2030 char *cp_tmp = NULL;
2032 /* Test strl operations */
2033 (void)arg;
2034 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
2035 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
2036 tt_str_op(buf,OP_EQ, "Hello");
2037 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
2038 tt_str_op(buf,OP_EQ, "Hello");
2039 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
2040 tt_str_op(buf,OP_EQ, "Hell");
2041 strlcpy(buf, "Hello", sizeof(buf));
2042 tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
2044 /* Test strstrip() */
2045 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
2046 tor_strstrip(buf, ",!");
2047 tt_str_op(buf,OP_EQ, "Testing 1 2 3");
2048 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
2049 tor_strstrip(buf, "!? ");
2050 tt_str_op(buf,OP_EQ, "Testing123");
2051 strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
2052 tor_strstrip(buf, "!? ");
2053 tt_str_op(buf,OP_EQ, "Testing123");
2055 /* Test snprintf */
2056 /* Returning -1 when there's not enough room in the output buffer */
2057 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
2058 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
2059 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
2060 tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
2061 /* Always NUL-terminate the output */
2062 tor_snprintf(buf, 5, "abcdef");
2063 tt_int_op(0,OP_EQ, buf[4]);
2064 tor_snprintf(buf, 10, "abcdef");
2065 tt_int_op(0,OP_EQ, buf[6]);
2066 /* uint64 */
2067 tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x",
2068 (UINT64_C(12345678901)));
2069 tt_str_op("x!12345678901!x",OP_EQ, buf);
2071 /* Test str{,case}cmpstart */
2072 tt_assert(strcmpstart("abcdef", "abcdef")==0);
2073 tt_assert(strcmpstart("abcdef", "abc")==0);
2074 tt_assert(strcmpstart("abcdef", "abd")<0);
2075 tt_assert(strcmpstart("abcdef", "abb")>0);
2076 tt_assert(strcmpstart("ab", "abb")<0);
2077 tt_assert(strcmpstart("ab", "")==0);
2078 tt_assert(strcmpstart("ab", "ab ")<0);
2079 tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
2080 tt_assert(strcasecmpstart("abcDeF", "abc")==0);
2081 tt_assert(strcasecmpstart("abcdef", "Abd")<0);
2082 tt_assert(strcasecmpstart("Abcdef", "abb")>0);
2083 tt_assert(strcasecmpstart("ab", "Abb")<0);
2084 tt_assert(strcasecmpstart("ab", "")==0);
2085 tt_assert(strcasecmpstart("ab", "ab ")<0);
2087 /* Test str{,case}cmpend */
2088 tt_assert(strcmpend("abcdef", "abcdef")==0);
2089 tt_assert(strcmpend("abcdef", "def")==0);
2090 tt_assert(strcmpend("abcdef", "deg")<0);
2091 tt_assert(strcmpend("abcdef", "dee")>0);
2092 tt_assert(strcmpend("ab", "aab")>0);
2093 tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
2094 tt_assert(strcasecmpend("abcdef", "dEF")==0);
2095 tt_assert(strcasecmpend("abcdef", "Deg")<0);
2096 tt_assert(strcasecmpend("abcDef", "dee")>0);
2097 tt_assert(strcasecmpend("AB", "abb")<0);
2099 /* Test digest_is_zero */
2100 memset(buf,0,20);
2101 buf[20] = 'x';
2102 tt_assert(tor_digest_is_zero(buf));
2103 buf[19] = 'x';
2104 tt_assert(!tor_digest_is_zero(buf));
2106 /* Test mem_is_zero */
2107 memset(buf,0,128);
2108 buf[128] = 'x';
2109 tt_assert(tor_mem_is_zero(buf, 10));
2110 tt_assert(tor_mem_is_zero(buf, 20));
2111 tt_assert(tor_mem_is_zero(buf, 128));
2112 tt_assert(!tor_mem_is_zero(buf, 129));
2113 buf[60] = (char)255;
2114 tt_assert(!tor_mem_is_zero(buf, 128));
2115 buf[0] = (char)1;
2116 tt_assert(!tor_mem_is_zero(buf, 10));
2118 /* Test 'escaped' */
2119 tt_ptr_op(escaped(NULL), OP_EQ, NULL);
2120 tt_str_op("\"\"",OP_EQ, escaped(""));
2121 tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
2122 tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
2123 tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
2124 escaped("unnecessary \'backslashes\'"));
2125 /* Non-printable characters appear as octal */
2126 tt_str_op("\"z\\001abc\\277d\"",OP_EQ, escaped("z\001abc\277d"));
2127 tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
2129 /* Other cases of esc_for_log{,_len} */
2130 cp_tmp = esc_for_log(NULL);
2131 tt_str_op(cp_tmp, OP_EQ, "(null)");
2132 tor_free(cp_tmp);
2133 cp_tmp = esc_for_log_len("abcdefg", 3);
2134 tt_str_op(cp_tmp, OP_EQ, "\"abc\"");
2135 tor_free(cp_tmp);
2136 cp_tmp = esc_for_log_len("abcdefg", 100);
2137 tt_str_op(cp_tmp, OP_EQ, "\"abcdefg\"");
2138 tor_free(cp_tmp);
2140 /* Test strndup and memdup */
2142 const char *s = "abcdefghijklmnopqrstuvwxyz";
2143 cp_tmp = tor_strndup(s, 30);
2144 tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
2145 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2146 tor_free(cp_tmp);
2148 cp_tmp = tor_strndup(s, 5);
2149 tt_str_op(cp_tmp,OP_EQ, "abcde");
2150 tor_free(cp_tmp);
2152 s = "a\0b\0c\0d\0e\0";
2153 cp_tmp = tor_memdup(s,10);
2154 tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
2155 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2156 tor_free(cp_tmp);
2159 /* Test str-foo functions */
2160 cp_tmp = tor_strdup("abcdef");
2161 tt_assert(tor_strisnonupper(cp_tmp));
2162 cp_tmp[3] = 'D';
2163 tt_assert(!tor_strisnonupper(cp_tmp));
2164 tor_strupper(cp_tmp);
2165 tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
2166 tor_strlower(cp_tmp);
2167 tt_str_op(cp_tmp,OP_EQ, "abcdef");
2168 tt_assert(tor_strisnonupper(cp_tmp));
2169 tt_assert(tor_strisprint(cp_tmp));
2170 cp_tmp[3] = 3;
2171 tt_assert(!tor_strisprint(cp_tmp));
2172 tor_free(cp_tmp);
2174 /* Test memmem and memstr */
2176 const char *haystack = "abcde";
2177 tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL);
2178 tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
2179 tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
2180 tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL);
2181 haystack = "ababcad";
2182 tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
2183 tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
2184 tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
2185 tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL);
2186 tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL);
2187 /* memstr */
2188 tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
2189 tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
2190 tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL);
2191 tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL);
2192 tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL);
2193 tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL);
2196 /* Test hex_str */
2198 char binary_data[68];
2199 size_t idx;
2200 for (idx = 0; idx < sizeof(binary_data); ++idx)
2201 binary_data[idx] = idx;
2202 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2203 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2204 tt_str_op(hex_str(binary_data, 17),OP_EQ,
2205 "000102030405060708090A0B0C0D0E0F10");
2206 tt_str_op(hex_str(binary_data, 32),OP_EQ,
2207 "000102030405060708090A0B0C0D0E0F"
2208 "101112131415161718191A1B1C1D1E1F");
2209 tt_str_op(hex_str(binary_data, 34),OP_EQ,
2210 "000102030405060708090A0B0C0D0E0F"
2211 "101112131415161718191A1B1C1D1E1F");
2212 /* Repeat these tests for shorter strings after longer strings
2213 have been tried, to make sure we're correctly terminating strings */
2214 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2215 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2218 /* Test strcmp_opt */
2219 tt_int_op(strcmp_opt("", "foo"), OP_LT, 0);
2220 tt_int_op(strcmp_opt("", ""), OP_EQ, 0);
2221 tt_int_op(strcmp_opt("foo", ""), OP_GT, 0);
2223 tt_int_op(strcmp_opt(NULL, ""), OP_LT, 0);
2224 tt_int_op(strcmp_opt(NULL, NULL), OP_EQ, 0);
2225 tt_int_op(strcmp_opt("", NULL), OP_GT, 0);
2227 tt_int_op(strcmp_opt(NULL, "foo"), OP_LT, 0);
2228 tt_int_op(strcmp_opt("foo", NULL), OP_GT, 0);
2230 /* Test strcmp_len */
2231 tt_int_op(strcmp_len("foo", "bar", 3), OP_GT, 0);
2232 tt_int_op(strcmp_len("foo", "bar", 2), OP_LT, 0);
2233 tt_int_op(strcmp_len("foo2", "foo1", 4), OP_GT, 0);
2234 tt_int_op(strcmp_len("foo2", "foo1", 3), OP_LT, 0); /* Really stop at len */
2235 tt_int_op(strcmp_len("foo2", "foo", 3), OP_EQ, 0); /* Really stop at len */
2236 tt_int_op(strcmp_len("blah", "", 4), OP_GT, 0);
2237 tt_int_op(strcmp_len("blah", "", 0), OP_EQ, 0);
2239 done:
2240 tor_free(cp_tmp);
2243 static void
2244 test_util_parse_integer(void *arg)
2246 (void)arg;
2247 int i;
2248 char *cp;
2250 /* Test parse_long */
2251 /* Empty/zero input */
2252 tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
2253 tt_int_op(0,OP_EQ, i);
2254 tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
2255 tt_int_op(1,OP_EQ, i);
2256 /* Normal cases */
2257 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
2258 tt_int_op(1,OP_EQ, i);
2259 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
2260 tt_int_op(1,OP_EQ, i);
2261 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
2262 tt_int_op(1,OP_EQ, i);
2263 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
2264 tt_int_op(1,OP_EQ, i);
2265 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
2266 tt_int_op(1,OP_EQ, i);
2267 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
2268 tt_int_op(1,OP_EQ, i);
2269 /* Extra garbage */
2270 tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
2271 tt_int_op(0,OP_EQ, i);
2272 tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
2273 tt_int_op(0,OP_EQ, i);
2274 tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
2275 tt_int_op(1,OP_EQ, i);
2276 tt_str_op(cp,OP_EQ, "m");
2277 tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
2278 tt_int_op(1,OP_EQ, i);
2279 tt_str_op(cp,OP_EQ, " plus garbage");
2280 /* Illogical min max */
2281 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL));
2282 tt_int_op(0,OP_EQ, i);
2283 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL));
2284 tt_int_op(0,OP_EQ, i);
2285 /* Out of bounds */
2286 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
2287 tt_int_op(0,OP_EQ, i);
2288 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,0,100,&i,NULL));
2289 tt_int_op(0,OP_EQ, i);
2290 /* Base different than 10 */
2291 tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL));
2292 tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
2293 tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
2294 tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
2295 tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
2296 tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
2297 tt_int_op(i,OP_EQ, 0);
2299 /* Test parse_ulong */
2300 tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
2301 tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
2302 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
2303 tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
2304 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
2305 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
2306 tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
2307 tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
2308 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
2309 tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
2310 tt_int_op(0,OP_EQ, i);
2311 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
2312 tt_int_op(0,OP_EQ, i);
2314 /* Test parse_uint64 */
2315 tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
2316 tt_int_op(1,OP_EQ, i);
2317 tt_str_op(cp,OP_EQ, " x");
2318 tt_assert(UINT64_C(12345678901) ==
2319 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
2320 tt_int_op(1,OP_EQ, i);
2321 tt_str_op(cp,OP_EQ, "");
2322 tt_assert(UINT64_C(0) ==
2323 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
2324 tt_int_op(0,OP_EQ, i);
2325 tt_assert(UINT64_C(0) ==
2326 tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
2327 tt_int_op(0,OP_EQ, i);
2330 /* Test parse_double */
2331 double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
2332 tt_int_op(1,OP_EQ, i);
2333 tt_assert(((uint64_t)d) == 10);
2334 d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
2335 tt_int_op(1,OP_EQ, i);
2336 tt_assert(((uint64_t)d) == 0);
2337 d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
2338 tt_double_op(fabs(d), OP_LT, 1e-10);
2339 tt_int_op(0,OP_EQ, i);
2340 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL);
2341 tt_double_op(fabs(d), OP_LT, 1e-10);
2342 tt_int_op(0,OP_EQ, i);
2343 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp);
2344 tt_double_op(fabs(d), OP_LT, 1e-10);
2345 tt_int_op(1,OP_EQ, i);
2346 d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
2347 tt_int_op(1,OP_EQ, i);
2348 tt_assert(((uint64_t)d) == 0);
2349 d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
2350 tt_int_op(1,OP_EQ, i);
2351 tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
2355 /* Test tor_parse_* where we overflow/underflow the underlying type. */
2356 /* This string should overflow 64-bit ints. */
2357 #define TOOBIG "100000000000000000000000000"
2358 tt_int_op(0L, OP_EQ,
2359 tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2360 tt_int_op(i,OP_EQ, 0);
2361 tt_int_op(0L,OP_EQ,
2362 tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2363 tt_int_op(i,OP_EQ, 0);
2364 tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
2365 tt_int_op(i,OP_EQ, 0);
2366 tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
2367 0, UINT64_MAX, &i, NULL));
2368 tt_int_op(i,OP_EQ, 0);
2370 done:
2374 static void
2375 test_util_pow2(void *arg)
2377 /* Test tor_log2(). */
2378 (void)arg;
2379 tt_int_op(tor_log2(64),OP_EQ, 6);
2380 tt_int_op(tor_log2(65),OP_EQ, 6);
2381 tt_int_op(tor_log2(63),OP_EQ, 5);
2382 /* incorrect mathematically, but as specified: */
2383 tt_int_op(tor_log2(0),OP_EQ, 0);
2384 tt_int_op(tor_log2(1),OP_EQ, 0);
2385 tt_int_op(tor_log2(2),OP_EQ, 1);
2386 tt_int_op(tor_log2(3),OP_EQ, 1);
2387 tt_int_op(tor_log2(4),OP_EQ, 2);
2388 tt_int_op(tor_log2(5),OP_EQ, 2);
2389 tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55);
2390 tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
2392 /* Test round_to_power_of_2 */
2393 tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
2394 tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
2395 tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
2396 tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ,
2397 UINT64_C(1)<<55);
2398 tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ,
2399 UINT64_C(1)<<63);
2400 tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
2401 tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
2402 tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
2403 tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
2404 tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
2405 tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
2406 tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
2407 tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
2409 done:
2413 static void
2414 test_util_compress_impl(compress_method_t method)
2416 char *buf1=NULL, *buf2=NULL, *buf3=NULL;
2417 size_t len1, len2;
2419 tt_assert(tor_compress_supports_method(method));
2421 if (method != NO_METHOD) {
2422 tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
2423 tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
2426 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
2427 tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
2429 tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
2430 tt_ptr_op(buf2, OP_NE, NULL);
2431 if (method == NO_METHOD) {
2432 // The identity transform doesn't actually compress, and it isn't
2433 // detectable as "the identity transform."
2434 tt_int_op(len1, OP_EQ, strlen(buf1)+1);
2435 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
2436 } else {
2437 tt_int_op(len1, OP_LT, strlen(buf1));
2438 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
2441 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
2442 tt_ptr_op(buf3, OP_NE, NULL);
2443 tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
2444 tt_str_op(buf1, OP_EQ, buf3);
2445 tt_int_op(buf3[len2], OP_EQ, 0);
2447 /* Check whether we can uncompress concatenated, compressed strings. */
2448 tor_free(buf3);
2449 buf2 = tor_reallocarray(buf2, len1, 2);
2450 memcpy(buf2+len1, buf2, len1);
2451 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
2452 tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
2453 tt_mem_op(buf3, OP_EQ,
2454 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
2455 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
2456 (strlen(buf1)+1)*2);
2457 tt_int_op(buf3[len2], OP_EQ, 0);
2459 /* Check whether we can uncompress partial strings */
2461 tor_free(buf1);
2462 tor_free(buf2);
2463 tor_free(buf3);
2465 size_t b1len = 1<<10;
2466 if (method == ZSTD_METHOD) {
2467 // zstd needs a big input before it starts generating output that it
2468 // can partially decompress.
2469 b1len = 1<<18;
2471 buf1 = tor_malloc(b1len);
2472 crypto_rand(buf1, b1len);
2473 tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
2474 tt_int_op(len1, OP_GT, 16);
2475 /* when we allow an incomplete output we should succeed.*/
2476 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
2477 method, 0, LOG_INFO));
2478 tt_int_op(len2, OP_GT, 5);
2479 tt_int_op(len2, OP_LE, len1);
2480 tt_assert(fast_memeq(buf1, buf3, len2));
2481 tt_int_op(buf3[len2], OP_EQ, 0);
2483 /* when we demand a complete output from a real compression method, this
2484 * must fail. */
2485 tor_free(buf3);
2486 if (method != NO_METHOD) {
2487 tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
2488 method, 1, LOG_INFO));
2489 tt_ptr_op(buf3, OP_EQ, NULL);
2492 done:
2493 tor_free(buf1);
2494 tor_free(buf2);
2495 tor_free(buf3);
2498 static void
2499 test_util_compress_stream_impl(compress_method_t method,
2500 compression_level_t level)
2502 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
2503 const char *ccp2;
2504 size_t len1, len2;
2506 tor_compress_state_t *state = NULL;
2507 state = tor_compress_new(1, method, level);
2508 tt_assert(state);
2509 cp1 = buf1 = tor_malloc(1024);
2510 len1 = 1024;
2511 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
2512 len2 = 21;
2513 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
2514 OP_EQ, TOR_COMPRESS_OK);
2515 tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
2516 tt_assert(cp1 > buf1);
2518 len2 = 0;
2519 cp2 = cp1;
2520 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
2521 OP_EQ, TOR_COMPRESS_DONE);
2522 tt_int_op(0, OP_EQ, len2);
2523 if (method == NO_METHOD) {
2524 tt_ptr_op(cp1, OP_EQ, cp2);
2525 } else {
2526 tt_assert(cp1 > cp2); /* Make sure we really added something. */
2529 tt_int_op(tor_compress_state_size(state), OP_GT, 0);
2531 tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
2532 method, 1, LOG_WARN));
2533 /* Make sure it compressed right. */
2534 tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
2535 tt_int_op(21, OP_EQ, len2);
2537 done:
2538 if (state)
2539 tor_compress_free(state);
2540 tor_free(buf1);
2541 tor_free(buf2);
2542 tor_free(buf3);
2545 /** Setup function for compression tests: handles x-zstd:nostatic
2547 static void *
2548 compression_test_setup(const struct testcase_t *testcase)
2550 tor_assert(testcase->setup_data);
2551 tor_assert(testcase->setup_data != (void*)TT_SKIP);
2552 const char *methodname = testcase->setup_data;
2554 if (!strcmp(methodname, "x-zstd:nostatic")) {
2555 methodname = "x-zstd";
2556 tor_zstd_set_static_apis_disabled_for_testing(1);
2559 return (void *)methodname;
2562 /** Cleanup for compression tests: disables nostatic */
2563 static int
2564 compression_test_cleanup(const struct testcase_t *testcase, void *ptr)
2566 (void)testcase;
2567 (void)ptr;
2568 tor_zstd_set_static_apis_disabled_for_testing(0);
2569 return 1;
2572 static const struct testcase_setup_t compress_setup = {
2573 compression_test_setup, compression_test_cleanup
2576 /** Run unit tests for compression functions */
2577 static void
2578 test_util_compress(void *arg)
2580 const char *methodname = arg;
2581 tt_assert(methodname);
2583 compress_method_t method = compression_method_get_by_name(methodname);
2584 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2586 if (! tor_compress_supports_method(method)) {
2587 tt_skip();
2590 compression_level_t levels[] = {
2591 BEST_COMPRESSION,
2592 HIGH_COMPRESSION,
2593 MEDIUM_COMPRESSION,
2594 LOW_COMPRESSION
2597 test_util_compress_impl(method);
2599 for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
2600 compression_level_t level = levels[l];
2601 test_util_compress_stream_impl(method, level);
2603 done:
2607 static void
2608 test_util_decompress_concatenated_impl(compress_method_t method)
2610 char input[4096];
2611 char *c1 = NULL, *c2 = NULL, *c3 = NULL;
2612 char *result = NULL;
2613 size_t sz1, sz2, sz3, szr;
2614 int r;
2616 crypto_rand(input, sizeof(input));
2618 /* Compress the input in two chunks. */
2619 r = tor_compress(&c1, &sz1, input, 2048, method);
2620 tt_int_op(r, OP_EQ, 0);
2621 r = tor_compress(&c2, &sz2, input+2048, 2048, method);
2622 tt_int_op(r, OP_EQ, 0);
2624 /* concatenate the chunks. */
2625 sz3 = sz1 + sz2;
2626 c3 = tor_malloc(sz3);
2627 memcpy(c3, c1, sz1);
2628 memcpy(c3+sz1, c2, sz2);
2630 /* decompress the concatenated result */
2631 r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
2632 tt_int_op(r, OP_EQ, 0);
2633 tt_int_op(szr, OP_EQ, sizeof(input));
2634 tt_mem_op(result, OP_EQ, input, sizeof(input));
2636 done:
2637 tor_free(c1);
2638 tor_free(c2);
2639 tor_free(c3);
2640 tor_free(result);
2643 static void
2644 test_util_decompress_concatenated(void *arg)
2646 const char *methodname = arg;
2647 tt_assert(methodname);
2649 compress_method_t method = compression_method_get_by_name(methodname);
2650 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2651 if (! tor_compress_supports_method(method)) {
2652 tt_skip();
2655 test_util_decompress_concatenated_impl(method);
2656 done:
2660 static void
2661 test_util_decompress_junk_impl(compress_method_t method)
2663 char input[4096];
2664 char *result = NULL, *result2 = NULL;
2665 size_t szr, szr2, sz;
2666 int r;
2668 /* This shouldn't be a compressed string according to any method. */
2669 strlcpy(input, "This shouldn't be a compressed string by any means.",
2670 sizeof(input));
2671 sz = strlen(input);
2672 setup_capture_of_logs(LOG_WARN);
2673 r = tor_uncompress(&result, &szr, input, sz, method, 0, LOG_WARN);
2674 tt_int_op(r, OP_EQ, -1);
2675 tt_ptr_op(result, OP_EQ, NULL);
2676 expect_log_msg_containing("Error while uncompressing data: bad input?");
2677 mock_clean_saved_logs();
2679 /* Now try again, with a compressed object that starts out good and turns to
2680 junk. */
2681 crypto_rand(input, sizeof(input));
2682 r = tor_compress(&result, &szr, input, sizeof(input), method);
2683 tt_int_op(r, OP_EQ, 0);
2684 crypto_rand(result+szr/2, szr-(szr/2)); // trash the 2nd half of the result
2685 r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2686 tt_int_op(r, OP_EQ, -1);
2687 expect_log_msg_containing("Error while uncompressing data: bad input?");
2689 done:
2690 teardown_capture_of_logs();
2691 tor_free(result);
2692 tor_free(result2);
2695 static void
2696 test_util_decompress_junk(void *arg)
2698 const char *methodname = arg;
2699 tt_assert(methodname);
2701 compress_method_t method = compression_method_get_by_name(methodname);
2702 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2703 if (! tor_compress_supports_method(method)) {
2704 tt_skip();
2707 test_util_decompress_junk_impl(method);
2708 done:
2712 /* mock replacement for tor_compress_is_compression_bomb that doesn't
2713 * believe in compression bombs. */
2714 static int
2715 mock_is_never_compression_bomb(size_t in, size_t out)
2717 (void)in;
2718 (void) out;
2719 return 0;
2722 static void
2723 test_util_decompress_dos_impl(compress_method_t method)
2725 char *input;
2726 char *result = NULL, *result2 = NULL;
2727 size_t szr, szr2;
2728 int r;
2730 const size_t big = 1024*1024;
2731 /* one megabyte of 0s. */
2732 input = tor_malloc_zero(big);
2734 /* Compress it into "result": it should fail. */
2735 setup_full_capture_of_logs(LOG_WARN);
2736 r = tor_compress(&result, &szr, input, big, method);
2737 tt_int_op(r, OP_EQ, -1);
2738 expect_log_msg_containing(
2739 "other Tors would think this was a compression bomb");
2740 teardown_capture_of_logs();
2742 /* Try again, but this time suppress compression-bomb detection */
2743 MOCK(tor_compress_is_compression_bomb, mock_is_never_compression_bomb);
2744 r = tor_compress(&result, &szr, input, big, method);
2745 UNMOCK(tor_compress_is_compression_bomb);
2746 tt_int_op(r, OP_EQ, 0);
2747 tt_ptr_op(result, OP_NE, NULL);
2749 /* We should refuse to uncomrpess it again, since it looks like a
2750 * compression bomb. */
2751 setup_capture_of_logs(LOG_WARN);
2752 r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2753 tt_int_op(r, OP_EQ, -1);
2754 expect_log_msg_containing("bomb; abandoning stream");
2756 done:
2757 teardown_capture_of_logs();
2758 tor_free(input);
2759 tor_free(result);
2760 tor_free(result2);
2763 static void
2764 test_util_decompress_dos(void *arg)
2766 const char *methodname = arg;
2767 tt_assert(methodname);
2769 compress_method_t method = compression_method_get_by_name(methodname);
2770 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2771 if (! tor_compress_supports_method(method)) {
2772 tt_skip();
2775 test_util_decompress_dos_impl(method);
2776 done:
2780 static void
2781 test_util_gzip_compression_bomb(void *arg)
2783 /* A 'compression bomb' is a very small object that uncompresses to a huge
2784 * one. Most compression formats support them, but they can be a DOS vector.
2785 * In Tor we try not to generate them, and we don't accept them.
2787 (void) arg;
2788 size_t one_million = 1<<20;
2789 char *one_mb = tor_malloc_zero(one_million);
2790 char *result = NULL;
2791 size_t result_len = 0;
2792 tor_compress_state_t *state = NULL;
2794 /* Make sure we can't produce a compression bomb */
2795 setup_full_capture_of_logs(LOG_WARN);
2796 tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
2797 one_mb, one_million,
2798 ZLIB_METHOD));
2799 expect_single_log_msg_containing(
2800 "We compressed something and got an insanely high "
2801 "compression factor; other Tors would think this "
2802 "was a compression bomb.");
2803 teardown_capture_of_logs();
2805 /* Here's a compression bomb that we made manually. */
2806 const char compression_bomb[1039] =
2807 { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
2808 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
2809 tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
2810 compression_bomb, 1039,
2811 ZLIB_METHOD, 0, LOG_WARN));
2813 /* Now try streaming that. */
2814 state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
2815 tor_compress_output_t r;
2816 const char *inp = compression_bomb;
2817 size_t inlen = 1039;
2818 do {
2819 char *outp = one_mb;
2820 size_t outleft = 4096; /* small on purpose */
2821 r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
2822 tt_int_op(inlen, OP_NE, 0);
2823 } while (r == TOR_COMPRESS_BUFFER_FULL);
2825 tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
2827 done:
2828 tor_free(one_mb);
2829 tor_compress_free(state);
2832 /** Run unit tests for mmap() wrapper functionality. */
2833 static void
2834 test_util_mmap(void *arg)
2836 char *fname1 = tor_strdup(get_fname("mapped_1"));
2837 char *fname2 = tor_strdup(get_fname("mapped_2"));
2838 char *fname3 = tor_strdup(get_fname("mapped_3"));
2839 const size_t buflen = 17000;
2840 char *buf = tor_malloc(17000);
2841 tor_mmap_t *mapping = NULL;
2843 (void)arg;
2844 crypto_rand(buf, buflen);
2846 mapping = tor_mmap_file(fname1);
2847 tt_ptr_op(mapping, OP_EQ, NULL);
2849 write_str_to_file(fname1, "Short file.", 1);
2851 mapping = tor_mmap_file(fname1);
2852 tt_assert(mapping);
2853 tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
2854 tt_str_op(mapping->data,OP_EQ, "Short file.");
2855 #ifdef _WIN32
2856 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2857 mapping = NULL;
2858 tt_assert(unlink(fname1) == 0);
2859 #else
2860 /* make sure we can unlink. */
2861 tt_assert(unlink(fname1) == 0);
2862 tt_str_op(mapping->data,OP_EQ, "Short file.");
2863 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2864 mapping = NULL;
2865 #endif /* defined(_WIN32) */
2867 /* Now a zero-length file. */
2868 write_str_to_file(fname1, "", 1);
2869 mapping = tor_mmap_file(fname1);
2870 tt_ptr_op(mapping,OP_EQ, NULL);
2871 tt_int_op(ERANGE,OP_EQ, errno);
2872 unlink(fname1);
2874 /* Make sure that we fail to map a no-longer-existent file. */
2875 mapping = tor_mmap_file(fname1);
2876 tt_ptr_op(mapping, OP_EQ, NULL);
2878 /* Now try a big file that stretches across a few pages and isn't aligned */
2879 write_bytes_to_file(fname2, buf, buflen, 1);
2880 mapping = tor_mmap_file(fname2);
2881 tt_assert(mapping);
2882 tt_int_op(mapping->size,OP_EQ, buflen);
2883 tt_mem_op(mapping->data,OP_EQ, buf, buflen);
2884 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2885 mapping = NULL;
2887 /* Now try a big aligned file. */
2888 write_bytes_to_file(fname3, buf, 16384, 1);
2889 mapping = tor_mmap_file(fname3);
2890 tt_assert(mapping);
2891 tt_int_op(mapping->size,OP_EQ, 16384);
2892 tt_mem_op(mapping->data,OP_EQ, buf, 16384);
2893 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2894 mapping = NULL;
2896 done:
2897 unlink(fname1);
2898 unlink(fname2);
2899 unlink(fname3);
2901 tor_free(fname1);
2902 tor_free(fname2);
2903 tor_free(fname3);
2904 tor_free(buf);
2906 tor_munmap_file(mapping);
2909 /** Run unit tests for escaping/unescaping data for use by controllers. */
2910 static void
2911 test_util_control_formats(void *arg)
2913 char *out = NULL;
2914 const char *inp =
2915 "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
2916 size_t sz;
2918 (void)arg;
2919 sz = read_escaped_data(inp, strlen(inp), &out);
2920 tt_str_op(out,OP_EQ,
2921 ".This is a test\nof the emergency \n.system.\n\rZ.\n");
2922 tt_int_op(sz,OP_EQ, strlen(out));
2924 done:
2925 tor_free(out);
2928 #define test_feq(value1,value2) do { \
2929 double v1 = (value1), v2=(value2); \
2930 double tf_diff = v1-v2; \
2931 double tf_tolerance = ((v1+v2)/2.0)/1e8; \
2932 if (tf_diff<0) tf_diff=-tf_diff; \
2933 if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
2934 if (tf_diff<tf_tolerance) { \
2935 TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
2936 } else { \
2937 TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
2939 } while (0)
2941 static void
2942 test_util_sscanf(void *arg)
2944 unsigned u1, u2, u3;
2945 unsigned long ulng;
2946 char s1[20], s2[10], s3[10], ch, *huge = NULL;
2947 int r;
2948 long lng1,lng2;
2949 int int1, int2;
2950 double d1,d2,d3,d4;
2952 /* Simple tests (malformed patterns, literal matching, ...) */
2953 (void)arg;
2954 tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
2955 tt_int_op(-1,OP_EQ,
2956 tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
2957 tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
2958 /* this will fail because we don't allow widths longer than 9999 */
2960 huge = tor_malloc(1000000);
2961 r = tor_sscanf("prettylongstring", "%99999s", huge);
2962 tor_free(huge);
2963 tt_int_op(-1,OP_EQ, r);
2965 #if 0
2966 /* GCC thinks these two are illegal. */
2967 test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
2968 test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
2969 #endif
2970 /* No '%'-strings: always "success" */
2971 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
2972 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
2973 /* Excess data */
2974 tt_int_op(0,OP_EQ,
2975 tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
2976 tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
2977 tt_int_op(0,OP_EQ,
2978 tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
2979 tt_int_op(1,OP_EQ,
2980 tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
2982 /* Numbers (ie. %u) */
2983 tt_int_op(0,OP_EQ,
2984 tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
2985 tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
2986 tt_int_op(12345u,OP_EQ, u1);
2987 tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
2988 tt_int_op(12346u,OP_EQ, u1);
2989 tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
2990 tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
2991 tt_int_op(12348u,OP_EQ, u1);
2992 tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
2993 tt_int_op(0u,OP_EQ, u1);
2994 tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
2995 tt_int_op(0u,OP_EQ, u2);
2996 tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
2997 tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
2998 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
3000 /* Numbers with size (eg. %2u) */
3001 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
3002 tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
3003 tt_int_op(12u,OP_EQ, u1);
3004 tt_int_op(3456u,OP_EQ, u2);
3005 tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
3006 tt_int_op(123456u,OP_EQ, u1);
3007 tt_int_op(1,OP_EQ, tor_sscanf("123457 ", "%8u", &u1));
3008 tt_int_op(123457u,OP_EQ, u1);
3009 tt_int_op(0,OP_EQ, tor_sscanf(" 123456", "%8u", &u1));
3010 tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
3011 tt_int_op(12u,OP_EQ, u1);
3012 tt_int_op(3u,OP_EQ, u2);
3013 tt_int_op(456u,OP_EQ, u3);
3014 tt_int_op(3,OP_EQ,
3015 tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
3016 tt_int_op(67u,OP_EQ, u1);
3017 tt_int_op(8u,OP_EQ, u2);
3018 tt_int_op(99u,OP_EQ, u3);
3019 /* %u does not match space.*/
3020 tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
3021 tt_int_op(12u,OP_EQ, u1);
3022 tt_int_op(3u,OP_EQ, u2);
3023 /* %u does not match negative numbers. */
3024 tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
3025 tt_int_op(67u,OP_EQ, u1);
3026 tt_int_op(8u,OP_EQ, u2);
3027 /* Arbitrary amounts of 0-padding are okay */
3028 tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
3029 &u1, &u2, &u3));
3030 tt_int_op(12u,OP_EQ, u1);
3031 tt_int_op(3u,OP_EQ, u2);
3032 tt_int_op(99u,OP_EQ, u3);
3034 /* Hex (ie. %x) */
3035 tt_int_op(3,OP_EQ,
3036 tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
3037 tt_int_op(0x1234,OP_EQ, u1);
3038 tt_int_op(0x2ABCDEF,OP_EQ, u2);
3039 tt_int_op(0xFF,OP_EQ, u3);
3040 /* Width works on %x */
3041 tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
3042 tt_int_op(0xf00d,OP_EQ, u1);
3043 tt_int_op(0xcafe,OP_EQ, u2);
3044 tt_int_op(444,OP_EQ, u3);
3046 /* Literal '%' (ie. '%%') */
3047 tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
3048 tt_int_op(99,OP_EQ, u1);
3049 tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
3050 tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
3051 tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
3052 tt_int_op(99,OP_EQ, u1);
3053 tt_str_op(s1,OP_EQ, "fresh");
3054 tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
3055 tt_str_op("boo",OP_EQ, s1);
3057 /* Strings (ie. %s) */
3058 tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
3059 tt_str_op(s1,OP_EQ, "hel");
3060 tt_str_op(s2,OP_EQ, "lo");
3061 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
3062 tt_str_op(s3,OP_EQ, "WD");
3063 tt_int_op(40,OP_EQ, u1);
3064 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
3065 tt_str_op(s3,OP_EQ, "WD4");
3066 tt_int_op(0,OP_EQ, u1);
3067 tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
3068 tt_int_op(76,OP_EQ, u1);
3069 tt_str_op(s1,OP_EQ, "trombones");
3071 huge = tor_malloc(1000);
3072 r = tor_sscanf("prettylongstring", "%999s", huge);
3073 tt_int_op(1,OP_EQ, r);
3074 tt_str_op(huge,OP_EQ, "prettylongstring");
3075 tor_free(huge);
3077 /* %s doesn't eat spaces */
3078 tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
3079 tt_str_op(s1,OP_EQ, "hello");
3080 tt_str_op(s2,OP_EQ, "world");
3081 tt_int_op(2,OP_EQ, tor_sscanf("bye world?", "%9s %9s", s1, s2));
3082 tt_str_op(s1,OP_EQ, "bye");
3083 tt_str_op(s2,OP_EQ, "");
3084 tt_int_op(3,OP_EQ,
3085 tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
3086 tt_str_op(s1,OP_EQ, "hi");
3087 tt_str_op(s2,OP_EQ, "");
3088 tt_str_op(s3,OP_EQ, "");
3090 tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3091 tt_int_op(4,OP_EQ,
3092 tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3093 tt_int_op(' ',OP_EQ, ch);
3095 r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
3096 tt_int_op(r,OP_EQ, 3);
3097 tt_int_op(int1,OP_EQ, 12345);
3098 tt_int_op(lng1,OP_EQ, -67890);
3099 tt_int_op(int2,OP_EQ, -1);
3101 #if SIZEOF_INT == 4
3102 /* %u */
3103 /* UINT32_MAX should work */
3104 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
3105 tt_int_op(4294967295U,OP_EQ, u1);
3107 /* But UINT32_MAX + 1 shouldn't work */
3108 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
3109 /* but parsing only 9... */
3110 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
3111 tt_int_op(429496729U,OP_EQ, u1);
3113 /* %x */
3114 /* UINT32_MAX should work */
3115 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
3116 tt_int_op(0xFFFFFFFF,OP_EQ, u1);
3118 /* But UINT32_MAX + 1 shouldn't work */
3119 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
3121 /* %d */
3122 /* INT32_MIN and INT32_MAX should work */
3123 r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
3124 tt_int_op(r,OP_EQ, 2);
3125 tt_int_op(int1,OP_EQ, -2147483647 - 1);
3126 tt_int_op(int2,OP_EQ, 2147483647);
3128 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3129 r = tor_sscanf("-2147483649.", "%d.", &int1);
3130 tt_int_op(r,OP_EQ, 0);
3132 r = tor_sscanf("2147483648.", "%d.", &int1);
3133 tt_int_op(r,OP_EQ, 0);
3135 /* and the first failure stops further processing */
3136 r = tor_sscanf("-2147483648. 2147483648.",
3137 "%d. %d.", &int1, &int2);
3138 tt_int_op(r,OP_EQ, 1);
3140 r = tor_sscanf("-2147483649. 2147483647.",
3141 "%d. %d.", &int1, &int2);
3142 tt_int_op(r,OP_EQ, 0);
3144 r = tor_sscanf("2147483648. -2147483649.",
3145 "%d. %d.", &int1, &int2);
3146 tt_int_op(r,OP_EQ, 0);
3147 #elif SIZEOF_INT == 8
3148 /* %u */
3149 /* UINT64_MAX should work */
3150 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
3151 tt_int_op(18446744073709551615U,OP_EQ, u1);
3153 /* But UINT64_MAX + 1 shouldn't work */
3154 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
3155 /* but parsing only 19... */
3156 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
3157 tt_int_op(1844674407370955161U,OP_EQ, u1);
3159 /* %x */
3160 /* UINT64_MAX should work */
3161 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
3162 tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
3164 /* But UINT64_MAX + 1 shouldn't work */
3165 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
3167 /* %d */
3168 /* INT64_MIN and INT64_MAX should work */
3169 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3170 "%d. %d.", &int1, &int2);
3171 tt_int_op(r,OP_EQ, 2);
3172 tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
3173 tt_int_op(int2,OP_EQ, 9223372036854775807);
3175 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3176 r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
3177 tt_int_op(r,OP_EQ, 0);
3179 r = tor_sscanf("9223372036854775808.", "%d.", &int1);
3180 tt_int_op(r,OP_EQ, 0);
3182 /* and the first failure stops further processing */
3183 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3184 "%d. %d.", &int1, &int2);
3185 tt_int_op(r,OP_EQ, 1);
3187 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3188 "%d. %d.", &int1, &int2);
3189 tt_int_op(r,OP_EQ, 0);
3191 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3192 "%d. %d.", &int1, &int2);
3193 tt_int_op(r,OP_EQ, 0);
3194 #endif /* SIZEOF_INT == 4 || ... */
3196 #if SIZEOF_LONG == 4
3197 /* %lu */
3198 /* UINT32_MAX should work */
3199 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
3200 tt_int_op(4294967295UL,OP_EQ, ulng);
3202 /* But UINT32_MAX + 1 shouldn't work */
3203 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
3204 /* but parsing only 9... */
3205 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
3206 tt_int_op(429496729UL,OP_EQ, ulng);
3208 /* %lx */
3209 /* UINT32_MAX should work */
3210 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
3211 tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
3213 /* But UINT32_MAX + 1 shouldn't work */
3214 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
3216 /* %ld */
3217 /* INT32_MIN and INT32_MAX should work */
3218 r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
3219 tt_int_op(r,OP_EQ, 2);
3220 tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
3221 tt_int_op(lng2,OP_EQ, 2147483647L);
3223 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3224 r = tor_sscanf("-2147483649.", "%ld.", &lng1);
3225 tt_int_op(r,OP_EQ, 0);
3227 r = tor_sscanf("2147483648.", "%ld.", &lng1);
3228 tt_int_op(r,OP_EQ, 0);
3230 /* and the first failure stops further processing */
3231 r = tor_sscanf("-2147483648. 2147483648.",
3232 "%ld. %ld.", &lng1, &lng2);
3233 tt_int_op(r,OP_EQ, 1);
3235 r = tor_sscanf("-2147483649. 2147483647.",
3236 "%ld. %ld.", &lng1, &lng2);
3237 tt_int_op(r,OP_EQ, 0);
3239 r = tor_sscanf("2147483648. -2147483649.",
3240 "%ld. %ld.", &lng1, &lng2);
3241 tt_int_op(r,OP_EQ, 0);
3242 #elif SIZEOF_LONG == 8
3243 /* %lu */
3244 /* UINT64_MAX should work */
3245 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
3246 tt_int_op(18446744073709551615UL,OP_EQ, ulng);
3248 /* But UINT64_MAX + 1 shouldn't work */
3249 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
3250 /* but parsing only 19... */
3251 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
3252 tt_int_op(1844674407370955161UL,OP_EQ, ulng);
3254 /* %lx */
3255 /* UINT64_MAX should work */
3256 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
3257 tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
3259 /* But UINT64_MAX + 1 shouldn't work */
3260 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
3262 /* %ld */
3263 /* INT64_MIN and INT64_MAX should work */
3264 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3265 "%ld. %ld.", &lng1, &lng2);
3266 tt_int_op(r,OP_EQ, 2);
3267 tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
3268 tt_int_op(lng2,OP_EQ, 9223372036854775807L);
3270 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3271 r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
3272 tt_int_op(r,OP_EQ, 0);
3274 r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
3275 tt_int_op(r,OP_EQ, 0);
3277 /* and the first failure stops further processing */
3278 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3279 "%ld. %ld.", &lng1, &lng2);
3280 tt_int_op(r,OP_EQ, 1);
3282 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3283 "%ld. %ld.", &lng1, &lng2);
3284 tt_int_op(r,OP_EQ, 0);
3286 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3287 "%ld. %ld.", &lng1, &lng2);
3288 tt_int_op(r,OP_EQ, 0);
3289 #endif /* SIZEOF_LONG == 4 || ... */
3291 r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
3292 "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
3293 tt_int_op(r,OP_EQ, 4);
3294 test_feq(d1, 123.456);
3295 test_feq(d2, .000007);
3296 test_feq(d3, -900123123.2000787);
3297 test_feq(d4, 3.2);
3299 /* missing float */
3300 r = tor_sscanf("3 ", "%d %lf", &int1, &d1);
3301 tt_int_op(r, OP_EQ, 1);
3302 tt_int_op(int1, OP_EQ, 3);
3304 /* not a float */
3305 r = tor_sscanf("999 notafloat", "%d %lf", &int1, &d1);
3306 tt_int_op(r, OP_EQ, 1);
3307 tt_int_op(int1, OP_EQ, 999);
3309 /* %s but no buffer. */
3310 char *nullbuf = NULL;
3311 r = tor_sscanf("hello", "%3s", nullbuf);
3312 tt_int_op(r, OP_EQ, 0);
3314 done:
3315 tor_free(huge);
3318 #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
3319 #define tt_ci_char_op(a,op,b) \
3320 tt_char_op(TOR_TOLOWER((int)a),op,TOR_TOLOWER((int)b))
3322 #ifndef HAVE_STRNLEN
3323 static size_t
3324 strnlen(const char *s, size_t len)
3326 const char *p = memchr(s, 0, len);
3327 if (!p)
3328 return len;
3329 return p - s;
3331 #endif /* !defined(HAVE_STRNLEN) */
3333 static void
3334 test_util_format_time_interval(void *arg)
3336 /* use the same sized buffer and integers as tor uses */
3337 #define DBUF_SIZE 64
3338 char dbuf[DBUF_SIZE];
3339 #define T_ "%ld"
3340 long sec, min, hour, day;
3342 /* we don't care about the exact spelling of the
3343 * second(s), minute(s), hour(s), day(s) labels */
3344 #define LABEL_SIZE 21
3345 #define L_ "%20s"
3346 char label_s[LABEL_SIZE];
3347 char label_m[LABEL_SIZE];
3348 char label_h[LABEL_SIZE];
3349 char label_d[LABEL_SIZE];
3351 #define TL_ T_ " " L_
3353 int r;
3355 (void)arg;
3357 /* In these tests, we're not picky about
3358 * spelling or abbreviations */
3360 /* seconds: 0, 1, 9, 10, 59 */
3362 /* ignore exact spelling of "second(s)"*/
3363 format_time_interval(dbuf, sizeof(dbuf), 0);
3364 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3365 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3366 tt_int_op(r,OP_EQ, 2);
3367 tt_ci_char_op(label_s[0],OP_EQ, 's');
3368 tt_int_op(sec,OP_EQ, 0);
3370 format_time_interval(dbuf, sizeof(dbuf), 1);
3371 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3372 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3373 tt_int_op(r,OP_EQ, 2);
3374 tt_ci_char_op(label_s[0],OP_EQ, 's');
3375 tt_int_op(sec,OP_EQ, 1);
3377 format_time_interval(dbuf, sizeof(dbuf), 10);
3378 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3379 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3380 tt_int_op(r,OP_EQ, 2);
3381 tt_ci_char_op(label_s[0],OP_EQ, 's');
3382 tt_int_op(sec,OP_EQ, 10);
3384 format_time_interval(dbuf, sizeof(dbuf), 59);
3385 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3386 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3387 tt_int_op(r,OP_EQ, 2);
3388 tt_ci_char_op(label_s[0],OP_EQ, 's');
3389 tt_int_op(sec,OP_EQ, 59);
3391 /* negative seconds are reported as their absolute value */
3393 format_time_interval(dbuf, sizeof(dbuf), -4);
3394 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3395 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3396 tt_int_op(r,OP_EQ, 2);
3397 tt_ci_char_op(label_s[0],OP_EQ, 's');
3398 tt_int_op(sec,OP_EQ, 4);
3399 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3401 format_time_interval(dbuf, sizeof(dbuf), -32);
3402 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3403 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3404 tt_int_op(r,OP_EQ, 2);
3405 tt_ci_char_op(label_s[0],OP_EQ, 's');
3406 tt_int_op(sec,OP_EQ, 32);
3407 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3409 /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
3411 /* ignore trailing "0 second(s)", if present */
3412 format_time_interval(dbuf, sizeof(dbuf), 60);
3413 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3414 r = tor_sscanf(dbuf, TL_, &min, label_m);
3415 tt_int_op(r,OP_EQ, 2);
3416 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3417 tt_int_op(min,OP_EQ, 1);
3418 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3420 /* ignore exact spelling of "minute(s)," and "second(s)" */
3421 format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
3422 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3423 r = tor_sscanf(dbuf, TL_ " " TL_,
3424 &min, label_m, &sec, label_s);
3425 tt_int_op(r,OP_EQ, 4);
3426 tt_int_op(min,OP_EQ, 1);
3427 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3428 tt_int_op(sec,OP_EQ, 1);
3429 tt_ci_char_op(label_s[0],OP_EQ, 's');
3430 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3432 format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
3433 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3434 r = tor_sscanf(dbuf, TL_ " " TL_,
3435 &min, label_m, &sec, label_s);
3436 tt_int_op(r,OP_EQ, 4);
3437 tt_int_op(min,OP_EQ, 1);
3438 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3439 tt_int_op(sec,OP_EQ, 59);
3440 tt_ci_char_op(label_s[0],OP_EQ, 's');
3442 /* ignore trailing "0 second(s)", if present */
3443 format_time_interval(dbuf, sizeof(dbuf), 60*2);
3444 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3445 r = tor_sscanf(dbuf, TL_, &min, label_m);
3446 tt_int_op(r,OP_EQ, 2);
3447 tt_int_op(min,OP_EQ, 2);
3448 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3450 /* ignore exact spelling of "minute(s)," and "second(s)" */
3451 format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
3452 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3453 r = tor_sscanf(dbuf, TL_ " " TL_,
3454 &min, label_m, &sec, label_s);
3455 tt_int_op(r,OP_EQ, 4);
3456 tt_int_op(min,OP_EQ, 2);
3457 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3458 tt_int_op(sec,OP_EQ, 1);
3459 tt_ci_char_op(label_s[0],OP_EQ, 's');
3461 format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
3462 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3463 r = tor_sscanf(dbuf, TL_ " " TL_,
3464 &min, label_m, &sec, label_s);
3465 tt_int_op(r,OP_EQ, 4);
3466 tt_int_op(min,OP_EQ, 59);
3467 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3468 tt_int_op(sec,OP_EQ, 59);
3469 tt_ci_char_op(label_s[0],OP_EQ, 's');
3471 /* negative minutes are reported as their absolute value */
3473 /* ignore trailing "0 second(s)", if present */
3474 format_time_interval(dbuf, sizeof(dbuf), -3*60);
3475 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3476 r = tor_sscanf(dbuf, TL_, &min, label_m);
3477 tt_int_op(r,OP_EQ, 2);
3478 tt_int_op(min,OP_EQ, 3);
3479 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3481 /* ignore exact spelling of "minute(s)," and "second(s)" */
3482 format_time_interval(dbuf, sizeof(dbuf), -96);
3483 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3484 r = tor_sscanf(dbuf, TL_ " " TL_,
3485 &min, label_m, &sec, label_s);
3486 tt_int_op(r,OP_EQ, 4);
3487 tt_int_op(min,OP_EQ, 1);
3488 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3489 tt_int_op(sec,OP_EQ, 36);
3490 tt_ci_char_op(label_s[0],OP_EQ, 's');
3492 format_time_interval(dbuf, sizeof(dbuf), -2815);
3493 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3494 r = tor_sscanf(dbuf, TL_ " " TL_,
3495 &min, label_m, &sec, label_s);
3496 tt_int_op(r,OP_EQ, 4);
3497 tt_int_op(min,OP_EQ, 46);
3498 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3499 tt_int_op(sec,OP_EQ, 55);
3500 tt_ci_char_op(label_s[0],OP_EQ, 's');
3502 /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
3503 /* always ignore trailing seconds, if present */
3505 /* ignore trailing "0 minute(s)" etc., if present */
3506 format_time_interval(dbuf, sizeof(dbuf), 60*60);
3507 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3508 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3509 tt_int_op(r,OP_EQ, 2);
3510 tt_int_op(hour,OP_EQ, 1);
3511 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3513 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
3514 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3515 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3516 tt_int_op(r,OP_EQ, 2);
3517 tt_int_op(hour,OP_EQ, 1);
3518 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3520 /* ignore exact spelling of "hour(s)," etc. */
3521 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
3522 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3523 r = tor_sscanf(dbuf, TL_ " " TL_,
3524 &hour, label_h, &min, label_m);
3525 tt_int_op(r,OP_EQ, 4);
3526 tt_int_op(hour,OP_EQ, 1);
3527 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3528 tt_int_op(min,OP_EQ, 1);
3529 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3531 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
3532 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3533 r = tor_sscanf(dbuf, TL_ " " TL_,
3534 &hour, label_h, &min, label_m);
3535 tt_int_op(r,OP_EQ, 4);
3536 tt_int_op(hour,OP_EQ, 23);
3537 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3538 tt_int_op(min,OP_EQ, 59);
3539 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3541 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
3542 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3543 r = tor_sscanf(dbuf, TL_ " " TL_,
3544 &hour, label_h, &min, label_m);
3545 tt_int_op(r,OP_EQ, 4);
3546 tt_int_op(hour,OP_EQ, 23);
3547 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3548 tt_int_op(min,OP_EQ, 59);
3549 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3551 /* negative hours are reported as their absolute value */
3553 /* ignore exact spelling of "hour(s)," etc., if present */
3554 format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
3555 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3556 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3557 tt_int_op(r,OP_EQ, 2);
3558 tt_int_op(hour,OP_EQ, 2);
3559 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3561 format_time_interval(dbuf, sizeof(dbuf), -75804);
3562 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3563 r = tor_sscanf(dbuf, TL_ " " TL_,
3564 &hour, label_h, &min, label_m);
3565 tt_int_op(r,OP_EQ, 4);
3566 tt_int_op(hour,OP_EQ, 21);
3567 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3568 tt_int_op(min,OP_EQ, 3);
3569 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3571 /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
3572 /* always ignore trailing seconds, if present */
3574 /* ignore trailing "0 hours(s)" etc., if present */
3575 format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
3576 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3577 r = tor_sscanf(dbuf, TL_, &day, label_d);
3578 tt_int_op(r,OP_EQ, 2);
3579 tt_int_op(day,OP_EQ, 1);
3580 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3582 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
3583 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3584 r = tor_sscanf(dbuf, TL_, &day, label_d);
3585 tt_int_op(r,OP_EQ, 2);
3586 tt_int_op(day,OP_EQ, 1);
3587 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3589 /* ignore exact spelling of "days(s)," etc. */
3590 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
3591 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3592 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3593 &day, label_d, &hour, label_h, &min, label_m);
3594 if (r == -1) {
3595 /* ignore 0 hours(s), if present */
3596 r = tor_sscanf(dbuf, TL_ " " TL_,
3597 &day, label_d, &min, label_m);
3599 tt_assert(r == 4 || r == 6);
3600 tt_int_op(day,OP_EQ, 1);
3601 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3602 if (r == 6) {
3603 tt_int_op(hour,OP_EQ, 0);
3604 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3606 tt_int_op(min,OP_EQ, 1);
3607 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3609 /* ignore trailing "0 minutes(s)" etc., if present */
3610 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
3611 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3612 r = tor_sscanf(dbuf, TL_ " " TL_,
3613 &day, label_d, &hour, label_h);
3614 tt_int_op(r,OP_EQ, 4);
3615 tt_int_op(day,OP_EQ, 1);
3616 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3617 tt_int_op(hour,OP_EQ, 1);
3618 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3620 /* negative days are reported as their absolute value */
3622 format_time_interval(dbuf, sizeof(dbuf), -21936184);
3623 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3624 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3625 &day, label_d, &hour, label_h, &min, label_m);
3626 tt_int_op(r,OP_EQ, 6);
3627 tt_int_op(day,OP_EQ, 253);
3628 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3629 tt_int_op(hour,OP_EQ, 21);
3630 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3631 tt_int_op(min,OP_EQ, 23);
3632 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3634 /* periods > 1 year are reported in days (warn?) */
3636 /* ignore exact spelling of "days(s)," etc., if present */
3637 format_time_interval(dbuf, sizeof(dbuf), 758635154);
3638 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3639 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3640 &day, label_d, &hour, label_h, &min, label_m);
3641 tt_int_op(r,OP_EQ, 6);
3642 tt_int_op(day,OP_EQ, 8780);
3643 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3644 tt_int_op(hour,OP_EQ, 11);
3645 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3646 tt_int_op(min,OP_EQ, 59);
3647 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3649 /* negative periods > 1 year are reported in days (warn?) */
3651 format_time_interval(dbuf, sizeof(dbuf), -1427014922);
3652 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3653 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3654 &day, label_d, &hour, label_h, &min, label_m);
3655 tt_int_op(r,OP_EQ, 6);
3656 tt_int_op(day,OP_EQ, 16516);
3657 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3658 tt_int_op(hour,OP_EQ, 9);
3659 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3660 tt_int_op(min,OP_EQ, 2);
3661 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3663 #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
3665 /* We can try INT32_MIN/MAX */
3666 /* Always ignore second(s) */
3668 /* INT32_MAX */
3669 format_time_interval(dbuf, sizeof(dbuf), 2147483647);
3670 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3671 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3672 &day, label_d, &hour, label_h, &min, label_m);
3673 tt_int_op(r,OP_EQ, 6);
3674 tt_int_op(day,OP_EQ, 24855);
3675 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3676 tt_int_op(hour,OP_EQ, 3);
3677 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3678 tt_int_op(min,OP_EQ, 14);
3679 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3680 /* and 7 seconds - ignored */
3682 /* INT32_MIN: check that we get the absolute value of interval,
3683 * which doesn't actually fit in int32_t.
3684 * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
3685 format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
3686 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3687 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3688 &day, label_d, &hour, label_h, &min, label_m);
3689 tt_int_op(r,OP_EQ, 6);
3690 tt_int_op(day,OP_EQ, 24855);
3691 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3692 tt_int_op(hour,OP_EQ, 3);
3693 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3694 tt_int_op(min,OP_EQ, 14);
3695 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3696 /* and 7 or 8 seconds - ignored */
3698 #endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */
3700 #if SIZEOF_LONG == 8
3702 /* We can try INT64_MIN/MAX */
3703 /* Always ignore second(s) */
3705 /* INT64_MAX */
3706 format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
3707 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3708 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3709 &day, label_d, &hour, label_h, &min, label_m);
3710 tt_int_op(r,OP_EQ, 6);
3711 tt_int_op(day,OP_EQ, 106751991167300L);
3712 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3713 tt_int_op(hour,OP_EQ, 15);
3714 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3715 tt_int_op(min,OP_EQ, 30);
3716 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3717 /* and 7 seconds - ignored */
3719 /* INT64_MIN: check that we get the absolute value of interval,
3720 * which doesn't actually fit in int64_t.
3721 * We expect INT64_MAX */
3722 format_time_interval(dbuf, sizeof(dbuf),
3723 -9223372036854775807L - 1L);
3724 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3725 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3726 &day, label_d, &hour, label_h, &min, label_m);
3727 tt_int_op(r,OP_EQ, 6);
3728 tt_int_op(day,OP_EQ, 106751991167300L);
3729 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3730 tt_int_op(hour,OP_EQ, 15);
3731 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3732 tt_int_op(min,OP_EQ, 30);
3733 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3734 /* and 7 or 8 seconds - ignored */
3736 #endif /* SIZEOF_LONG == 8 */
3738 done:
3742 #undef tt_char_op
3743 #undef tt_ci_char_op
3744 #undef DBUF_SIZE
3745 #undef T_
3746 #undef LABEL_SIZE
3747 #undef L_
3748 #undef TL_
3750 static void
3751 test_util_path_is_relative(void *arg)
3753 /* OS-independent tests */
3754 (void)arg;
3755 tt_int_op(1,OP_EQ, path_is_relative(""));
3756 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3757 tt_int_op(1,OP_EQ, path_is_relative("dir/"));
3758 tt_int_op(1,OP_EQ, path_is_relative("./dir"));
3759 tt_int_op(1,OP_EQ, path_is_relative("../dir"));
3761 tt_int_op(0,OP_EQ, path_is_relative("/"));
3762 tt_int_op(0,OP_EQ, path_is_relative("/dir"));
3763 tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
3765 /* Windows */
3766 #ifdef _WIN32
3767 /* I don't have Windows so I can't test this, hence the "#ifdef
3768 0". These are tests that look useful, so please try to get them
3769 running and uncomment if it all works as it should */
3770 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3771 tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
3772 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
3773 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
3774 tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
3776 tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
3777 tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
3778 tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
3779 #endif /* defined(_WIN32) */
3781 done:
3785 /** Run unittests for memory area allocator */
3786 static void
3787 test_util_memarea(void *arg)
3789 memarea_t *area = memarea_new();
3790 char *p1, *p2, *p3, *p1_orig;
3791 void *malloced_ptr = NULL;
3792 int i;
3794 #ifdef DISABLE_MEMORY_SENTINELS
3795 /* If memory sentinels are disabled, this whole module is just an alias for
3796 malloc(), which is free to lay out memory most any way it wants. */
3797 if (1)
3798 tt_skip();
3799 #endif /* defined(DISABLE_MEMORY_SENTINELS) */
3801 (void)arg;
3802 tt_assert(area);
3804 p1_orig = p1 = memarea_alloc(area,64);
3805 p2 = memarea_alloc_zero(area,52);
3806 p3 = memarea_alloc(area,11);
3808 tt_assert(memarea_owns_ptr(area, p1));
3809 tt_assert(memarea_owns_ptr(area, p2));
3810 tt_assert(memarea_owns_ptr(area, p3));
3811 /* Make sure we left enough space. */
3812 tt_assert(p1+64 <= p2);
3813 tt_assert(p2+52 <= p3);
3814 /* Make sure we aligned. */
3815 tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
3816 tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
3817 tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
3818 tt_assert(!memarea_owns_ptr(area, p3+8192));
3819 tt_assert(!memarea_owns_ptr(area, p3+30));
3820 tt_assert(tor_mem_is_zero(p2, 52));
3821 /* Make sure we don't overalign. */
3822 p1 = memarea_alloc(area, 1);
3823 p2 = memarea_alloc(area, 1);
3824 tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
3826 malloced_ptr = tor_malloc(64);
3827 tt_assert(!memarea_owns_ptr(area, malloced_ptr));
3828 tor_free(malloced_ptr);
3831 /* memarea_memdup */
3833 malloced_ptr = tor_malloc(64);
3834 crypto_rand((char*)malloced_ptr, 64);
3835 p1 = memarea_memdup(area, malloced_ptr, 64);
3836 tt_assert(p1 != malloced_ptr);
3837 tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
3838 tor_free(malloced_ptr);
3841 /* memarea_strdup. */
3842 p1 = memarea_strdup(area,"");
3843 p2 = memarea_strdup(area, "abcd");
3844 tt_assert(p1);
3845 tt_assert(p2);
3846 tt_str_op(p1,OP_EQ, "");
3847 tt_str_op(p2,OP_EQ, "abcd");
3849 /* memarea_strndup. */
3851 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
3852 /* (From Turandot, act 3.) */
3853 size_t len = strlen(s);
3854 p1 = memarea_strndup(area, s, 1000);
3855 p2 = memarea_strndup(area, s, 10);
3856 tt_str_op(p1,OP_EQ, s);
3857 tt_assert(p2 >= p1 + len + 1);
3858 tt_mem_op(s,OP_EQ, p2, 10);
3859 tt_int_op(p2[10],OP_EQ, '\0');
3860 p3 = memarea_strndup(area, s, len);
3861 tt_str_op(p3,OP_EQ, s);
3862 p3 = memarea_strndup(area, s, len-1);
3863 tt_mem_op(s,OP_EQ, p3, len-1);
3864 tt_int_op(p3[len-1],OP_EQ, '\0');
3867 memarea_clear(area);
3868 p1 = memarea_alloc(area, 1);
3869 tt_ptr_op(p1,OP_EQ, p1_orig);
3870 memarea_clear(area);
3871 size_t total = 0, initial_allocation, allocation2, dummy;
3872 memarea_get_stats(area, &initial_allocation, &dummy);
3874 /* Check for running over an area's size. */
3875 for (i = 0; i < 4096; ++i) {
3876 size_t n = crypto_rand_int(6);
3877 p1 = memarea_alloc(area, n);
3878 total += n;
3879 tt_assert(memarea_owns_ptr(area, p1));
3881 memarea_assert_ok(area);
3882 memarea_get_stats(area, &allocation2, &dummy);
3883 /* Make sure we can allocate a too-big object. */
3884 p1 = memarea_alloc_zero(area, 9000);
3885 p2 = memarea_alloc_zero(area, 16);
3886 total += 9000;
3887 total += 16;
3888 tt_assert(memarea_owns_ptr(area, p1));
3889 tt_assert(memarea_owns_ptr(area, p2));
3891 /* Now test stats... */
3892 size_t allocated = 0, used = 0;
3893 memarea_get_stats(area, &allocated, &used);
3894 tt_int_op(used, OP_LE, allocated);
3895 tt_int_op(used, OP_GE, total); /* not EQ, because of alignment and headers*/
3896 tt_int_op(allocated, OP_GT, allocation2);
3898 tt_int_op(allocation2, OP_GT, initial_allocation);
3900 memarea_clear(area);
3901 memarea_get_stats(area, &allocated, &used);
3902 tt_int_op(used, OP_LT, 128); /* Not 0, because of header */
3903 tt_int_op(allocated, OP_EQ, initial_allocation);
3905 done:
3906 memarea_drop_all(area);
3907 tor_free(malloced_ptr);
3910 /** Run unit tests for utility functions to get file names relative to
3911 * the data directory. */
3912 static void
3913 test_util_datadir(void *arg)
3915 char buf[1024];
3916 char *f = NULL;
3917 char *temp_dir = NULL;
3919 (void)arg;
3920 temp_dir = get_datadir_fname(NULL);
3921 f = get_datadir_fname("state");
3922 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
3923 tt_str_op(f,OP_EQ, buf);
3924 tor_free(f);
3925 f = get_datadir_fname2("cache", "thingy");
3926 tor_snprintf(buf, sizeof(buf),
3927 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
3928 tt_str_op(f,OP_EQ, buf);
3929 tor_free(f);
3930 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
3931 tor_snprintf(buf, sizeof(buf),
3932 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
3933 tt_str_op(f,OP_EQ, buf);
3934 tor_free(f);
3935 f = get_datadir_fname_suffix("cache", ".foo");
3936 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
3937 temp_dir);
3938 tt_str_op(f,OP_EQ, buf);
3940 done:
3941 tor_free(f);
3942 tor_free(temp_dir);
3945 static void
3946 test_util_strtok(void *arg)
3948 char buf[128];
3949 char buf2[128];
3950 int i;
3951 char *cp1, *cp2;
3953 (void)arg;
3954 for (i = 0; i < 3; i++) {
3955 const char *pad1="", *pad2="";
3956 switch (i) {
3957 case 0:
3958 break;
3959 case 1:
3960 pad1 = " ";
3961 pad2 = "!";
3962 break;
3963 case 2:
3964 pad1 = " ";
3965 pad2 = ";!";
3966 break;
3968 tor_snprintf(buf, sizeof(buf), "%s", pad1);
3969 tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
3970 tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL);
3971 tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL);
3973 tor_snprintf(buf, sizeof(buf),
3974 "%sGraved on the dark in gestures of descent%s", pad1, pad1);
3975 tor_snprintf(buf2, sizeof(buf2),
3976 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
3977 /* -- "Year's End", Richard Wilbur */
3979 tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3980 tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
3981 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
3982 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
3983 tt_str_op("on",OP_EQ, S1());
3984 tt_str_op("the",OP_EQ, S1());
3985 tt_str_op("dark",OP_EQ, S1());
3986 tt_str_op("seemed",OP_EQ, S2());
3987 tt_str_op("their",OP_EQ, S2());
3988 tt_str_op("own",OP_EQ, S2());
3989 tt_str_op("in",OP_EQ, S1());
3990 tt_str_op("gestures",OP_EQ, S1());
3991 tt_str_op("of",OP_EQ, S1());
3992 tt_str_op("most",OP_EQ, S2());
3993 tt_str_op("perfect",OP_EQ, S2());
3994 tt_str_op("descent",OP_EQ, S1());
3995 tt_str_op("monument",OP_EQ, S2());
3996 tt_ptr_op(NULL,OP_EQ, S1());
3997 tt_ptr_op(NULL,OP_EQ, S2());
4000 buf[0] = 0;
4001 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4002 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
4004 strlcpy(buf, "Howdy!", sizeof(buf));
4005 tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
4006 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
4008 strlcpy(buf, " ", sizeof(buf));
4009 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4010 strlcpy(buf, " ", sizeof(buf));
4011 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4013 strlcpy(buf, "something ", sizeof(buf));
4014 tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4015 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
4016 done:
4020 static void
4021 test_util_find_str_at_start_of_line(void *ptr)
4023 const char *long_string =
4024 "howdy world. how are you? i hope it's fine.\n"
4025 "hello kitty\n"
4026 "third line";
4027 char *line2 = strchr(long_string,'\n')+1;
4028 char *line3 = strchr(line2,'\n')+1;
4029 const char *short_string = "hello kitty\n"
4030 "second line\n";
4031 char *short_line2 = strchr(short_string,'\n')+1;
4033 (void)ptr;
4035 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
4036 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
4037 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
4038 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
4039 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
4040 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
4041 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
4042 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
4043 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
4044 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
4045 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
4046 tt_ptr_op(line2,OP_EQ,
4047 find_str_at_start_of_line(long_string, "hello kitty\n"));
4048 tt_ptr_op(line2,OP_EQ,
4049 find_str_at_start_of_line(long_string, "hello kitty\nt"));
4050 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
4051 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
4052 tt_ptr_op(NULL, OP_EQ,
4053 find_str_at_start_of_line(long_string, "third line\n"));
4054 tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
4055 "second line\n"));
4056 done:
4060 static void
4061 test_util_string_is_C_identifier(void *ptr)
4063 (void)ptr;
4065 tt_int_op(1,OP_EQ, string_is_C_identifier("string_is_C_identifier"));
4066 tt_int_op(1,OP_EQ, string_is_C_identifier("_string_is_C_identifier"));
4067 tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
4068 tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
4069 tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
4070 tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
4071 tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
4072 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4073 tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
4074 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4076 tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
4077 tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
4078 tt_int_op(0,OP_EQ, string_is_C_identifier(""));
4079 tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
4080 tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
4081 tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
4082 tt_int_op(0,OP_EQ, string_is_C_identifier("í"));
4083 tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
4085 done:
4089 static void
4090 test_util_string_is_utf8(void *ptr)
4092 (void)ptr;
4094 tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0));
4095 tt_int_op(1, OP_EQ, string_is_utf8("", 1));
4096 tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3));
4097 tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3));
4098 tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7));
4099 tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9));
4101 // Validate exactly 'len' bytes.
4102 tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2));
4103 tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6));
4105 // Reject sequences with missing bytes.
4106 tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1));
4107 tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1));
4108 tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2));
4109 tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2));
4110 tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3));
4111 tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3));
4112 tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4));
4114 // Reject encodings that are overly long.
4115 tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2));
4116 tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2));
4117 tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3));
4118 tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3));
4119 tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4));
4120 tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4));
4122 // Reject UTF-16 surrogate halves.
4123 tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3));
4124 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3));
4125 tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
4126 tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
4128 // The maximum legal codepoint, 10FFFF.
4129 tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
4130 tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
4132 done:
4136 static void
4137 test_util_asprintf(void *ptr)
4139 #define LOREMIPSUM \
4140 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
4141 char *cp=NULL, *cp2=NULL;
4142 int r;
4143 (void)ptr;
4145 /* simple string */
4146 r = tor_asprintf(&cp, "simple string 100%% safe");
4147 tt_assert(cp);
4148 tt_str_op("simple string 100% safe",OP_EQ, cp);
4149 tt_int_op(strlen(cp),OP_EQ, r);
4150 tor_free(cp);
4152 /* empty string */
4153 r = tor_asprintf(&cp, "%s", "");
4154 tt_assert(cp);
4155 tt_str_op("",OP_EQ, cp);
4156 tt_int_op(strlen(cp),OP_EQ, r);
4157 tor_free(cp);
4159 /* numbers (%i) */
4160 r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
4161 tt_assert(cp);
4162 tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
4163 tt_int_op(strlen(cp),OP_EQ, r);
4164 /* don't free cp; next test uses it. */
4166 /* numbers (%d) */
4167 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
4168 tt_assert(cp2);
4169 tt_int_op(strlen(cp2),OP_EQ, r);
4170 tt_str_op("First=101, Second=202",OP_EQ, cp2);
4171 tt_assert(cp != cp2);
4172 tor_free(cp);
4173 tor_free(cp2);
4175 /* Glass-box test: a string exactly 128 characters long. */
4176 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
4177 tt_assert(cp);
4178 tt_int_op(128,OP_EQ, r);
4179 tt_int_op(cp[128], OP_EQ, '\0');
4180 tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
4181 tor_free(cp);
4183 /* String longer than 128 characters */
4184 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
4185 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
4186 tt_assert(cp);
4187 tt_int_op(strlen(cp),OP_EQ, r);
4188 tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
4190 done:
4191 tor_free(cp);
4192 tor_free(cp2);
4195 static void
4196 test_util_listdir(void *ptr)
4198 smartlist_t *dir_contents = NULL;
4199 char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
4200 int r;
4201 (void)ptr;
4203 fname1 = tor_strdup(get_fname("hopscotch"));
4204 fname2 = tor_strdup(get_fname("mumblety-peg"));
4205 fname3 = tor_strdup(get_fname(".hidden-file"));
4206 dir1 = tor_strdup(get_fname("some-directory"));
4207 dirname = tor_strdup(get_fname(NULL));
4209 tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
4210 tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
4211 tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
4212 #ifdef _WIN32
4213 r = mkdir(dir1);
4214 #else
4215 r = mkdir(dir1, 0700);
4216 #endif
4217 if (r) {
4218 fprintf(stderr, "Can't create directory %s:", dir1);
4219 perror("");
4220 exit(1);
4223 dir_contents = tor_listdir(dirname);
4224 tt_assert(dir_contents);
4225 /* make sure that each filename is listed. */
4226 tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
4227 tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
4228 tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
4229 tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
4231 tt_assert(!smartlist_contains_string(dir_contents, "."));
4232 tt_assert(!smartlist_contains_string(dir_contents, ".."));
4234 done:
4235 tor_free(fname1);
4236 tor_free(fname2);
4237 tor_free(fname3);
4238 tor_free(dir1);
4239 tor_free(dirname);
4240 if (dir_contents) {
4241 SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
4242 smartlist_free(dir_contents);
4246 static void
4247 test_util_parent_dir(void *ptr)
4249 char *cp;
4250 (void)ptr;
4252 #define T(output,expect_ok,input) \
4253 do { \
4254 int ok; \
4255 cp = tor_strdup(input); \
4256 ok = get_parent_directory(cp); \
4257 tt_int_op(expect_ok, OP_EQ, ok); \
4258 if (ok==0) \
4259 tt_str_op(output, OP_EQ, cp); \
4260 tor_free(cp); \
4261 } while (0);
4263 T("/home/wombat", 0, "/home/wombat/knish");
4264 T("/home/wombat", 0, "/home/wombat/knish/");
4265 T("/home/wombat", 0, "/home/wombat/knish///");
4266 T("./home/wombat", 0, "./home/wombat/knish/");
4267 T("/", 0, "/home");
4268 T("/", 0, "/home//");
4269 T(".", 0, "./wombat");
4270 T(".", 0, "./wombat/");
4271 T(".", 0, "./wombat//");
4272 T("wombat", 0, "wombat/foo");
4273 T("wombat/..", 0, "wombat/../foo");
4274 T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
4275 T("wombat/.", 0, "wombat/./foo");
4276 T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
4277 T("wombat", 0, "wombat/..//");
4278 T("wombat", 0, "wombat/foo/");
4279 T("wombat", 0, "wombat/.foo");
4280 T("wombat", 0, "wombat/.foo/");
4282 T("wombat", -1, "");
4283 T("w", -1, "");
4284 T("wombat", 0, "wombat/knish");
4286 T("/", 0, "/");
4287 T("/", 0, "////");
4289 done:
4290 tor_free(cp);
4293 static void
4294 test_util_ftruncate(void *ptr)
4296 char *buf = NULL;
4297 const char *fname;
4298 int fd = -1;
4299 const char *message = "Hello world";
4300 const char *message2 = "Hola mundo";
4301 struct stat st;
4303 (void) ptr;
4305 fname = get_fname("ftruncate");
4307 fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
4308 tt_int_op(fd, OP_GE, 0);
4310 /* Make the file be there. */
4311 tt_int_op(strlen(message), OP_EQ,
4312 write_all_to_fd(fd, message, strlen(message)));
4313 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
4314 tt_int_op(0, OP_EQ, fstat(fd, &st));
4315 tt_int_op((int)st.st_size, OP_EQ, strlen(message));
4317 /* Truncate and see if it got truncated */
4318 tt_int_op(0, OP_EQ, tor_ftruncate(fd));
4319 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
4320 tt_int_op(0, OP_EQ, fstat(fd, &st));
4321 tt_int_op((int)st.st_size, OP_EQ, 0);
4323 /* Replace, and see if it got replaced */
4324 tt_int_op(strlen(message2), OP_EQ,
4325 write_all_to_fd(fd, message2, strlen(message2)));
4326 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
4327 tt_int_op(0, OP_EQ, fstat(fd, &st));
4328 tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
4330 close(fd);
4331 fd = -1;
4333 buf = read_file_to_str(fname, 0, NULL);
4334 tt_str_op(message2, OP_EQ, buf);
4336 done:
4337 if (fd >= 0)
4338 close(fd);
4339 tor_free(buf);
4342 static void
4343 test_util_num_cpus(void *arg)
4345 (void)arg;
4346 int num = compute_num_cpus();
4347 if (num < 0)
4348 tt_skip();
4350 tt_int_op(num, OP_GE, 1);
4351 tt_int_op(num, OP_LE, 16);
4353 done:
4357 #ifdef _WIN32
4358 static void
4359 test_util_load_win_lib(void *ptr)
4361 HANDLE h = load_windows_system_library(_T("advapi32.dll"));
4362 (void) ptr;
4364 tt_assert(h);
4365 done:
4366 if (h)
4367 FreeLibrary(h);
4369 #endif /* defined(_WIN32) */
4371 #ifndef _WIN32
4372 static void
4373 clear_hex_errno(char *hex_errno)
4375 memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
4378 static void
4379 test_util_exit_status(void *ptr)
4381 /* Leave an extra byte for a \0 so we can do string comparison */
4382 char hex_errno[HEX_ERRNO_SIZE + 1];
4383 int n;
4385 (void)ptr;
4387 clear_hex_errno(hex_errno);
4388 tt_str_op("",OP_EQ, hex_errno);
4390 clear_hex_errno(hex_errno);
4391 n = format_helper_exit_status(0, 0, hex_errno);
4392 tt_str_op("0/0\n",OP_EQ, hex_errno);
4393 tt_int_op(n,OP_EQ, strlen(hex_errno));
4395 #if SIZEOF_INT == 4
4397 clear_hex_errno(hex_errno);
4398 n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
4399 tt_str_op("0/7FFFFFFF\n",OP_EQ, hex_errno);
4400 tt_int_op(n,OP_EQ, strlen(hex_errno));
4402 clear_hex_errno(hex_errno);
4403 n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
4404 tt_str_op("FF/-80000000\n",OP_EQ, hex_errno);
4405 tt_int_op(n,OP_EQ, strlen(hex_errno));
4406 tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE);
4408 #elif SIZEOF_INT == 8
4410 clear_hex_errno(hex_errno);
4411 n = format_helper_exit_status(0, 0x7FFFFFFFFFFFFFFF, hex_errno);
4412 tt_str_op("0/7FFFFFFFFFFFFFFF\n",OP_EQ, hex_errno);
4413 tt_int_op(n,OP_EQ, strlen(hex_errno));
4415 clear_hex_errno(hex_errno);
4416 n = format_helper_exit_status(0xFF, -0x8000000000000000, hex_errno);
4417 tt_str_op("FF/-8000000000000000\n",OP_EQ, hex_errno);
4418 tt_int_op(n,OP_EQ, strlen(hex_errno));
4419 tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE);
4421 #endif /* SIZEOF_INT == 4 || ... */
4423 clear_hex_errno(hex_errno);
4424 n = format_helper_exit_status(0x7F, 0, hex_errno);
4425 tt_str_op("7F/0\n",OP_EQ, hex_errno);
4426 tt_int_op(n,OP_EQ, strlen(hex_errno));
4428 clear_hex_errno(hex_errno);
4429 n = format_helper_exit_status(0x08, -0x242, hex_errno);
4430 tt_str_op("8/-242\n",OP_EQ, hex_errno);
4431 tt_int_op(n,OP_EQ, strlen(hex_errno));
4433 clear_hex_errno(hex_errno);
4434 tt_str_op("",OP_EQ, hex_errno);
4436 done:
4439 #endif /* !defined(_WIN32) */
4441 #ifndef _WIN32
4442 static void
4443 test_util_string_from_pipe(void *ptr)
4445 int test_pipe[2] = {-1, -1};
4446 int retval = 0;
4447 enum stream_status status = IO_STREAM_TERM;
4448 ssize_t retlen;
4449 char buf[4] = { 0 };
4451 (void)ptr;
4453 errno = 0;
4455 /* Set up a pipe to test on */
4456 retval = pipe(test_pipe);
4457 tt_int_op(retval, OP_EQ, 0);
4459 /* Send in a string. */
4460 retlen = write(test_pipe[1], "ABC", 3);
4461 tt_int_op(retlen, OP_EQ, 3);
4463 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4464 tt_int_op(errno, OP_EQ, 0);
4465 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4466 tt_str_op(buf, OP_EQ, "ABC");
4467 errno = 0;
4469 /* Send in a string that contains a nul. */
4470 retlen = write(test_pipe[1], "AB\0", 3);
4471 tt_int_op(retlen, OP_EQ, 3);
4473 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4474 tt_int_op(errno, OP_EQ, 0);
4475 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4476 tt_str_op(buf, OP_EQ, "AB");
4477 errno = 0;
4479 /* Send in a string that contains a nul only. */
4480 retlen = write(test_pipe[1], "\0", 1);
4481 tt_int_op(retlen, OP_EQ, 1);
4483 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4484 tt_int_op(errno, OP_EQ, 0);
4485 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4486 tt_str_op(buf, OP_EQ, "");
4487 errno = 0;
4489 /* Send in a string that contains a trailing newline. */
4490 retlen = write(test_pipe[1], "AB\n", 3);
4491 tt_int_op(retlen, OP_EQ, 3);
4493 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4494 tt_int_op(errno, OP_EQ, 0);
4495 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4496 tt_str_op(buf, OP_EQ, "AB");
4497 errno = 0;
4499 /* Send in a string that contains a newline only. */
4500 retlen = write(test_pipe[1], "\n", 1);
4501 tt_int_op(retlen, OP_EQ, 1);
4503 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4504 tt_int_op(errno, OP_EQ, 0);
4505 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4506 tt_str_op(buf, OP_EQ, "");
4507 errno = 0;
4509 /* Send in a string and check that we nul terminate return values. */
4510 retlen = write(test_pipe[1], "AAA", 3);
4511 tt_int_op(retlen, OP_EQ, 3);
4513 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4514 tt_int_op(errno, OP_EQ, 0);
4515 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4516 tt_str_op(buf, OP_EQ, "AAA");
4517 tt_mem_op(buf, OP_EQ, "AAA\0", sizeof(buf));
4518 errno = 0;
4520 retlen = write(test_pipe[1], "B", 1);
4521 tt_int_op(retlen, OP_EQ, 1);
4523 memset(buf, '\xff', sizeof(buf));
4524 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4525 tt_int_op(errno, OP_EQ, 0);
4526 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4527 tt_str_op(buf, OP_EQ, "B");
4528 tt_mem_op(buf, OP_EQ, "B\0\xff\xff", sizeof(buf));
4529 errno = 0;
4531 /* Send in multiple lines. */
4532 retlen = write(test_pipe[1], "A\nB", 3);
4533 tt_int_op(retlen, OP_EQ, 3);
4535 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4536 tt_int_op(errno, OP_EQ, 0);
4537 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4538 tt_str_op(buf, OP_EQ, "A\nB");
4539 errno = 0;
4541 /* Send in a line and close */
4542 retlen = write(test_pipe[1], "AB", 2);
4543 tt_int_op(retlen, OP_EQ, 2);
4544 retval = close(test_pipe[1]);
4545 tt_int_op(retval, OP_EQ, 0);
4546 test_pipe[1] = -1;
4548 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4549 tt_int_op(errno, OP_EQ, 0);
4550 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4551 tt_str_op(buf, OP_EQ, "AB");
4552 errno = 0;
4554 /* Check for EOF */
4555 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4556 tt_int_op(errno, OP_EQ, 0);
4557 tt_int_op(status, OP_EQ, IO_STREAM_CLOSED);
4558 errno = 0;
4560 done:
4561 if (test_pipe[0] != -1)
4562 close(test_pipe[0]);
4563 if (test_pipe[1] != -1)
4564 close(test_pipe[1]);
4567 #endif /* !defined(_WIN32) */
4570 * Test for format_hex_number_sigsafe()
4573 static void
4574 test_util_format_hex_number(void *ptr)
4576 int i, len;
4577 char buf[33];
4578 const struct {
4579 const char *str;
4580 unsigned int x;
4581 } test_data[] = {
4582 {"0", 0},
4583 {"1", 1},
4584 {"273A", 0x273a},
4585 {"FFFF", 0xffff},
4586 {"7FFFFFFF", 0x7fffffff},
4587 {"FFFFFFFF", 0xffffffff},
4588 #if UINT_MAX >= 0xffffffff
4589 {"31BC421D", 0x31bc421d},
4590 {"FFFFFFFF", 0xffffffff},
4591 #endif
4592 {NULL, 0}
4595 (void)ptr;
4597 for (i = 0; test_data[i].str != NULL; ++i) {
4598 len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
4599 tt_int_op(len,OP_NE, 0);
4600 tt_int_op(len,OP_EQ, strlen(buf));
4601 tt_str_op(buf,OP_EQ, test_data[i].str);
4604 tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
4605 tt_str_op(buf,OP_EQ, "FFFF");
4606 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
4607 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
4609 done:
4610 return;
4614 * Test for format_hex_number_sigsafe()
4617 static void
4618 test_util_format_dec_number(void *ptr)
4620 int i, len;
4621 char buf[33];
4622 const struct {
4623 const char *str;
4624 unsigned int x;
4625 } test_data[] = {
4626 {"0", 0},
4627 {"1", 1},
4628 {"1234", 1234},
4629 {"12345678", 12345678},
4630 {"99999999", 99999999},
4631 {"100000000", 100000000},
4632 {"4294967295", 4294967295u},
4633 #if UINT_MAX > 0xffffffff
4634 {"18446744073709551615", 18446744073709551615u },
4635 #endif
4636 {NULL, 0}
4639 (void)ptr;
4641 for (i = 0; test_data[i].str != NULL; ++i) {
4642 len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
4643 tt_int_op(len,OP_NE, 0);
4644 tt_int_op(len,OP_EQ, strlen(buf));
4645 tt_str_op(buf,OP_EQ, test_data[i].str);
4647 len = format_dec_number_sigsafe(test_data[i].x, buf,
4648 (int)(strlen(test_data[i].str) + 1));
4649 tt_int_op(len,OP_EQ, strlen(buf));
4650 tt_str_op(buf,OP_EQ, test_data[i].str);
4653 tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
4654 tt_str_op(buf,OP_EQ, "7331");
4655 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
4656 tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
4657 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
4659 done:
4660 return;
4664 * Test that we can properly format a Windows command line
4666 static void
4667 test_util_join_win_cmdline(void *ptr)
4669 /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
4670 * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
4671 * will try to only generate simple cases for the child process to parse;
4672 * i.e. we never embed quoted strings in arguments. */
4674 const char *argvs[][4] = {
4675 {"a", "bb", "CCC", NULL}, // Normal
4676 {NULL, NULL, NULL, NULL}, // Empty argument list
4677 {"", NULL, NULL, NULL}, // Empty argument
4678 {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
4679 {"a\tbc", "dd dd", "E", NULL}, // Whitespace
4680 {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
4681 {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
4682 {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
4683 { NULL } // Terminator
4686 const char *cmdlines[] = {
4687 "a bb CCC",
4689 "\"\"",
4690 "\\\"a b\\\"b CCC\\\"",
4691 "\"a\tbc\" \"dd dd\" E",
4692 "a\\\\\\b \"de fg\" H",
4693 "a\\\\\\\"b \\c D\\",
4694 "\"a\\\\b c\" d E",
4695 NULL // Terminator
4698 int i;
4699 char *joined_argv = NULL;
4701 (void)ptr;
4703 for (i=0; cmdlines[i]!=NULL; i++) {
4704 log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
4705 joined_argv = tor_join_win_cmdline(argvs[i]);
4706 tt_str_op(cmdlines[i],OP_EQ, joined_argv);
4707 tor_free(joined_argv);
4710 done:
4711 tor_free(joined_argv);
4714 #define MAX_SPLIT_LINE_COUNT 4
4715 struct split_lines_test_t {
4716 const char *orig_line; // Line to be split (may contain \0's)
4717 int orig_length; // Length of orig_line
4718 const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
4722 * Test that we properly split a buffer into lines
4724 static void
4725 test_util_split_lines(void *ptr)
4727 /* Test cases. orig_line of last test case must be NULL.
4728 * The last element of split_line[i] must be NULL. */
4729 struct split_lines_test_t tests[] = {
4730 {"", 0, {NULL}},
4731 {"foo", 3, {"foo", NULL}},
4732 {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
4733 {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
4734 {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
4735 {"line 1\r\nline 2", 14, {"line 1", "line 2", NULL}},
4736 {"line 1\r\n\r\nline 2", 16, {"line 1", "line 2", NULL}},
4737 {"line 1\r\n\r\r\r\nline 2", 18, {"line 1", "line 2", NULL}},
4738 {"line 1\r\n\n\n\n\rline 2", 18, {"line 1", "line 2", NULL}},
4739 {"line 1\r\n\r\t\r\nline 3", 18, {"line 1", ".", "line 3", NULL}},
4740 {"\n\t\r\t\nline 3", 11, {".", ".", "line 3", NULL}},
4741 {NULL, 0, { NULL }}
4744 int i, j;
4745 char *orig_line=NULL;
4746 smartlist_t *sl=NULL;
4748 (void)ptr;
4750 for (i=0; tests[i].orig_line; i++) {
4751 sl = smartlist_new();
4752 /* Allocate space for string and trailing NULL */
4753 orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
4754 tor_split_lines(sl, orig_line, tests[i].orig_length);
4756 j = 0;
4757 log_info(LD_GENERAL, "Splitting test %d of length %d",
4758 i, tests[i].orig_length);
4759 SMARTLIST_FOREACH_BEGIN(sl, const char *, line) {
4760 /* Check we have not got too many lines */
4761 tt_int_op(MAX_SPLIT_LINE_COUNT, OP_GT, j);
4762 /* Check that there actually should be a line here */
4763 tt_ptr_op(tests[i].split_line[j], OP_NE, NULL);
4764 log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
4765 j, i, tests[i].split_line[j]);
4766 /* Check that the line is as expected */
4767 tt_str_op(line,OP_EQ, tests[i].split_line[j]);
4768 j++;
4769 } SMARTLIST_FOREACH_END(line);
4770 /* Check that we didn't miss some lines */
4771 tt_ptr_op(NULL,OP_EQ, tests[i].split_line[j]);
4772 tor_free(orig_line);
4773 smartlist_free(sl);
4774 sl = NULL;
4777 done:
4778 tor_free(orig_line);
4779 smartlist_free(sl);
4782 static void
4783 test_util_di_ops(void *arg)
4785 #define LT -1
4786 #define GT 1
4787 #define EQ 0
4788 const struct {
4789 const char *a; int want_sign; const char *b;
4790 } examples[] = {
4791 { "Foo", EQ, "Foo" },
4792 { "foo", GT, "bar", },
4793 { "foobar", EQ ,"foobar" },
4794 { "foobar", LT, "foobaw" },
4795 { "foobar", GT, "f00bar" },
4796 { "foobar", GT, "boobar" },
4797 { "", EQ, "" },
4798 { NULL, 0, NULL },
4801 int i;
4803 (void)arg;
4804 for (i = 0; examples[i].a; ++i) {
4805 size_t len = strlen(examples[i].a);
4806 int eq1, eq2, neq1, neq2, cmp1, cmp2;
4807 tt_int_op(len,OP_EQ, strlen(examples[i].b));
4808 /* We do all of the operations, with operands in both orders. */
4809 eq1 = tor_memeq(examples[i].a, examples[i].b, len);
4810 eq2 = tor_memeq(examples[i].b, examples[i].a, len);
4811 neq1 = tor_memneq(examples[i].a, examples[i].b, len);
4812 neq2 = tor_memneq(examples[i].b, examples[i].a, len);
4813 cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
4814 cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
4816 /* Check for correctness of cmp1 */
4817 if (cmp1 < 0 && examples[i].want_sign != LT)
4818 TT_DIE(("Assertion failed."));
4819 else if (cmp1 > 0 && examples[i].want_sign != GT)
4820 TT_DIE(("Assertion failed."));
4821 else if (cmp1 == 0 && examples[i].want_sign != EQ)
4822 TT_DIE(("Assertion failed."));
4824 /* Check for consistency of everything else with cmp1 */
4825 tt_int_op(eq1,OP_EQ, eq2);
4826 tt_int_op(neq1,OP_EQ, neq2);
4827 tt_int_op(cmp1,OP_EQ, -cmp2);
4828 tt_int_op(eq1,OP_EQ, cmp1 == 0);
4829 tt_int_op(neq1,OP_EQ, !eq1);
4833 uint8_t zz = 0;
4834 uint8_t ii = 0;
4835 int z;
4837 /* exhaustively test tor_memeq and tor_memcmp
4838 * against each possible single-byte numeric difference
4839 * some arithmetic bugs only appear with certain bit patterns */
4840 for (z = 0; z < 256; z++) {
4841 for (i = 0; i < 256; i++) {
4842 ii = (uint8_t)i;
4843 zz = (uint8_t)z;
4844 tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
4845 tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
4846 zz > ii ? GT : EQ);
4847 tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
4848 ii < zz ? LT : EQ);
4853 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
4854 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
4855 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
4856 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
4857 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
4858 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
4859 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
4860 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
4861 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
4863 done:
4867 static void
4868 test_util_di_map(void *arg)
4870 (void)arg;
4871 di_digest256_map_t *dimap = NULL;
4872 uint8_t key1[] = "Robert Anton Wilson ";
4873 uint8_t key2[] = "Martin Gardner, _Fads&fallacies";
4874 uint8_t key3[] = "Tom Lehrer, _Be Prepared_. ";
4875 uint8_t key4[] = "Ursula Le Guin,_A Wizard of... ";
4877 char dflt_entry[] = "'You have made a good beginning', but no more";
4879 tt_int_op(32, OP_EQ, sizeof(key1));
4880 tt_int_op(32, OP_EQ, sizeof(key2));
4881 tt_int_op(32, OP_EQ, sizeof(key3));
4883 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry));
4885 char *str1 = tor_strdup("You are precisely as big as what you love"
4886 " and precisely as small as what you allow"
4887 " to annoy you.");
4888 char *str2 = tor_strdup("Let us hope that Lysenko's success in Russia will"
4889 " serve for many generations to come as another"
4890 " reminder to the world of how quickly and easily"
4891 " a science can be corrupted when ignorant"
4892 " political leaders deem themselves competent"
4893 " to arbitrate scientific disputes");
4894 char *str3 = tor_strdup("Don't write naughty words on walls "
4895 "if you can't spell.");
4897 dimap_add_entry(&dimap, key1, str1);
4898 dimap_add_entry(&dimap, key2, str2);
4899 dimap_add_entry(&dimap, key3, str3);
4901 tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry));
4902 tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry));
4903 tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry));
4904 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry));
4906 done:
4907 dimap_free(dimap, tor_free_);
4911 * Test counting high bits
4913 static void
4914 test_util_n_bits_set(void *ptr)
4916 (void)ptr;
4917 tt_int_op(0,OP_EQ, n_bits_set_u8(0));
4918 tt_int_op(1,OP_EQ, n_bits_set_u8(1));
4919 tt_int_op(3,OP_EQ, n_bits_set_u8(7));
4920 tt_int_op(1,OP_EQ, n_bits_set_u8(8));
4921 tt_int_op(2,OP_EQ, n_bits_set_u8(129));
4922 tt_int_op(8,OP_EQ, n_bits_set_u8(255));
4923 done:
4928 * Test LHS whitespace (and comment) eater
4930 static void
4931 test_util_eat_whitespace(void *ptr)
4933 const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
4934 char str[80];
4935 size_t i;
4937 (void)ptr;
4939 /* Try one leading ws */
4940 strlcpy(str, "fuubaar", sizeof(str));
4941 for (i = 0; i < sizeof(ws); ++i) {
4942 str[0] = ws[i];
4943 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
4944 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4945 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
4946 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4948 str[0] = '\n';
4949 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
4950 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4951 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4952 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4954 /* Empty string */
4955 strlcpy(str, "", sizeof(str));
4956 tt_ptr_op(str,OP_EQ, eat_whitespace(str));
4957 tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
4958 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4959 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
4961 /* Only ws */
4962 strlcpy(str, " \t\r\n", sizeof(str));
4963 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4964 tt_ptr_op(str + strlen(str),OP_EQ,
4965 eat_whitespace_eos(str, str + strlen(str)));
4966 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
4967 eat_whitespace_no_nl(str));
4968 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
4969 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4971 strlcpy(str, " \t\r ", sizeof(str));
4972 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4973 tt_ptr_op(str + strlen(str),OP_EQ,
4974 eat_whitespace_eos(str, str + strlen(str)));
4975 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
4976 tt_ptr_op(str + strlen(str),OP_EQ,
4977 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4979 /* Multiple ws */
4980 strlcpy(str, "fuubaar", sizeof(str));
4981 for (i = 0; i < sizeof(ws); ++i)
4982 str[i] = ws[i];
4983 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
4984 tt_ptr_op(str + sizeof(ws),OP_EQ,
4985 eat_whitespace_eos(str, str + strlen(str)));
4986 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
4987 tt_ptr_op(str + sizeof(ws),OP_EQ,
4988 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4990 /* Eat comment */
4991 strlcpy(str, "# Comment \n No Comment", sizeof(str));
4992 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
4993 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4994 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4995 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4997 /* Eat comment & ws mix */
4998 strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
4999 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
5000 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5001 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
5002 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5004 /* Eat entire comment */
5005 strlcpy(str, "#Comment", sizeof(str));
5006 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5007 tt_ptr_op(str + strlen(str),OP_EQ,
5008 eat_whitespace_eos(str, str + strlen(str)));
5009 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5010 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5012 /* Blank line, then comment */
5013 strlcpy(str, " \t\n # Comment", sizeof(str));
5014 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5015 tt_ptr_op(str + strlen(str),OP_EQ,
5016 eat_whitespace_eos(str, str + strlen(str)));
5017 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
5018 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5020 done:
5024 /** Return a newly allocated smartlist containing the lines of text in
5025 * <b>lines</b>. The returned strings are heap-allocated, and must be
5026 * freed by the caller.
5028 * XXXX? Move to container.[hc] ? */
5029 static smartlist_t *
5030 smartlist_new_from_text_lines(const char *lines)
5032 smartlist_t *sl = smartlist_new();
5033 char *last_line;
5035 smartlist_split_string(sl, lines, "\n", 0, 0);
5037 last_line = smartlist_pop_last(sl);
5038 if (last_line != NULL && *last_line != '\0') {
5039 smartlist_add(sl, last_line);
5040 } else {
5041 tor_free(last_line);
5044 return sl;
5047 /** Test smartlist_new_from_text_lines */
5048 static void
5049 test_util_sl_new_from_text_lines(void *ptr)
5051 (void)ptr;
5053 { /* Normal usage */
5054 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
5055 int sl_len = smartlist_len(sl);
5057 tt_want_int_op(sl_len, OP_EQ, 3);
5059 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5060 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
5061 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
5063 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5064 smartlist_free(sl);
5067 { /* No final newline */
5068 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
5069 int sl_len = smartlist_len(sl);
5071 tt_want_int_op(sl_len, OP_EQ, 3);
5073 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5074 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
5075 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
5077 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5078 smartlist_free(sl);
5081 { /* No newlines */
5082 smartlist_t *sl = smartlist_new_from_text_lines("foo");
5083 int sl_len = smartlist_len(sl);
5085 tt_want_int_op(sl_len, OP_EQ, 1);
5087 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5089 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5090 smartlist_free(sl);
5093 { /* No text at all */
5094 smartlist_t *sl = smartlist_new_from_text_lines("");
5095 int sl_len = smartlist_len(sl);
5097 tt_want_int_op(sl_len, OP_EQ, 0);
5099 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5100 smartlist_free(sl);
5104 static void
5105 test_util_envnames(void *ptr)
5107 (void) ptr;
5109 tt_assert(environment_variable_names_equal("abc", "abc"));
5110 tt_assert(environment_variable_names_equal("abc", "abc="));
5111 tt_assert(environment_variable_names_equal("abc", "abc=def"));
5112 tt_assert(environment_variable_names_equal("abc=def", "abc"));
5113 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
5115 tt_assert(environment_variable_names_equal("abc", "abc"));
5116 tt_assert(environment_variable_names_equal("abc", "abc="));
5117 tt_assert(environment_variable_names_equal("abc", "abc=def"));
5118 tt_assert(environment_variable_names_equal("abc=def", "abc"));
5119 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
5121 tt_assert(!environment_variable_names_equal("abc", "abcd"));
5122 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
5123 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
5124 tt_assert(!environment_variable_names_equal("abc=", "def"));
5125 tt_assert(!environment_variable_names_equal("abc=", "def="));
5126 tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
5128 tt_assert(!environment_variable_names_equal("", "a=def"));
5129 /* A bit surprising. */
5130 tt_assert(environment_variable_names_equal("", "=def"));
5131 tt_assert(environment_variable_names_equal("=y", "=x"));
5133 done:
5137 /** Test process_environment_make */
5138 static void
5139 test_util_make_environment(void *ptr)
5141 const char *env_vars_string =
5142 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5143 "HOME=/home/foozer\n";
5144 const char expected_windows_env_block[] =
5145 "HOME=/home/foozer\000"
5146 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
5147 "\000";
5148 size_t expected_windows_env_block_len =
5149 sizeof(expected_windows_env_block) - 1;
5151 smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
5152 smartlist_t *env_vars_sorted = smartlist_new();
5153 smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
5155 process_environment_t *env;
5157 (void)ptr;
5159 env = process_environment_make(env_vars);
5161 /* Check that the Windows environment block is correct. */
5162 tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
5163 expected_windows_env_block_len));
5165 /* Now for the Unixoid environment block. We don't care which order
5166 * these environment variables are in, so we sort both lists first. */
5168 smartlist_add_all(env_vars_sorted, env_vars);
5171 char **v;
5172 for (v = env->unixoid_environment_block; *v; ++v) {
5173 smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
5177 smartlist_sort_strings(env_vars_sorted);
5178 smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
5180 tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
5181 smartlist_len(env_vars_in_unixoid_env_block_sorted));
5183 int len = smartlist_len(env_vars_sorted);
5184 int i;
5186 if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
5187 len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
5190 for (i = 0; i < len; ++i) {
5191 tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
5192 smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
5196 /* Clean up. */
5197 smartlist_free(env_vars_in_unixoid_env_block_sorted);
5198 smartlist_free(env_vars_sorted);
5200 SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
5201 smartlist_free(env_vars);
5203 process_environment_free(env);
5206 /** Test set_environment_variable_in_smartlist */
5207 static void
5208 test_util_set_env_var_in_sl(void *ptr)
5210 /* The environment variables in these strings are in arbitrary
5211 * order; we sort the resulting lists before comparing them.
5213 * (They *will not* end up in the order shown in
5214 * expected_resulting_env_vars_string.) */
5216 const char *base_env_vars_string =
5217 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5218 "HOME=/home/foozer\n"
5219 "TERM=xterm\n"
5220 "SHELL=/bin/ksh\n"
5221 "USER=foozer\n"
5222 "LOGNAME=foozer\n"
5223 "USERNAME=foozer\n"
5224 "LANG=en_US.utf8\n"
5227 const char *new_env_vars_string =
5228 "TERM=putty\n"
5229 "DISPLAY=:18.0\n"
5232 const char *expected_resulting_env_vars_string =
5233 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5234 "HOME=/home/foozer\n"
5235 "TERM=putty\n"
5236 "SHELL=/bin/ksh\n"
5237 "USER=foozer\n"
5238 "LOGNAME=foozer\n"
5239 "USERNAME=foozer\n"
5240 "LANG=en_US.utf8\n"
5241 "DISPLAY=:18.0\n"
5244 smartlist_t *merged_env_vars =
5245 smartlist_new_from_text_lines(base_env_vars_string);
5246 smartlist_t *new_env_vars =
5247 smartlist_new_from_text_lines(new_env_vars_string);
5248 smartlist_t *expected_resulting_env_vars =
5249 smartlist_new_from_text_lines(expected_resulting_env_vars_string);
5251 /* Elements of merged_env_vars are heap-allocated, and must be
5252 * freed. Some of them are (or should) be freed by
5253 * set_environment_variable_in_smartlist.
5255 * Elements of new_env_vars are heap-allocated, but are copied into
5256 * merged_env_vars, so they are not freed separately at the end of
5257 * the function.
5259 * Elements of expected_resulting_env_vars are heap-allocated, and
5260 * must be freed. */
5262 (void)ptr;
5264 SMARTLIST_FOREACH(new_env_vars, char *, env_var,
5265 set_environment_variable_in_smartlist(merged_env_vars,
5266 env_var,
5267 tor_free_,
5268 1));
5270 smartlist_sort_strings(merged_env_vars);
5271 smartlist_sort_strings(expected_resulting_env_vars);
5273 tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
5274 smartlist_len(expected_resulting_env_vars));
5276 int len = smartlist_len(merged_env_vars);
5277 int i;
5279 if (smartlist_len(expected_resulting_env_vars) < len) {
5280 len = smartlist_len(expected_resulting_env_vars);
5283 for (i = 0; i < len; ++i) {
5284 tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
5285 smartlist_get(expected_resulting_env_vars, i));
5289 /* Clean up. */
5290 SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
5291 smartlist_free(merged_env_vars);
5293 smartlist_free(new_env_vars);
5295 SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
5296 smartlist_free(expected_resulting_env_vars);
5299 static void
5300 test_util_weak_random(void *arg)
5302 int i, j, n[16];
5303 tor_weak_rng_t rng;
5304 (void) arg;
5306 tor_init_weak_random(&rng, (unsigned)time(NULL));
5308 for (i = 1; i <= 256; ++i) {
5309 for (j=0;j<100;++j) {
5310 int r = tor_weak_random_range(&rng, i);
5311 tt_int_op(0, OP_LE, r);
5312 tt_int_op(r, OP_LT, i);
5316 memset(n,0,sizeof(n));
5317 for (j=0;j<8192;++j) {
5318 n[tor_weak_random_range(&rng, 16)]++;
5321 for (i=0;i<16;++i)
5322 tt_int_op(n[i], OP_GT, 0);
5323 done:
5327 static void
5328 test_util_mathlog(void *arg)
5330 double d;
5331 (void) arg;
5333 d = tor_mathlog(2.718281828);
5334 tt_double_op(fabs(d - 1.0), OP_LT, .000001);
5335 d = tor_mathlog(10);
5336 tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
5337 done:
5341 static void
5342 test_util_fraction(void *arg)
5344 uint64_t a,b;
5345 (void)arg;
5347 a = 99; b = 30;
5348 simplify_fraction64(&a,&b);
5349 tt_u64_op(a, OP_EQ, 33);
5350 tt_u64_op(b, OP_EQ, 10);
5352 a = 3000000; b = 10000000;
5353 simplify_fraction64(&a,&b);
5354 tt_u64_op(a, OP_EQ, 3);
5355 tt_u64_op(b, OP_EQ, 10);
5357 a = 0; b = 15;
5358 simplify_fraction64(&a,&b);
5359 tt_u64_op(a, OP_EQ, 0);
5360 tt_u64_op(b, OP_EQ, 1);
5362 done:
5366 static void
5367 test_util_round_to_next_multiple_of(void *arg)
5369 (void)arg;
5371 tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0);
5372 tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0);
5374 tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99);
5375 tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105);
5376 tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99);
5378 tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ,
5379 UINT64_MAX);
5381 tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0);
5382 tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0);
5384 tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99);
5385 tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105);
5386 tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99);
5388 tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ,
5389 UINT32_MAX);
5391 tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0);
5392 tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0);
5394 tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99);
5395 tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105);
5396 tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99);
5398 tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ,
5399 UINT_MAX);
5400 done:
5404 static void
5405 test_util_laplace(void *arg)
5407 /* Sample values produced using Python's SciPy:
5409 * >>> from scipy.stats import laplace
5410 * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
5411 ... loc = 24, scale = 24)
5412 * array([ nan, -inf, -69.88855213, 24. ,
5413 * 24.48486498, 117.88855213, inf, nan])
5415 const double mu = 24.0, b = 24.0;
5416 const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
5417 (void)arg;
5419 tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0));
5420 tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01));
5421 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5));
5422 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51));
5423 tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99));
5425 /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
5426 * ... loc = 0, scale = 50)
5427 * array([ -inf, -80.47189562, -34.65735903, 0. ,
5428 * 34.65735903, 80.47189562, 195.60115027])
5430 tt_i64_op(INT64_MIN + 20, OP_EQ,
5431 add_laplace_noise(20, 0.0, delta_f, epsilon));
5433 tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon));
5434 tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon));
5435 tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon));
5436 tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon));
5437 tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon));
5438 tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon));
5440 /* Test extreme values of signal with maximally negative values of noise
5441 * 1.0000000000000002 is the smallest number > 1
5442 * 0.0000000000000002 is the double epsilon (error when calculating near 1)
5443 * this is approximately 1/(2^52)
5444 * per https://en.wikipedia.org/wiki/Double_precision
5445 * (let's not descend into the world of subnormals)
5446 * >>> laplace.ppf([0, 0.0000000000000002], loc = 0, scale = 1)
5447 * array([ -inf, -35.45506713])
5449 const double noscale_df = 1.0, noscale_eps = 1.0;
5451 tt_i64_op(INT64_MIN, OP_EQ,
5452 add_laplace_noise(0, 0.0, noscale_df, noscale_eps));
5454 /* is it clipped to INT64_MIN? */
5455 tt_i64_op(INT64_MIN, OP_EQ,
5456 add_laplace_noise(-1, 0.0, noscale_df, noscale_eps));
5457 tt_i64_op(INT64_MIN, OP_EQ,
5458 add_laplace_noise(INT64_MIN, 0.0,
5459 noscale_df, noscale_eps));
5460 /* ... even when scaled? */
5461 tt_i64_op(INT64_MIN, OP_EQ,
5462 add_laplace_noise(0, 0.0, delta_f, epsilon));
5463 tt_i64_op(INT64_MIN, OP_EQ,
5464 add_laplace_noise(0, 0.0,
5465 DBL_MAX, 1));
5466 tt_i64_op(INT64_MIN, OP_EQ,
5467 add_laplace_noise(INT64_MIN, 0.0,
5468 DBL_MAX, 1));
5470 /* does it play nice with INT64_MAX? */
5471 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5472 add_laplace_noise(INT64_MAX, 0.0,
5473 noscale_df, noscale_eps));
5475 /* do near-zero fractional values work? */
5476 const double min_dbl_error = 0.0000000000000002;
5478 tt_i64_op(-35, OP_EQ,
5479 add_laplace_noise(0, min_dbl_error,
5480 noscale_df, noscale_eps));
5481 tt_i64_op(INT64_MIN, OP_EQ,
5482 add_laplace_noise(INT64_MIN, min_dbl_error,
5483 noscale_df, noscale_eps));
5484 tt_i64_op((-35 + INT64_MAX), OP_EQ,
5485 add_laplace_noise(INT64_MAX, min_dbl_error,
5486 noscale_df, noscale_eps));
5487 tt_i64_op(INT64_MIN, OP_EQ,
5488 add_laplace_noise(0, min_dbl_error,
5489 DBL_MAX, 1));
5490 tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ,
5491 add_laplace_noise(INT64_MAX, min_dbl_error,
5492 DBL_MAX, 1));
5493 tt_i64_op(INT64_MIN, OP_EQ,
5494 add_laplace_noise(INT64_MIN, min_dbl_error,
5495 DBL_MAX, 1));
5497 /* does it play nice with INT64_MAX? */
5498 tt_i64_op((INT64_MAX - 35), OP_EQ,
5499 add_laplace_noise(INT64_MAX, min_dbl_error,
5500 noscale_df, noscale_eps));
5502 /* Test extreme values of signal with maximally positive values of noise
5503 * 1.0000000000000002 is the smallest number > 1
5504 * 0.9999999999999998 is the greatest number < 1 by calculation
5505 * per https://en.wikipedia.org/wiki/Double_precision
5506 * >>> laplace.ppf([1.0, 0.9999999999999998], loc = 0, scale = 1)
5507 * array([inf, 35.35050621])
5508 * but the function rejects p == 1.0, so we just use max_dbl_lt_one
5510 const double max_dbl_lt_one = 0.9999999999999998;
5512 /* do near-one fractional values work? */
5513 tt_i64_op(35, OP_EQ,
5514 add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps));
5516 /* is it clipped to INT64_MAX? */
5517 tt_i64_op(INT64_MAX, OP_EQ,
5518 add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one,
5519 noscale_df, noscale_eps));
5520 tt_i64_op(INT64_MAX, OP_EQ,
5521 add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one,
5522 noscale_df, noscale_eps));
5523 tt_i64_op(INT64_MAX, OP_EQ,
5524 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5525 noscale_df, noscale_eps));
5526 /* ... even when scaled? */
5527 tt_i64_op(INT64_MAX, OP_EQ,
5528 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5529 delta_f, epsilon));
5530 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5531 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5532 DBL_MAX, 1));
5533 tt_i64_op(INT64_MAX, OP_EQ,
5534 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5535 DBL_MAX, 1));
5536 /* does it play nice with INT64_MIN? */
5537 tt_i64_op((INT64_MIN + 35), OP_EQ,
5538 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5539 noscale_df, noscale_eps));
5541 done:
5545 static void
5546 test_util_clamp_double_to_int64(void *arg)
5548 (void)arg;
5550 tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL));
5551 tt_i64_op(INT64_MIN, OP_EQ,
5552 clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0));
5553 tt_i64_op(INT64_MIN, OP_EQ,
5554 clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0));
5555 tt_i64_op(((uint64_t) -1) << 53, OP_EQ,
5556 clamp_double_to_int64(-1.0 * pow(2.0, 53.0)));
5557 tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ,
5558 clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0));
5559 tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0));
5560 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9));
5561 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1));
5562 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0));
5563 tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL));
5564 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1));
5565 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9));
5566 tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0));
5567 tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ,
5568 clamp_double_to_int64(pow(2.0, 53.0) - 1.0));
5569 tt_i64_op(((int64_t) 1) << 53, OP_EQ,
5570 clamp_double_to_int64(pow(2.0, 53.0)));
5571 tt_i64_op(INT64_MAX, OP_EQ,
5572 clamp_double_to_int64(pow(2.0, 63.0)));
5573 tt_i64_op(INT64_MAX, OP_EQ,
5574 clamp_double_to_int64(pow(2.0, 64.0)));
5575 tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL));
5577 done:
5581 #ifdef FD_CLOEXEC
5582 #define CAN_CHECK_CLOEXEC
5583 static int
5584 fd_is_cloexec(tor_socket_t fd)
5586 int flags = fcntl(fd, F_GETFD, 0);
5587 return (flags & FD_CLOEXEC) == FD_CLOEXEC;
5589 #endif /* defined(FD_CLOEXEC) */
5591 #ifndef _WIN32
5592 #define CAN_CHECK_NONBLOCK
5593 static int
5594 fd_is_nonblocking(tor_socket_t fd)
5596 int flags = fcntl(fd, F_GETFL, 0);
5597 return (flags & O_NONBLOCK) == O_NONBLOCK;
5599 #endif /* !defined(_WIN32) */
5601 #define ERRNO_IS_EPROTO(e) (e == SOCK_ERRNO(EPROTONOSUPPORT))
5602 #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
5604 /* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
5605 static void
5606 test_util_socket(void *arg)
5608 const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
5609 tor_socket_t fd1 = TOR_INVALID_SOCKET;
5610 tor_socket_t fd2 = TOR_INVALID_SOCKET;
5611 tor_socket_t fd3 = TOR_INVALID_SOCKET;
5612 tor_socket_t fd4 = TOR_INVALID_SOCKET;
5613 int n = get_n_open_sockets();
5615 TT_BLATHER(("Starting with %d open sockets.", n));
5617 (void)arg;
5619 fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
5620 int err = tor_socket_errno(fd1);
5621 if (fd1 < 0 && (err == SOCK_ERRNO(EPROTONOSUPPORT) ||
5622 err == SOCK_ERRNO(EAFNOSUPPORT))) {
5623 /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
5624 goto done;
5626 fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
5627 tt_assert(SOCKET_OK(fd1));
5628 tt_assert(SOCKET_OK(fd2));
5629 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5630 //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
5631 //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
5632 fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
5633 fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
5634 tt_assert(SOCKET_OK(fd3));
5635 tt_assert(SOCKET_OK(fd4));
5636 tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
5638 #ifdef CAN_CHECK_CLOEXEC
5639 tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
5640 tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
5641 tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
5642 tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
5643 #endif /* defined(CAN_CHECK_CLOEXEC) */
5644 #ifdef CAN_CHECK_NONBLOCK
5645 tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
5646 tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
5647 tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
5648 tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
5649 #endif /* defined(CAN_CHECK_NONBLOCK) */
5651 tor_assert(tor_close_socket == tor_close_socket__real);
5653 /* we use close_socket__real here so that coverity can tell that we are
5654 * really closing these sockets. */
5655 tor_close_socket__real(fd1);
5656 tor_close_socket__real(fd2);
5657 fd1 = fd2 = TOR_INVALID_SOCKET;
5658 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5659 tor_close_socket__real(fd3);
5660 tor_close_socket__real(fd4);
5661 fd3 = fd4 = TOR_INVALID_SOCKET;
5662 tt_int_op(get_n_open_sockets(), OP_EQ, n);
5664 done:
5665 if (SOCKET_OK(fd1))
5666 tor_close_socket__real(fd1);
5667 if (SOCKET_OK(fd2))
5668 tor_close_socket__real(fd2);
5669 if (SOCKET_OK(fd3))
5670 tor_close_socket__real(fd3);
5671 if (SOCKET_OK(fd4))
5672 tor_close_socket__real(fd4);
5675 #if 0
5676 static int
5677 is_there_a_localhost(int family)
5679 tor_socket_t s;
5680 s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP);
5681 tor_assert(SOCKET_OK(s));
5683 int result = 0;
5684 if (family == AF_INET) {
5685 struct sockaddr_in s_in;
5686 memset(&s_in, 0, sizeof(s_in));
5687 s_in.sin_family = AF_INET;
5688 s_in.sin_addr.s_addr = htonl(0x7f000001);
5689 s_in.sin_port = 0;
5691 if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) {
5692 result = 1;
5694 } else if (family == AF_INET6) {
5695 struct sockaddr_in6 sin6;
5696 memset(&sin6, 0, sizeof(sin6));
5697 sin6.sin6_family = AF_INET6;
5698 sin6.sin6_addr.s6_addr[15] = 1;
5699 sin6.sin6_port = 0;
5701 tor_close_socket(s);
5703 return result;
5705 #endif /* 0 */
5707 /* Test for socketpair and ersatz_socketpair(). We test them both, since
5708 * the latter is a tolerably good way to exercise tor_accept_socket(). */
5709 static void
5710 test_util_socketpair(void *arg)
5712 const int ersatz = !strcmp(arg, "1");
5713 int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
5714 ersatz ? tor_ersatz_socketpair : tor_socketpair;
5715 int n = get_n_open_sockets();
5716 tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
5717 const int family = AF_UNIX;
5718 int socketpair_result = 0;
5720 socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
5722 #ifdef __FreeBSD__
5723 /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail.
5724 * Otherwise, we risk exposing a socketpair on a routable IP address. (Some
5725 * BSD jails use a routable address for localhost. Fortunately, they have
5726 * the real AF_UNIX socketpair.) */
5727 if (ersatz && socketpair_result < 0) {
5728 /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL.
5729 * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */
5730 tt_skip();
5732 #endif /* defined(__FreeBSD__) */
5733 tt_int_op(0, OP_EQ, socketpair_result);
5735 tt_assert(SOCKET_OK(fds[0]));
5736 tt_assert(SOCKET_OK(fds[1]));
5737 if (ersatz)
5738 tt_int_op(get_n_open_sockets(), OP_EQ, n);
5739 else
5740 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5741 #ifdef CAN_CHECK_CLOEXEC
5742 tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, !ersatz);
5743 tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, !ersatz);
5744 #endif
5745 #ifdef CAN_CHECK_NONBLOCK
5746 tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
5747 tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
5748 #endif
5750 done:
5751 if (ersatz) {
5752 if (SOCKET_OK(fds[0]))
5753 tor_close_socket_simple(fds[0]);
5754 if (SOCKET_OK(fds[1]))
5755 tor_close_socket_simple(fds[1]);
5756 } else {
5757 if (SOCKET_OK(fds[0]))
5758 tor_close_socket(fds[0]);
5759 if (SOCKET_OK(fds[1]))
5760 tor_close_socket(fds[1]);
5764 #undef SOCKET_EPROTO
5766 static void
5767 test_util_max_mem(void *arg)
5769 size_t memory1, memory2;
5770 int r, r2;
5771 (void) arg;
5773 r = get_total_system_memory(&memory1);
5774 r2 = get_total_system_memory(&memory2);
5775 tt_int_op(r, OP_EQ, r2);
5776 tt_uint_op(memory2, OP_EQ, memory1);
5778 TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1)));
5780 if (r==0) {
5781 /* You have at least a megabyte. */
5782 tt_uint_op(memory1, OP_GT, (1<<20));
5783 } else {
5784 /* You do not have a petabyte. */
5785 #if SIZEOF_SIZE_T >= 8
5786 tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50));
5787 #endif
5790 done:
5794 static void
5795 test_util_dest_validation_edgecase(void *arg)
5797 (void)arg;
5799 tt_assert(!string_is_valid_dest(NULL));
5800 tt_assert(!string_is_valid_dest(""));
5802 done:
5803 return;
5806 static void
5807 test_util_hostname_validation(void *arg)
5809 (void)arg;
5811 // Lets try valid hostnames first.
5812 tt_assert(string_is_valid_nonrfc_hostname("torproject.org"));
5813 tt_assert(string_is_valid_nonrfc_hostname("ocw.mit.edu"));
5814 tt_assert(string_is_valid_nonrfc_hostname("i.4cdn.org"));
5815 tt_assert(string_is_valid_nonrfc_hostname("stanford.edu"));
5816 tt_assert(string_is_valid_nonrfc_hostname("multiple-words-with-hypens.jp"));
5818 // Subdomain name cannot start with '-' or '_'.
5819 tt_assert(!string_is_valid_nonrfc_hostname("-torproject.org"));
5820 tt_assert(!string_is_valid_nonrfc_hostname("subdomain.-domain.org"));
5821 tt_assert(!string_is_valid_nonrfc_hostname("-subdomain.domain.org"));
5822 tt_assert(!string_is_valid_nonrfc_hostname("___abc.org"));
5824 // Hostnames cannot contain non-alphanumeric characters.
5825 tt_assert(!string_is_valid_nonrfc_hostname("%%domain.\\org."));
5826 tt_assert(!string_is_valid_nonrfc_hostname("***x.net"));
5827 tt_assert(!string_is_valid_nonrfc_hostname("\xff\xffxyz.org"));
5828 tt_assert(!string_is_valid_nonrfc_hostname("word1 word2.net"));
5830 // Test workaround for nytimes.com stupidity, technically invalid,
5831 // but we allow it since they are big, even though they are failing to
5832 // comply with a ~30 year old standard.
5833 tt_assert(string_is_valid_nonrfc_hostname("core3_euw1.fabrik.nytimes.com"));
5835 // Firefox passes FQDNs with trailing '.'s directly to the SOCKS proxy,
5836 // which is redundant since the spec states DOMAINNAME addresses are fully
5837 // qualified. While unusual, this should be tollerated.
5838 tt_assert(string_is_valid_nonrfc_hostname("core9_euw1.fabrik.nytimes.com."));
5839 tt_assert(!string_is_valid_nonrfc_hostname(
5840 "..washingtonpost.is.better.com"));
5841 tt_assert(!string_is_valid_nonrfc_hostname("so.is..ft.com"));
5842 tt_assert(!string_is_valid_nonrfc_hostname("..."));
5844 // XXX: do we allow single-label DNS names?
5845 // We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
5846 // but only test pathologically malformed traling '.' cases for now.
5847 tt_assert(!string_is_valid_nonrfc_hostname("."));
5848 tt_assert(!string_is_valid_nonrfc_hostname(".."));
5850 // IP address strings are not hostnames.
5851 tt_assert(!string_is_valid_nonrfc_hostname("8.8.8.8"));
5852 tt_assert(!string_is_valid_nonrfc_hostname("[2a00:1450:401b:800::200e]"));
5853 tt_assert(!string_is_valid_nonrfc_hostname("2a00:1450:401b:800::200e"));
5855 // We allow alphanumeric TLDs. For discussion, see ticket #25055.
5856 tt_assert(string_is_valid_nonrfc_hostname("lucky.13"));
5857 tt_assert(string_is_valid_nonrfc_hostname("luck.y13"));
5858 tt_assert(string_is_valid_nonrfc_hostname("luck.y13."));
5860 // We allow punycode TLDs. For examples, see
5861 // http://data.iana.org/TLD/tlds-alpha-by-domain.txt
5862 tt_assert(string_is_valid_nonrfc_hostname("example.xn--l1acc"));
5864 done:
5865 return;
5868 static void
5869 test_util_ipv4_validation(void *arg)
5871 (void)arg;
5873 tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
5874 tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
5876 tt_assert(!string_is_valid_ipv4_address("abcd"));
5877 tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
5878 tt_assert(!string_is_valid_ipv4_address("8.8."));
5880 done:
5881 return;
5884 static void
5885 test_util_writepid(void *arg)
5887 (void) arg;
5889 char *contents = NULL;
5890 const char *fname = get_fname("tmp_pid");
5891 unsigned long pid;
5892 char c;
5894 write_pidfile(fname);
5896 contents = read_file_to_str(fname, 0, NULL);
5897 tt_assert(contents);
5899 int n = tor_sscanf(contents, "%lu\n%c", &pid, &c);
5900 tt_int_op(n, OP_EQ, 1);
5902 #ifdef _WIN32
5903 tt_uint_op(pid, OP_EQ, _getpid());
5904 #else
5905 tt_uint_op(pid, OP_EQ, getpid());
5906 #endif
5908 done:
5909 tor_free(contents);
5912 static void
5913 test_util_get_avail_disk_space(void *arg)
5915 (void) arg;
5916 int64_t val;
5918 /* No answer for nonexistent directory */
5919 val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa");
5920 tt_i64_op(val, OP_EQ, -1);
5922 /* Try the current directory */
5923 val = tor_get_avail_disk_space(".");
5925 #if !defined(HAVE_STATVFS) && !defined(_WIN32)
5926 tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */
5927 #else
5928 tt_i64_op(val, OP_GT, 0); /* You have some space. */
5929 tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */
5930 #endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */
5932 done:
5936 static void
5937 test_util_touch_file(void *arg)
5939 (void) arg;
5940 const char *fname = get_fname("touch");
5942 const time_t now = time(NULL);
5943 struct stat st;
5944 write_bytes_to_file(fname, "abc", 3, 1);
5945 tt_int_op(0, OP_EQ, stat(fname, &st));
5946 /* A subtle point: the filesystem time is not necessarily equal to the
5947 * system clock time, since one can be using a monotonic clock, or coarse
5948 * monotonic clock, or whatever. So we might wind up with an mtime a few
5949 * microseconds ago. Let's just give it a lot of wiggle room. */
5950 tt_i64_op(st.st_mtime, OP_GE, now - 1);
5952 const time_t five_sec_ago = now - 5;
5953 struct utimbuf u = { five_sec_ago, five_sec_ago };
5954 tt_int_op(0, OP_EQ, utime(fname, &u));
5955 tt_int_op(0, OP_EQ, stat(fname, &st));
5956 /* Let's hope that utime/stat give the same second as a round-trip? */
5957 tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
5959 /* Finally we can touch the file */
5960 tt_int_op(0, OP_EQ, touch_file(fname));
5961 tt_int_op(0, OP_EQ, stat(fname, &st));
5962 tt_i64_op(st.st_mtime, OP_GE, now-1);
5964 done:
5968 #ifndef _WIN32
5969 static void
5970 test_util_pwdb(void *arg)
5972 (void) arg;
5973 const struct passwd *me = NULL, *me2, *me3;
5974 char *name = NULL;
5975 char *dir = NULL;
5977 /* Uncached case. */
5978 /* Let's assume that we exist. */
5979 me = tor_getpwuid(getuid());
5980 tt_ptr_op(me, OP_NE, NULL);
5981 name = tor_strdup(me->pw_name);
5983 /* Uncached case */
5984 me2 = tor_getpwnam(name);
5985 tt_ptr_op(me2, OP_NE, NULL);
5986 tt_int_op(me2->pw_uid, OP_EQ, getuid());
5988 /* Cached case */
5989 me3 = tor_getpwuid(getuid());
5990 tt_ptr_op(me3, OP_NE, NULL);
5991 tt_str_op(me3->pw_name, OP_EQ, name);
5993 me3 = tor_getpwnam(name);
5994 tt_ptr_op(me3, OP_NE, NULL);
5995 tt_int_op(me3->pw_uid, OP_EQ, getuid());
5997 dir = get_user_homedir(name);
5998 tt_ptr_op(dir, OP_NE, NULL);
6000 /* Try failing cases. First find a user that doesn't exist by name */
6001 char randbytes[4];
6002 char badname[9];
6003 int i, found=0;
6004 for (i = 0; i < 100; ++i) {
6005 crypto_rand(randbytes, sizeof(randbytes));
6006 base16_encode(badname, sizeof(badname), randbytes, sizeof(randbytes));
6007 if (tor_getpwnam(badname) == NULL) {
6008 found = 1;
6009 break;
6012 tt_assert(found);
6013 tor_free(dir);
6015 /* We should do a LOG_ERR */
6016 setup_full_capture_of_logs(LOG_ERR);
6017 dir = get_user_homedir(badname);
6018 tt_ptr_op(dir, OP_EQ, NULL);
6019 expect_log_msg_containing("not found");
6020 tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1);
6021 teardown_capture_of_logs();
6023 /* Now try to find a user that doesn't exist by ID. */
6024 found = 0;
6025 for (i = 0; i < 1000; ++i) {
6026 uid_t u;
6027 crypto_rand((char*)&u, sizeof(u));
6028 if (tor_getpwuid(u) == NULL) {
6029 found = 1;
6030 break;
6033 tt_assert(found);
6035 done:
6036 tor_free(name);
6037 tor_free(dir);
6038 teardown_capture_of_logs();
6040 #endif /* !defined(_WIN32) */
6042 static void
6043 test_util_calloc_check(void *arg)
6045 (void) arg;
6046 /* Easy cases that are good. */
6047 tt_assert(size_mul_check(0,0));
6048 tt_assert(size_mul_check(0,100));
6049 tt_assert(size_mul_check(100,0));
6050 tt_assert(size_mul_check(100,100));
6052 /* Harder cases that are still good. */
6053 tt_assert(size_mul_check(SIZE_MAX, 1));
6054 tt_assert(size_mul_check(1, SIZE_MAX));
6055 tt_assert(size_mul_check(SIZE_MAX / 10, 9));
6056 tt_assert(size_mul_check(11, SIZE_MAX / 12));
6057 const size_t sqrt_size_max_p1 = ((size_t)1) << (sizeof(size_t) * 4);
6058 tt_assert(size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1 - 1));
6060 /* Cases that overflow */
6061 tt_assert(! size_mul_check(SIZE_MAX, 2));
6062 tt_assert(! size_mul_check(2, SIZE_MAX));
6063 tt_assert(! size_mul_check(SIZE_MAX / 10, 11));
6064 tt_assert(! size_mul_check(11, SIZE_MAX / 10));
6065 tt_assert(! size_mul_check(SIZE_MAX / 8, 9));
6066 tt_assert(! size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1));
6068 done:
6072 static void
6073 test_util_monotonic_time(void *arg)
6075 (void)arg;
6077 monotime_t mt1, mt2;
6078 monotime_coarse_t mtc1, mtc2;
6079 uint64_t nsec1, nsec2, usec1, msec1;
6080 uint64_t nsecc1, nsecc2, usecc1, msecc1;
6081 uint32_t stamp1, stamp2;
6083 monotime_init();
6085 monotime_get(&mt1);
6086 monotime_coarse_get(&mtc1);
6087 nsec1 = monotime_absolute_nsec();
6088 usec1 = monotime_absolute_usec();
6089 msec1 = monotime_absolute_msec();
6090 nsecc1 = monotime_coarse_absolute_nsec();
6091 usecc1 = monotime_coarse_absolute_usec();
6092 msecc1 = monotime_coarse_absolute_msec();
6093 stamp1 = monotime_coarse_to_stamp(&mtc1);
6095 tor_sleep_msec(200);
6097 monotime_get(&mt2);
6098 monotime_coarse_get(&mtc2);
6099 nsec2 = monotime_absolute_nsec();
6100 nsecc2 = monotime_coarse_absolute_nsec();
6101 stamp2 = monotime_coarse_to_stamp(&mtc2);
6103 /* We need to be a little careful here since we don't know the system load.
6105 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_GE, 175);
6106 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_LT, 1000);
6107 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_GE, 125);
6108 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_LT, 1000);
6109 tt_u64_op(nsec2-nsec1, OP_GE, 175000000);
6110 tt_u64_op(nsec2-nsec1, OP_LT, 1000000000);
6111 tt_u64_op(nsecc2-nsecc1, OP_GE, 125000000);
6112 tt_u64_op(nsecc2-nsecc1, OP_LT, 1000000000);
6114 tt_u64_op(msec1, OP_GE, nsec1 / 1000000);
6115 tt_u64_op(usec1, OP_GE, nsec1 / 1000);
6116 tt_u64_op(msecc1, OP_GE, nsecc1 / 1000000);
6117 tt_u64_op(usecc1, OP_GE, nsecc1 / 1000);
6118 tt_u64_op(msec1, OP_LE, nsec1 / 1000000 + 10);
6119 tt_u64_op(usec1, OP_LE, nsec1 / 1000 + 10000);
6120 tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 10);
6121 tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 10000);
6123 uint64_t coarse_stamp_diff =
6124 monotime_coarse_stamp_units_to_approx_msec(stamp2-stamp1);
6125 tt_u64_op(coarse_stamp_diff, OP_GE, 120);
6126 tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
6129 uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
6130 uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
6131 tt_u64_op(ms, OP_GE, 4950);
6132 tt_u64_op(ms, OP_LT, 5050);
6135 done:
6139 static void
6140 test_util_monotonic_time_ratchet(void *arg)
6142 (void)arg;
6143 monotime_init();
6144 monotime_reset_ratchets_for_testing();
6146 /* win32, performance counter ratchet. */
6147 tt_i64_op(100, OP_EQ, ratchet_performance_counter(100));
6148 tt_i64_op(101, OP_EQ, ratchet_performance_counter(101));
6149 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(2000));
6150 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(100));
6151 tt_i64_op(2005, OP_EQ, ratchet_performance_counter(105));
6152 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1105));
6153 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1000));
6154 tt_i64_op(3010, OP_EQ, ratchet_performance_counter(1005));
6156 /* win32, GetTickCounts32 ratchet-and-rollover-detector. */
6157 const int64_t R = ((int64_t)1) << 32;
6158 tt_i64_op(5, OP_EQ, ratchet_coarse_performance_counter(5));
6159 tt_i64_op(1000, OP_EQ, ratchet_coarse_performance_counter(1000));
6160 tt_i64_op(5+R, OP_EQ, ratchet_coarse_performance_counter(5));
6161 tt_i64_op(10+R, OP_EQ, ratchet_coarse_performance_counter(10));
6162 tt_i64_op(4+R*2, OP_EQ, ratchet_coarse_performance_counter(4));
6164 /* gettimeofday regular ratchet. */
6165 struct timeval tv_in = {0,0}, tv_out;
6166 tv_in.tv_usec = 9000;
6168 ratchet_timeval(&tv_in, &tv_out);
6169 tt_int_op(tv_out.tv_usec, OP_EQ, 9000);
6170 tt_i64_op(tv_out.tv_sec, OP_EQ, 0);
6172 tv_in.tv_sec = 1337;
6173 tv_in.tv_usec = 0;
6174 ratchet_timeval(&tv_in, &tv_out);
6175 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
6176 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6178 tv_in.tv_sec = 1336;
6179 tv_in.tv_usec = 500000;
6180 ratchet_timeval(&tv_in, &tv_out);
6181 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
6182 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6184 tv_in.tv_sec = 1337;
6185 tv_in.tv_usec = 0;
6186 ratchet_timeval(&tv_in, &tv_out);
6187 tt_int_op(tv_out.tv_usec, OP_EQ, 500000);
6188 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6190 tv_in.tv_sec = 1337;
6191 tv_in.tv_usec = 600000;
6192 ratchet_timeval(&tv_in, &tv_out);
6193 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
6194 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
6196 tv_in.tv_sec = 1000;
6197 tv_in.tv_usec = 1000;
6198 ratchet_timeval(&tv_in, &tv_out);
6199 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
6200 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
6202 tv_in.tv_sec = 2000;
6203 tv_in.tv_usec = 2000;
6204 ratchet_timeval(&tv_in, &tv_out);
6205 tt_int_op(tv_out.tv_usec, OP_EQ, 101000);
6206 tt_i64_op(tv_out.tv_sec, OP_EQ, 2338);
6208 done:
6212 static void
6213 test_util_monotonic_time_zero(void *arg)
6215 (void) arg;
6216 monotime_t t1;
6217 monotime_coarse_t ct1;
6218 monotime_init();
6219 /* Check 1: The current time is not zero. */
6220 monotime_get(&t1);
6221 monotime_coarse_get(&ct1);
6222 tt_assert(!monotime_is_zero(&t1));
6223 tt_assert(!monotime_coarse_is_zero(&ct1));
6225 /* Check 2: The _zero() makes the time zero. */
6226 monotime_zero(&t1);
6227 monotime_coarse_zero(&ct1);
6228 tt_assert(monotime_is_zero(&t1));
6229 tt_assert(monotime_coarse_is_zero(&ct1));
6230 done:
6234 static void
6235 test_util_monotonic_time_add_msec(void *arg)
6237 (void) arg;
6238 monotime_t t1, t2;
6239 monotime_coarse_t ct1, ct2;
6240 monotime_init();
6242 monotime_get(&t1);
6243 monotime_coarse_get(&ct1);
6245 /* adding zero does nothing */
6246 monotime_add_msec(&t2, &t1, 0);
6247 monotime_coarse_add_msec(&ct2, &ct1, 0);
6248 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 0);
6249 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 0);
6251 /* Add 1337 msec; see if the diff function agree */
6252 monotime_add_msec(&t2, &t1, 1337);
6253 monotime_coarse_add_msec(&ct2, &ct1, 1337);
6254 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
6255 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
6256 // The 32-bit variant must be within 1% of the regular one.
6257 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
6258 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
6260 /* Add 1337 msec twice more; make sure that any second rollover issues
6261 * worked. */
6262 monotime_add_msec(&t2, &t2, 1337);
6263 monotime_coarse_add_msec(&ct2, &ct2, 1337);
6264 monotime_add_msec(&t2, &t2, 1337);
6265 monotime_coarse_add_msec(&ct2, &ct2, 1337);
6266 tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
6267 tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
6268 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
6269 tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
6271 done:
6275 static void
6276 test_util_nowrap_math(void *arg)
6278 (void)arg;
6280 tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
6281 tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
6282 tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
6283 tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
6284 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
6285 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
6286 tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
6288 done:
6292 static void
6293 test_util_htonll(void *arg)
6295 (void)arg;
6296 #ifdef WORDS_BIGENDIAN
6297 const uint64_t res_be = 0x8877665544332211;
6298 #else
6299 const uint64_t res_le = 0x1122334455667788;
6300 #endif
6302 tt_u64_op(0, OP_EQ, tor_htonll(0));
6303 tt_u64_op(0, OP_EQ, tor_ntohll(0));
6304 tt_u64_op(UINT64_MAX, OP_EQ, tor_htonll(UINT64_MAX));
6305 tt_u64_op(UINT64_MAX, OP_EQ, tor_ntohll(UINT64_MAX));
6307 #ifdef WORDS_BIGENDIAN
6308 tt_u64_op(res_be, OP_EQ, tor_htonll(0x8877665544332211));
6309 tt_u64_op(res_be, OP_EQ, tor_ntohll(0x8877665544332211));
6310 #else
6311 tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211));
6312 tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211));
6313 #endif /* defined(WORDS_BIGENDIAN) */
6315 done:
6319 static void
6320 test_util_get_unquoted_path(void *arg)
6322 (void)arg;
6324 char *r = NULL;
6326 r = get_unquoted_path("\""); // "
6327 tt_ptr_op(r, OP_EQ, NULL);
6328 tor_free(r);
6330 r = get_unquoted_path("\"\"\""); // """
6331 tt_ptr_op(r, OP_EQ, NULL);
6332 tor_free(r);
6334 r = get_unquoted_path("\\\""); // \"
6335 tt_ptr_op(r, OP_EQ, NULL);
6336 tor_free(r);
6338 r = get_unquoted_path("\\\"\\\""); // \"\"
6339 tt_ptr_op(r, OP_EQ, NULL);
6340 tor_free(r);
6342 r = get_unquoted_path("A\\B\\C\""); // A\B\C"
6343 tt_ptr_op(r, OP_EQ, NULL);
6344 tor_free(r);
6346 r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
6347 tt_ptr_op(r, OP_EQ, NULL);
6348 tor_free(r);
6350 r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
6351 tt_ptr_op(r, OP_EQ, NULL);
6352 tor_free(r);
6354 r = get_unquoted_path("A\\B\"C"); // A\B"C
6355 tt_ptr_op(r, OP_EQ, NULL);
6356 tor_free(r);
6358 r = get_unquoted_path("");
6359 tt_str_op(r, OP_EQ, "");
6360 tor_free(r);
6362 r = get_unquoted_path("\"\""); // ""
6363 tt_str_op(r, OP_EQ, "");
6364 tor_free(r);
6366 r = get_unquoted_path("A\\B\\C"); // A\B\C
6367 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6368 tor_free(r);
6370 r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
6371 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6372 tor_free(r);
6374 r = get_unquoted_path("\"\\\""); // "\"
6375 tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
6376 tor_free(r);
6378 r = get_unquoted_path("\"\\\"\""); // "\""
6379 tt_str_op(r, OP_EQ, "\""); // "
6380 tor_free(r);
6382 r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
6383 tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
6384 tor_free(r);
6386 r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
6387 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6388 tor_free(r);
6390 r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
6391 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6393 done:
6394 tor_free(r);
6397 #define UTIL_LEGACY(name) \
6398 { #name, test_util_ ## name , 0, NULL, NULL }
6400 #define UTIL_TEST(name, flags) \
6401 { #name, test_util_ ## name, flags, NULL, NULL }
6403 #define COMPRESS(name, identifier) \
6404 { "compress/" #name, test_util_compress, 0, &compress_setup, \
6405 (char*)(identifier) }
6407 #define COMPRESS_CONCAT(name, identifier) \
6408 { "compress_concat/" #name, test_util_decompress_concatenated, 0, \
6409 &compress_setup, \
6410 (char*)(identifier) }
6412 #define COMPRESS_JUNK(name, identifier) \
6413 { "compress_junk/" #name, test_util_decompress_junk, 0, \
6414 &compress_setup, \
6415 (char*)(identifier) }
6417 #define COMPRESS_DOS(name, identifier) \
6418 { "compress_dos/" #name, test_util_decompress_dos, 0, \
6419 &compress_setup, \
6420 (char*)(identifier) }
6422 #ifdef _WIN32
6423 #define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
6424 #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
6425 #define UTIL_LEGACY_NO_WIN(n) UTIL_TEST_NO_WIN(n, 0)
6426 #else
6427 #define UTIL_TEST_NO_WIN(n, f) UTIL_TEST(n, (f))
6428 #define UTIL_TEST_WIN_ONLY(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
6429 #define UTIL_LEGACY_NO_WIN(n) UTIL_LEGACY(n)
6430 #endif /* defined(_WIN32) */
6432 struct testcase_t util_tests[] = {
6433 UTIL_LEGACY(time),
6434 UTIL_TEST(parse_http_time, 0),
6435 UTIL_LEGACY(config_line),
6436 UTIL_LEGACY(config_line_quotes),
6437 UTIL_LEGACY(config_line_comment_character),
6438 UTIL_LEGACY(config_line_escaped_content),
6439 UTIL_LEGACY(config_line_crlf),
6440 UTIL_LEGACY_NO_WIN(expand_filename),
6441 UTIL_LEGACY(escape_string_socks),
6442 UTIL_LEGACY(string_is_key_value),
6443 UTIL_LEGACY(strmisc),
6444 UTIL_TEST(parse_integer, 0),
6445 UTIL_LEGACY(pow2),
6446 COMPRESS(zlib, "deflate"),
6447 COMPRESS(gzip, "gzip"),
6448 COMPRESS(lzma, "x-tor-lzma"),
6449 COMPRESS(zstd, "x-zstd"),
6450 COMPRESS(zstd_nostatic, "x-zstd:nostatic"),
6451 COMPRESS(none, "identity"),
6452 COMPRESS_CONCAT(zlib, "deflate"),
6453 COMPRESS_CONCAT(gzip, "gzip"),
6454 COMPRESS_CONCAT(lzma, "x-tor-lzma"),
6455 COMPRESS_CONCAT(zstd, "x-zstd"),
6456 COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"),
6457 COMPRESS_CONCAT(none, "identity"),
6458 COMPRESS_JUNK(zlib, "deflate"),
6459 COMPRESS_JUNK(gzip, "gzip"),
6460 COMPRESS_JUNK(lzma, "x-tor-lzma"),
6461 COMPRESS_DOS(zlib, "deflate"),
6462 COMPRESS_DOS(gzip, "gzip"),
6463 COMPRESS_DOS(lzma, "x-tor-lzma"),
6464 COMPRESS_DOS(zstd, "x-zstd"),
6465 COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"),
6466 UTIL_TEST(gzip_compression_bomb, TT_FORK),
6467 UTIL_LEGACY(datadir),
6468 UTIL_LEGACY(memarea),
6469 UTIL_LEGACY(control_formats),
6470 UTIL_LEGACY(mmap),
6471 UTIL_TEST(sscanf, TT_FORK),
6472 UTIL_LEGACY(format_time_interval),
6473 UTIL_LEGACY(path_is_relative),
6474 UTIL_LEGACY(strtok),
6475 UTIL_LEGACY(di_ops),
6476 UTIL_TEST(di_map, 0),
6477 UTIL_TEST(round_to_next_multiple_of, 0),
6478 UTIL_TEST(laplace, 0),
6479 UTIL_TEST(clamp_double_to_int64, 0),
6480 UTIL_TEST(find_str_at_start_of_line, 0),
6481 UTIL_TEST(string_is_C_identifier, 0),
6482 UTIL_TEST(string_is_utf8, 0),
6483 UTIL_TEST(asprintf, 0),
6484 UTIL_TEST(listdir, 0),
6485 UTIL_TEST(parent_dir, 0),
6486 UTIL_TEST(ftruncate, 0),
6487 UTIL_TEST(nowrap_math, 0),
6488 UTIL_TEST(num_cpus, 0),
6489 UTIL_TEST_WIN_ONLY(load_win_lib, 0),
6490 UTIL_TEST_NO_WIN(exit_status, 0),
6491 UTIL_TEST_NO_WIN(string_from_pipe, 0),
6492 UTIL_TEST(format_hex_number, 0),
6493 UTIL_TEST(format_dec_number, 0),
6494 UTIL_TEST(join_win_cmdline, 0),
6495 UTIL_TEST(split_lines, 0),
6496 UTIL_TEST(n_bits_set, 0),
6497 UTIL_TEST(eat_whitespace, 0),
6498 UTIL_TEST(sl_new_from_text_lines, 0),
6499 UTIL_TEST(envnames, 0),
6500 UTIL_TEST(make_environment, 0),
6501 UTIL_TEST(set_env_var_in_sl, 0),
6502 UTIL_TEST(read_file_eof_tiny_limit, 0),
6503 UTIL_TEST(read_file_eof_one_loop_a, 0),
6504 UTIL_TEST(read_file_eof_one_loop_b, 0),
6505 UTIL_TEST(read_file_eof_two_loops, 0),
6506 UTIL_TEST(read_file_eof_two_loops_b, 0),
6507 UTIL_TEST(read_file_eof_zero_bytes, 0),
6508 UTIL_TEST(read_file_endlines, 0),
6509 UTIL_TEST(write_chunks_to_file, 0),
6510 UTIL_TEST(mathlog, 0),
6511 UTIL_TEST(fraction, 0),
6512 UTIL_TEST(weak_random, 0),
6513 { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
6514 (void*)"4" },
6515 { "socket_ipv6", test_util_socket, TT_FORK,
6516 &passthrough_setup, (void*)"6" },
6517 { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
6518 (void*)"0" },
6519 { "socketpair_ersatz", test_util_socketpair, TT_FORK,
6520 &passthrough_setup, (void*)"1" },
6521 UTIL_TEST(max_mem, 0),
6522 UTIL_TEST(hostname_validation, 0),
6523 UTIL_TEST(dest_validation_edgecase, 0),
6524 UTIL_TEST(ipv4_validation, 0),
6525 UTIL_TEST(writepid, 0),
6526 UTIL_TEST(get_avail_disk_space, 0),
6527 UTIL_TEST(touch_file, 0),
6528 UTIL_TEST_NO_WIN(pwdb, TT_FORK),
6529 UTIL_TEST(calloc_check, 0),
6530 UTIL_TEST(monotonic_time, 0),
6531 UTIL_TEST(monotonic_time_ratchet, TT_FORK),
6532 UTIL_TEST(monotonic_time_zero, 0),
6533 UTIL_TEST(monotonic_time_add_msec, 0),
6534 UTIL_TEST(htonll, 0),
6535 UTIL_TEST(get_unquoted_path, 0),
6536 END_OF_TESTCASES