Capture "Result does not fit in tor_timegm()" warnings in util tests
[tor.git] / src / test / test_util.c
blob35fd02b1e921ab9212d7308da1f5efbe6b72f1d7
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2017, 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 #include "or.h"
12 #include "buffers.h"
13 #include "config.h"
14 #include "control.h"
15 #include "test.h"
16 #include "memarea.h"
17 #include "util_process.h"
18 #include "log_test_helpers.h"
20 #ifdef HAVE_PWD_H
21 #include <pwd.h>
22 #endif
23 #ifdef HAVE_SYS_UTIME_H
24 #include <sys/utime.h>
25 #endif
26 #ifdef HAVE_UTIME_H
27 #include <utime.h>
28 #endif
29 #ifdef _WIN32
30 #include <tchar.h>
31 #endif
32 #include <math.h>
33 #include <ctype.h>
34 #include <float.h>
36 #define INFINITY_DBL ((double)INFINITY)
37 #define NAN_DBL ((double)NAN)
39 /* XXXX this is a minimal wrapper to make the unit tests compile with the
40 * changed tor_timegm interface. */
41 static time_t
42 tor_timegm_wrapper(const struct tm *tm)
44 time_t t;
45 if (tor_timegm(tm, &t) < 0)
46 return -1;
47 return t;
50 #define tor_timegm tor_timegm_wrapper
52 static void
53 test_util_read_until_eof_impl(const char *fname, size_t file_len,
54 size_t read_limit)
56 char *fifo_name = NULL;
57 char *test_str = NULL;
58 char *str = NULL;
59 size_t sz = 9999999;
60 int fd = -1;
61 int r;
63 fifo_name = tor_strdup(get_fname(fname));
64 test_str = tor_malloc(file_len);
65 crypto_rand(test_str, file_len);
67 r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
68 tt_int_op(r, OP_EQ, 0);
70 fd = open(fifo_name, O_RDONLY|O_BINARY);
71 tt_int_op(fd, OP_GE, 0);
72 str = read_file_to_str_until_eof(fd, read_limit, &sz);
73 tt_ptr_op(str, OP_NE, NULL);
75 if (read_limit < file_len)
76 tt_int_op(sz, OP_EQ, read_limit);
77 else
78 tt_int_op(sz, OP_EQ, file_len);
80 tt_mem_op(test_str, OP_EQ, str, sz);
81 tt_int_op(str[sz], OP_EQ, '\0');
83 done:
84 unlink(fifo_name);
85 tor_free(fifo_name);
86 tor_free(test_str);
87 tor_free(str);
88 if (fd >= 0)
89 close(fd);
92 static void
93 test_util_read_file_eof_tiny_limit(void *arg)
95 (void)arg;
96 // purposely set limit shorter than what we wrote to the FIFO to
97 // test the maximum, and that it puts the NUL in the right spot
99 test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
102 static void
103 test_util_read_file_eof_one_loop_a(void *arg)
105 (void)arg;
106 test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
109 static void
110 test_util_read_file_eof_one_loop_b(void *arg)
112 (void)arg;
113 test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
116 static void
117 test_util_read_file_eof_two_loops(void *arg)
119 (void)arg;
120 // write more than 1024 bytes to the FIFO to test two passes through
121 // the loop in the method; if the re-alloc size is changed this
122 // should be updated as well.
124 test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
127 static void
128 test_util_read_file_eof_two_loops_b(void *arg)
130 (void)arg;
132 test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
135 static void
136 test_util_read_file_eof_zero_bytes(void *arg)
138 (void)arg;
139 // zero-byte fifo
140 test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
143 /* Test the basic expected behaviour for write_chunks_to_file.
144 * NOTE: This will need to be updated if we ever change the tempfile location
145 * or extension */
146 static void
147 test_util_write_chunks_to_file(void *arg)
149 char *fname = NULL;
150 char *tempname = NULL;
151 char *str = NULL;
152 int r;
153 struct stat st;
155 /* These should be two different sizes to ensure the data is different
156 * between the data file and the temp file's 'known string' */
157 int temp_str_len = 1024;
158 int data_str_len = 512;
159 char *data_str = tor_malloc(data_str_len);
160 char *temp_str = tor_malloc(temp_str_len);
162 smartlist_t *chunks = smartlist_new();
163 sized_chunk_t c = {data_str, data_str_len/2};
164 sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
165 (void)arg;
167 crypto_rand(temp_str, temp_str_len);
168 crypto_rand(data_str, data_str_len);
170 // Ensure it can write multiple chunks
172 smartlist_add(chunks, &c);
173 smartlist_add(chunks, &c2);
176 * Check if it writes using a tempfile
178 fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
179 tor_asprintf(&tempname, "%s.tmp", fname);
181 // write a known string to a file where the tempfile will be
182 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
183 tt_int_op(r, OP_EQ, 0);
185 // call write_chunks_to_file
186 r = write_chunks_to_file(fname, chunks, 1, 0);
187 tt_int_op(r, OP_EQ, 0);
189 // assert the file has been written (expected size)
190 str = read_file_to_str(fname, RFTS_BIN, &st);
191 tt_assert(str != NULL);
192 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
193 tt_mem_op(data_str, OP_EQ, str, data_str_len);
194 tor_free(str);
196 // assert that the tempfile is removed (should not leave artifacts)
197 str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
198 tt_assert(str == NULL);
200 // Remove old testfile for second test
201 r = unlink(fname);
202 tt_int_op(r, OP_EQ, 0);
203 tor_free(fname);
204 tor_free(tempname);
207 * Check if it skips using a tempfile with flags
209 fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
210 tor_asprintf(&tempname, "%s.tmp", fname);
212 // write a known string to a file where the tempfile will be
213 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
214 tt_int_op(r, OP_EQ, 0);
216 // call write_chunks_to_file with no_tempfile = true
217 r = write_chunks_to_file(fname, chunks, 1, 1);
218 tt_int_op(r, OP_EQ, 0);
220 // assert the file has been written (expected size)
221 str = read_file_to_str(fname, RFTS_BIN, &st);
222 tt_assert(str != NULL);
223 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
224 tt_mem_op(data_str, OP_EQ, str, data_str_len);
225 tor_free(str);
227 // assert the tempfile still contains the known string
228 str = read_file_to_str(tempname, RFTS_BIN, &st);
229 tt_assert(str != NULL);
230 tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
231 tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
233 done:
234 unlink(fname);
235 unlink(tempname);
236 smartlist_free(chunks);
237 tor_free(fname);
238 tor_free(tempname);
239 tor_free(str);
240 tor_free(data_str);
241 tor_free(temp_str);
244 #define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
245 /** test the minimum set of struct tm fields needed for a unique epoch value
246 * this is also the set we use to test tor_timegm */
247 #define TM_EQUAL(a, b) \
248 TT_STMT_BEGIN \
249 _TFE(a, b, tm_year); \
250 _TFE(a, b, tm_mon ); \
251 _TFE(a, b, tm_mday); \
252 _TFE(a, b, tm_hour); \
253 _TFE(a, b, tm_min ); \
254 _TFE(a, b, tm_sec ); \
255 TT_STMT_END
257 static void
258 test_util_time(void *arg)
260 struct timeval start, end;
261 struct tm a_time, b_time;
262 char timestr[128];
263 time_t t_res;
264 int i;
265 struct timeval tv;
267 /* Test tv_udiff and tv_mdiff */
269 (void)arg;
270 start.tv_sec = 5;
271 start.tv_usec = 5000;
273 end.tv_sec = 5;
274 end.tv_usec = 5000;
276 tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
277 tt_int_op(0L,OP_EQ, tv_mdiff(&start, &end));
278 tt_int_op(0L,OP_EQ, tv_udiff(&end, &start));
279 tt_int_op(0L,OP_EQ, tv_mdiff(&end, &start));
281 end.tv_usec = 7000;
283 tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
284 tt_int_op(2L,OP_EQ, tv_mdiff(&start, &end));
285 tt_int_op(-2000L,OP_EQ, tv_udiff(&end, &start));
286 tt_int_op(-2L,OP_EQ, tv_mdiff(&end, &start));
288 end.tv_sec = 6;
290 tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
291 tt_int_op(1002L,OP_EQ, tv_mdiff(&start, &end));
292 tt_int_op(-1002000L,OP_EQ, tv_udiff(&end, &start));
293 tt_int_op(-1002L,OP_EQ, tv_mdiff(&end, &start));
295 end.tv_usec = 0;
297 tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
298 tt_int_op(995L,OP_EQ, tv_mdiff(&start, &end));
299 tt_int_op(-995000L,OP_EQ, tv_udiff(&end, &start));
300 tt_int_op(-995L,OP_EQ, tv_mdiff(&end, &start));
302 end.tv_sec = 4;
304 tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
305 tt_int_op(-1005L,OP_EQ, tv_mdiff(&start, &end));
306 tt_int_op(1005000L,OP_EQ, tv_udiff(&end, &start));
307 tt_int_op(1005L,OP_EQ, tv_mdiff(&end, &start));
309 /* Negative tv_sec values, these will break on platforms where tv_sec is
310 * unsigned */
312 end.tv_sec = -10;
314 tt_int_op(-15005000L,OP_EQ, tv_udiff(&start, &end));
315 tt_int_op(-15005L,OP_EQ, tv_mdiff(&start, &end));
316 tt_int_op(15005000L,OP_EQ, tv_udiff(&end, &start));
317 tt_int_op(15005L,OP_EQ, tv_mdiff(&end, &start));
319 start.tv_sec = -100;
321 tt_int_op(89995000L,OP_EQ, tv_udiff(&start, &end));
322 tt_int_op(89995L,OP_EQ, tv_mdiff(&start, &end));
323 tt_int_op(-89995000L,OP_EQ, tv_udiff(&end, &start));
324 tt_int_op(-89995L,OP_EQ, tv_mdiff(&end, &start));
326 /* Test that tv_usec values round away from zero when converted to msec */
327 start.tv_sec = 0;
328 start.tv_usec = 0;
329 end.tv_sec = 10;
330 end.tv_usec = 499;
332 tt_int_op(10000499L, OP_EQ, tv_udiff(&start, &end));
333 tt_int_op(10000L, OP_EQ, tv_mdiff(&start, &end));
334 tt_int_op(-10000499L, OP_EQ, tv_udiff(&end, &start));
335 tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
337 start.tv_sec = 0;
338 start.tv_usec = 0;
339 end.tv_sec = 10;
340 end.tv_usec = 500;
342 tt_int_op(10000500L, OP_EQ, tv_udiff(&start, &end));
343 tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
344 tt_int_op(-10000500L, OP_EQ, tv_udiff(&end, &start));
345 tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
347 start.tv_sec = 0;
348 start.tv_usec = 0;
349 end.tv_sec = 10;
350 end.tv_usec = 501;
352 tt_int_op(10000501L, OP_EQ, tv_udiff(&start, &end));
353 tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
354 tt_int_op(-10000501L, OP_EQ, tv_udiff(&end, &start));
355 tt_int_op(-10001L, OP_EQ, tv_mdiff(&end, &start));
357 /* Overflow conditions */
359 #ifdef _WIN32
360 /* Would you believe that tv_sec is a long on windows? Of course you would.*/
361 #define TV_SEC_MAX LONG_MAX
362 #define TV_SEC_MIN LONG_MIN
363 #else
364 /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
365 * Which means TIME_MAX is not actually the maximum value of tv_sec.
366 * But that's ok for the moment, because the code correctly performs 64-bit
367 * calculations internally, then catches the overflow. */
368 #define TV_SEC_MAX TIME_MAX
369 #define TV_SEC_MIN TIME_MIN
370 #endif /* defined(_WIN32) */
372 /* Assume tv_usec is an unsigned integer until proven otherwise */
373 #define TV_USEC_MAX UINT_MAX
374 #define TOR_USEC_PER_SEC 1000000
376 /* Overflows in the result type */
378 /* All comparisons work */
379 start.tv_sec = 0;
380 start.tv_usec = 0;
381 end.tv_sec = LONG_MAX/1000 - 2;
382 end.tv_usec = 0;
384 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
385 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
386 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
387 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
389 start.tv_sec = 0;
390 start.tv_usec = 0;
391 end.tv_sec = LONG_MAX/1000000 - 1;
392 end.tv_usec = 0;
394 tt_int_op(end.tv_sec*1000000L, OP_EQ, tv_udiff(&start, &end));
395 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
396 tt_int_op(-end.tv_sec*1000000L, OP_EQ, tv_udiff(&end, &start));
397 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
399 /* No comparisons work */
400 start.tv_sec = 0;
401 start.tv_usec = 0;
402 end.tv_sec = LONG_MAX/1000 + 1;
403 end.tv_usec = 0;
405 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
406 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
407 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
408 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
410 start.tv_sec = 0;
411 start.tv_usec = 0;
412 end.tv_sec = LONG_MAX/1000000 + 1;
413 end.tv_usec = 0;
415 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
416 tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
417 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
418 tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
420 start.tv_sec = 0;
421 start.tv_usec = 0;
422 end.tv_sec = LONG_MAX/1000;
423 end.tv_usec = TOR_USEC_PER_SEC;
425 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
426 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
427 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
428 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
430 start.tv_sec = 0;
431 start.tv_usec = 0;
432 end.tv_sec = LONG_MAX/1000000;
433 end.tv_usec = TOR_USEC_PER_SEC;
435 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
436 tt_int_op((end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&start, &end));
437 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
438 tt_int_op(-(end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&end, &start));
440 /* Overflows on comparison to zero */
442 start.tv_sec = 0;
443 start.tv_usec = 0;
445 end.tv_sec = TV_SEC_MAX;
446 end.tv_usec = 0;
448 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
449 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
450 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
451 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
453 end.tv_sec = TV_SEC_MAX;
454 end.tv_usec = TOR_USEC_PER_SEC;
456 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
457 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
458 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
459 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
461 end.tv_sec = 0;
462 end.tv_usec = TV_USEC_MAX;
464 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
465 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
466 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
467 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
469 end.tv_sec = TV_SEC_MAX;
470 end.tv_usec = TV_USEC_MAX;
472 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
473 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
474 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
475 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
477 end.tv_sec = 0;
478 end.tv_usec = 0;
480 start.tv_sec = TV_SEC_MIN;
481 start.tv_usec = 0;
483 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
484 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
485 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
486 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
488 start.tv_sec = TV_SEC_MIN;
489 start.tv_usec = TOR_USEC_PER_SEC;
491 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
492 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
493 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
494 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
496 start.tv_sec = TV_SEC_MIN;
497 start.tv_usec = TV_USEC_MAX;
499 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
500 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
501 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
502 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
504 /* overflows on comparison to maxima / minima */
506 start.tv_sec = TV_SEC_MIN;
507 start.tv_usec = 0;
509 end.tv_sec = TV_SEC_MAX;
510 end.tv_usec = 0;
512 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
513 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
514 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
515 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
517 end.tv_sec = TV_SEC_MAX;
518 end.tv_usec = TOR_USEC_PER_SEC;
520 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
521 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
522 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
523 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
525 end.tv_sec = TV_SEC_MAX;
526 end.tv_usec = 0;
528 start.tv_sec = TV_SEC_MIN;
529 start.tv_usec = 0;
531 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
532 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
533 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
534 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
536 start.tv_sec = TV_SEC_MIN;
537 start.tv_usec = TOR_USEC_PER_SEC;
539 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
540 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
541 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
542 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
544 /* overflows on comparison to maxima / minima with extra usec */
546 start.tv_sec = TV_SEC_MIN;
547 start.tv_usec = TOR_USEC_PER_SEC;
549 end.tv_sec = TV_SEC_MAX;
550 end.tv_usec = 0;
552 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
553 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
554 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
555 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
557 end.tv_sec = TV_SEC_MAX;
558 end.tv_usec = TOR_USEC_PER_SEC;
560 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
561 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
562 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
563 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
565 end.tv_sec = TV_SEC_MAX;
566 end.tv_usec = TOR_USEC_PER_SEC;
568 start.tv_sec = TV_SEC_MIN;
569 start.tv_usec = 0;
571 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
572 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
573 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
574 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
576 start.tv_sec = TV_SEC_MIN;
577 start.tv_usec = TOR_USEC_PER_SEC;
579 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
580 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
581 tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
582 tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
584 /* Test tor_timegm & tor_gmtime_r */
586 /* The test values here are confirmed to be correct on a platform
587 * with a working timegm & gmtime_r. */
589 /* Start with known-zero a_time and b_time.
590 * This avoids passing uninitialised values to TM_EQUAL in a_time.
591 * Zeroing may not be needed for b_time, as long as tor_gmtime_r
592 * never reads the existing values in the structure.
593 * But we really don't want intermittently failing tests. */
594 memset(&a_time, 0, sizeof(struct tm));
595 memset(&b_time, 0, sizeof(struct tm));
597 a_time.tm_year = 2003-1900;
598 a_time.tm_mon = 7;
599 a_time.tm_mday = 30;
600 a_time.tm_hour = 6;
601 a_time.tm_min = 14;
602 a_time.tm_sec = 55;
603 t_res = 1062224095UL;
604 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
605 tor_gmtime_r(&t_res, &b_time);
606 TM_EQUAL(a_time, b_time);
608 a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
609 t_res = 1093846495UL;
610 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
611 tor_gmtime_r(&t_res, &b_time);
612 TM_EQUAL(a_time, b_time);
614 a_time.tm_mon = 1; /* Try a leap year, in feb. */
615 a_time.tm_mday = 10;
616 t_res = 1076393695UL;
617 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
618 tor_gmtime_r(&t_res, &b_time);
619 TM_EQUAL(a_time, b_time);
621 a_time.tm_mon = 0;
622 t_res = 1073715295UL;
623 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
624 tor_gmtime_r(&t_res, &b_time);
625 TM_EQUAL(a_time, b_time);
627 /* This value is in range with 32 bit and 64 bit time_t */
628 a_time.tm_year = 2037-1900;
629 t_res = 2115180895UL;
630 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
631 tor_gmtime_r(&t_res, &b_time);
632 TM_EQUAL(a_time, b_time);
634 /* This value is out of range with 32 bit time_t, but in range for 64 bit
635 * time_t */
636 a_time.tm_year = 2039-1900;
637 #if SIZEOF_TIME_T == 4
638 setup_capture_of_logs(LOG_WARN);
639 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
640 expect_single_log_msg_containing("Result does not fit in tor_timegm");
641 teardown_capture_of_logs();
642 #elif SIZEOF_TIME_T == 8
643 t_res = 2178252895UL;
644 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
645 tor_gmtime_r(&t_res, &b_time);
646 TM_EQUAL(a_time, b_time);
647 #endif /* SIZEOF_TIME_T == 4 || ... */
649 /* Test tor_timegm out of range */
651 /* The below tests will all cause a BUG message, so we capture, suppress,
652 * and detect. */
653 #define CAPTURE() do { \
654 setup_full_capture_of_logs(LOG_WARN); \
655 } while (0)
656 #define CHECK_TIMEGM_WARNING(msg) do { \
657 expect_log_msg_containing(msg); \
658 tt_int_op(1, OP_EQ, smartlist_len(mock_saved_logs())); \
659 teardown_capture_of_logs(); \
660 } while (0)
662 #define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
663 CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")
665 /* year */
667 /* Wrong year < 1970 */
668 a_time.tm_year = 1969-1900;
669 CAPTURE();
670 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
671 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
673 a_time.tm_year = -1-1900;
674 CAPTURE();
675 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
676 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
678 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
679 a_time.tm_year = -1*(1 << 16);
680 CAPTURE();
681 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
682 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
684 /* one of the smallest tm_year values my 64 bit system supports:
685 * t_res = -9223372036854775LL without clamping */
686 a_time.tm_year = -292275055-1900;
687 CAPTURE();
688 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
689 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
691 a_time.tm_year = INT32_MIN;
692 CAPTURE();
693 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
694 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
695 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
697 #if SIZEOF_INT == 8
698 a_time.tm_year = -1*(1 << 48);
699 CAPTURE();
700 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
701 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
703 /* while unlikely, the system's gmtime(_r) could return
704 * a "correct" retrospective gregorian negative year value,
705 * which I'm pretty sure is:
706 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
707 * 730485 is the number of days in two millenia, including leap days */
708 a_time.tm_year = -292277022657-1900;
709 CAPTURE();
710 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
711 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
713 a_time.tm_year = INT64_MIN;
714 CAPTURE();
715 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
716 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
717 #endif /* SIZEOF_INT == 8 */
719 /* Wrong year >= INT32_MAX - 1900 */
720 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
721 a_time.tm_year = INT32_MAX-1900;
722 CAPTURE();
723 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
724 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
726 a_time.tm_year = INT32_MAX;
727 CAPTURE();
728 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
729 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
730 #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
732 #if SIZEOF_INT == 8
733 /* one of the largest tm_year values my 64 bit system supports */
734 a_time.tm_year = 292278994-1900;
735 CAPTURE();
736 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
737 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
739 /* while unlikely, the system's gmtime(_r) could return
740 * a "correct" proleptic gregorian year value,
741 * which I'm pretty sure is:
742 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
743 * 730485 is the number of days in two millenia, including leap days */
744 a_time.tm_year = 292277026596-1900;
745 CAPTURE();
746 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
747 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
749 a_time.tm_year = INT64_MAX-1900;
750 CAPTURE();
751 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
752 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
754 a_time.tm_year = INT64_MAX;
755 CAPTURE();
756 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
757 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
758 #endif /* SIZEOF_INT == 8 */
760 /* month */
761 a_time.tm_year = 2007-1900; /* restore valid year */
763 a_time.tm_mon = 12; /* Wrong month, it's 0-based */
764 CAPTURE();
765 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
766 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
768 a_time.tm_mon = -1; /* Wrong month */
769 CAPTURE();
770 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
771 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
773 /* day */
774 a_time.tm_mon = 6; /* Try July */
775 a_time.tm_mday = 32; /* Wrong day */
776 CAPTURE();
777 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
778 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
780 a_time.tm_mon = 5; /* Try June */
781 a_time.tm_mday = 31; /* Wrong day */
782 CAPTURE();
783 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
784 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
786 a_time.tm_year = 2008-1900; /* Try a leap year */
787 a_time.tm_mon = 1; /* in feb. */
788 a_time.tm_mday = 30; /* Wrong day */
789 CAPTURE();
790 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
791 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
793 a_time.tm_year = 2011-1900; /* Try a non-leap year */
794 a_time.tm_mon = 1; /* in feb. */
795 a_time.tm_mday = 29; /* Wrong day */
796 CAPTURE();
797 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
798 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
800 a_time.tm_mday = 0; /* Wrong day, it's 1-based (to be different) */
801 CAPTURE();
802 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
803 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
805 /* hour */
806 a_time.tm_mday = 3; /* restore valid month day */
808 a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
809 CAPTURE();
810 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
811 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
813 a_time.tm_hour = -1; /* Wrong hour */
814 CAPTURE();
815 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
816 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
818 /* minute */
819 a_time.tm_hour = 22; /* restore valid hour */
821 a_time.tm_min = 60; /* Wrong minute, it's 0-based */
822 CAPTURE();
823 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
824 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
826 a_time.tm_min = -1; /* Wrong minute */
827 CAPTURE();
828 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
829 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
831 /* second */
832 a_time.tm_min = 37; /* restore valid minute */
834 a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
835 CAPTURE();
836 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
837 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
839 a_time.tm_sec = -1; /* Wrong second */
840 CAPTURE();
841 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
842 CHECK_TIMEGM_ARG_OUT_OF_RANGE();
844 /* Test tor_gmtime_r out of range */
846 /* time_t < 0 yields a year clamped to 1 or 1970,
847 * depending on whether the implementation of the system gmtime(_r)
848 * sets struct tm (1) or not (1970) */
849 t_res = -1;
850 tor_gmtime_r(&t_res, &b_time);
851 tt_assert(b_time.tm_year == (1970-1900) ||
852 b_time.tm_year == (1969-1900));
854 if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
855 t_res = -1*(1 << 30);
856 tor_gmtime_r(&t_res, &b_time);
857 tt_assert(b_time.tm_year == (1970-1900) ||
858 b_time.tm_year == (1935-1900));
860 t_res = INT32_MIN;
861 tor_gmtime_r(&t_res, &b_time);
862 tt_assert(b_time.tm_year == (1970-1900) ||
863 b_time.tm_year == (1901-1900));
866 #if SIZEOF_TIME_T == 8
868 /* one of the smallest tm_year values my 64 bit system supports:
869 * b_time.tm_year == (-292275055LL-1900LL) without clamping */
870 t_res = -9223372036854775LL;
871 tor_gmtime_r(&t_res, &b_time);
872 tt_assert(b_time.tm_year == (1970-1900) ||
873 b_time.tm_year == (1-1900));
875 /* while unlikely, the system's gmtime(_r) could return
876 * a "correct" retrospective gregorian negative year value,
877 * which I'm pretty sure is:
878 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
879 * 730485 is the number of days in two millenia, including leap days
880 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
881 t_res = INT64_MIN;
882 CAPTURE();
883 tor_gmtime_r(&t_res, &b_time);
884 if (! (b_time.tm_year == (1970-1900) ||
885 b_time.tm_year == (1-1900))) {
886 tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
888 if (b_time.tm_year != 1970-1900) {
889 CHECK_TIMEGM_WARNING("Rounding up to ");
890 } else {
891 teardown_capture_of_logs();
894 #endif /* SIZEOF_TIME_T == 8 */
896 /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
897 * depending on whether the implementation of the system gmtime(_r)
898 * sets struct tm (9999) or not (2037) */
899 #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
901 t_res = 3*(1 << 29);
902 tor_gmtime_r(&t_res, &b_time);
903 tt_assert(b_time.tm_year == (2021-1900));
905 t_res = INT32_MAX;
906 tor_gmtime_r(&t_res, &b_time);
907 tt_assert(b_time.tm_year == (2037-1900) ||
908 b_time.tm_year == (2038-1900));
910 #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */
912 #if SIZEOF_TIME_T == 8
914 /* one of the largest tm_year values my 64 bit system supports:
915 * b_time.tm_year == (292278994L-1900L) without clamping */
916 t_res = 9223372036854775LL;
917 tor_gmtime_r(&t_res, &b_time);
918 tt_assert(b_time.tm_year == (2037-1900) ||
919 b_time.tm_year == (9999-1900));
921 /* while unlikely, the system's gmtime(_r) could return
922 * a "correct" proleptic gregorian year value,
923 * which I'm pretty sure is:
924 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
925 * 730485 is the number of days in two millenia, including leap days
926 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
927 t_res = INT64_MAX;
928 CAPTURE();
929 tor_gmtime_r(&t_res, &b_time);
930 CHECK_TIMEGM_WARNING("Rounding down to ");
932 tt_assert(b_time.tm_year == (2037-1900) ||
933 b_time.tm_year == (9999-1900));
935 #endif /* SIZEOF_TIME_T == 8 */
937 /* Test {format,parse}_rfc1123_time */
939 format_rfc1123_time(timestr, 0);
940 tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
941 format_rfc1123_time(timestr, (time_t)1091580502UL);
942 tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
944 t_res = 0;
945 i = parse_rfc1123_time(timestr, &t_res);
946 tt_int_op(0,OP_EQ, i);
947 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
949 /* This value is in range with 32 bit and 64 bit time_t */
950 format_rfc1123_time(timestr, (time_t)2080000000UL);
951 tt_str_op("Fri, 30 Nov 2035 01:46:40 GMT",OP_EQ, timestr);
953 t_res = 0;
954 i = parse_rfc1123_time(timestr, &t_res);
955 tt_int_op(0,OP_EQ, i);
956 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
958 /* This value is out of range with 32 bit time_t, but in range for 64 bit
959 * time_t */
960 format_rfc1123_time(timestr, (time_t)2150000000UL);
961 #if SIZEOF_TIME_T == 4
962 #if 0
963 /* Wrapping around will have made it this. */
964 /* On windows, at least, this is clipped to 1 Jan 1970. ??? */
965 tt_str_op("Sat, 11 Jan 1902 23:45:04 GMT",OP_EQ, timestr);
966 #endif
967 /* Make sure that the right date doesn't parse. */
968 strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr));
970 t_res = 0;
971 CAPTURE();
972 i = parse_rfc1123_time(timestr, &t_res);
973 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
974 tt_int_op(-1,OP_EQ, i);
975 #elif SIZEOF_TIME_T == 8
976 tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr);
978 t_res = 0;
979 i = parse_rfc1123_time(timestr, &t_res);
980 tt_int_op(0,OP_EQ, i);
981 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
982 #endif /* SIZEOF_TIME_T == 4 || ... */
984 /* The timezone doesn't matter */
985 t_res = 0;
986 tt_int_op(0,OP_EQ,
987 parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
988 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
989 tt_int_op(-1,OP_EQ,
990 parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
991 tt_int_op(-1,OP_EQ,
992 parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
993 tt_int_op(-1,OP_EQ,
994 parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
995 tt_int_op(-1,OP_EQ,
996 parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
997 tt_int_op(-1,OP_EQ,
998 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
999 tt_int_op(-1,OP_EQ,
1000 parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
1001 tt_int_op(-1,OP_EQ,
1002 parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
1003 tt_int_op(-1,OP_EQ,
1004 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
1005 tt_int_op(-1,OP_EQ,
1006 parse_rfc1123_time("Wed, 30 Mar 1900 23:59:59 GMT", &t_res));
1008 /* Leap year. */
1009 tt_int_op(-1,OP_EQ,
1010 parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
1011 tt_int_op(0,OP_EQ,
1012 parse_rfc1123_time("Wed, 29 Feb 2012 16:00:00 GMT", &t_res));
1014 /* Leap second plus one */
1015 tt_int_op(-1,OP_EQ,
1016 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
1018 /* Test parse_iso_time */
1020 t_res = 0;
1021 i = parse_iso_time("", &t_res);
1022 tt_int_op(-1,OP_EQ, i);
1023 t_res = 0;
1024 i = parse_iso_time("2004-08-32 00:48:22", &t_res);
1025 tt_int_op(-1,OP_EQ, i);
1026 t_res = 0;
1027 i = parse_iso_time("1969-08-03 00:48:22", &t_res);
1028 tt_int_op(-1,OP_EQ, i);
1030 t_res = 0;
1031 i = parse_iso_time("2004-08-04 00:48:22", &t_res);
1032 tt_int_op(0,OP_EQ, i);
1033 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1034 t_res = 0;
1035 i = parse_iso_time("2004-8-4 0:48:22", &t_res);
1036 tt_int_op(0,OP_EQ, i);
1037 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1039 /* This value is in range with 32 bit and 64 bit time_t */
1040 t_res = 0;
1041 i = parse_iso_time("2035-11-30 01:46:40", &t_res);
1042 tt_int_op(0,OP_EQ, i);
1043 tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1045 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1046 * time_t */
1047 t_res = 0;
1048 i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1049 #if SIZEOF_TIME_T == 4
1050 CAPTURE();
1051 tt_int_op(-1,OP_EQ, i);
1052 CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1053 #elif SIZEOF_TIME_T == 8
1054 tt_int_op(0,OP_EQ, i);
1055 tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1056 #endif /* SIZEOF_TIME_T == 4 || ... */
1058 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
1059 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
1060 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
1061 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
1062 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
1063 tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
1064 tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
1065 tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
1066 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
1067 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
1068 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
1070 /* but... that _is_ acceptable if we aren't being strict. */
1071 t_res = 0;
1072 i = parse_iso_time_("2004-08-04 00:48:22XYZ", &t_res, 0, 0);
1073 tt_int_op(0,OP_EQ, i);
1074 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1076 /* try nospace variant. */
1077 t_res = 0;
1078 i = parse_iso_time_nospace("2004-08-04T00:48:22", &t_res);
1079 tt_int_op(0,OP_EQ, i);
1080 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1082 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04T00:48:22", &t_res));
1083 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04 00:48:22", &t_res));
1084 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04x00:48:22", &t_res));
1085 tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04x00:48:22", &t_res));
1087 /* Test tor_gettimeofday */
1089 end.tv_sec = 4;
1090 end.tv_usec = 999990;
1091 start.tv_sec = 1;
1092 start.tv_usec = 500;
1094 tor_gettimeofday(&start);
1095 /* now make sure time works. */
1096 tor_gettimeofday(&end);
1097 /* We might've timewarped a little. */
1098 tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
1100 /* Test format_iso_time */
1102 tv.tv_sec = (time_t)1326296338UL;
1103 tv.tv_usec = 3060;
1104 format_iso_time(timestr, (time_t)tv.tv_sec);
1105 tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
1106 /* The output of format_local_iso_time will vary by timezone, and setting
1107 our timezone for testing purposes would be a nontrivial flaky pain.
1108 Skip this test for now.
1109 format_local_iso_time(timestr, tv.tv_sec);
1110 test_streq("2012-01-11 10:38:58", timestr);
1112 format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
1113 tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
1114 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
1115 format_iso_time_nospace_usec(timestr, &tv);
1116 tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
1117 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
1119 tv.tv_usec = 0;
1120 /* This value is in range with 32 bit and 64 bit time_t */
1121 tv.tv_sec = (time_t)2080000000UL;
1122 format_iso_time(timestr, (time_t)tv.tv_sec);
1123 tt_str_op("2035-11-30 01:46:40",OP_EQ, timestr);
1125 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1126 * time_t */
1127 tv.tv_sec = (time_t)2150000000UL;
1128 format_iso_time(timestr, (time_t)tv.tv_sec);
1129 #if SIZEOF_TIME_T == 4
1130 /* format_iso_time should indicate failure on overflow, but it doesn't yet.
1131 * Hopefully #18480 will improve the failure semantics in this case.
1132 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1134 #elif SIZEOF_TIME_T == 8
1135 #ifndef _WIN32
1136 /* This SHOULD work on windows too; see bug #18665 */
1137 tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1138 #endif
1139 #endif /* SIZEOF_TIME_T == 4 || ... */
1141 #undef CAPTURE
1142 #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE
1144 done:
1145 teardown_capture_of_logs();
1148 static void
1149 test_util_parse_http_time(void *arg)
1151 struct tm a_time;
1152 char b[ISO_TIME_LEN+1];
1153 (void)arg;
1155 #define T(s) do { \
1156 format_iso_time(b, tor_timegm(&a_time)); \
1157 tt_str_op(b, OP_EQ, (s)); \
1158 b[0]='\0'; \
1159 } while (0)
1161 /* Test parse_http_time */
1163 tt_int_op(-1,OP_EQ,
1164 parse_http_time("", &a_time));
1165 tt_int_op(-1,OP_EQ,
1166 parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
1167 tt_int_op(-1,OP_EQ,
1168 parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
1169 tt_int_op(-1,OP_EQ,
1170 parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
1171 tt_int_op(-1,OP_EQ,
1172 parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
1173 tt_int_op(-1,OP_EQ,
1174 parse_http_time("Sunday, August the third", &a_time));
1175 tt_int_op(-1,OP_EQ,
1176 parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
1178 tt_int_op(0,OP_EQ,
1179 parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
1180 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1181 T("1994-08-04 00:48:22");
1182 tt_int_op(0,OP_EQ,
1183 parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
1184 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1185 T("1994-08-04 00:48:22");
1186 tt_int_op(0,OP_EQ,
1187 parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
1188 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1189 T("1994-08-04 00:48:22");
1190 tt_int_op(0,OP_EQ,
1191 parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
1192 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1193 T("1994-08-04 00:48:22");
1194 tt_int_op(0,OP_EQ,
1195 parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
1196 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1197 T("1994-08-04 00:48:22");
1198 tt_int_op(0,OP_EQ,
1199 parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
1200 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1201 T("1994-08-04 00:48:22");
1202 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
1203 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1204 T("1994-08-04 00:48:22");
1205 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
1206 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1207 T("1994-08-04 00:48:22");
1208 tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
1209 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1210 T("1994-08-04 00:48:22");
1211 tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
1212 tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
1213 T("2012-01-01 00:00:00");
1214 tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
1215 tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
1216 T("2012-12-31 00:00:00");
1218 /* This value is in range with 32 bit and 64 bit time_t */
1219 tt_int_op(0,OP_EQ,parse_http_time("Fri, 30 Nov 2035 01:46:40 GMT", &a_time));
1220 tt_int_op((time_t)2080000000UL,OP_EQ, tor_timegm(&a_time));
1221 T("2035-11-30 01:46:40");
1223 /* This value is out of range with 32 bit time_t, but in range for 64 bit
1224 * time_t */
1225 #if SIZEOF_TIME_T == 4
1226 /* parse_http_time should indicate failure on overflow, but it doesn't yet.
1227 * Hopefully #18480 will improve the failure semantics in this case. */
1228 setup_capture_of_logs(LOG_WARN);
1229 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1230 tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time));
1231 expect_single_log_msg_containing("does not fit in tor_timegm");
1232 teardown_capture_of_logs();
1233 #elif SIZEOF_TIME_T == 8
1234 tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1235 tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time));
1236 T("2038-02-17 06:13:20");
1237 #endif /* SIZEOF_TIME_T == 4 || ... */
1239 tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
1240 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
1241 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
1242 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
1243 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
1244 tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
1245 tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
1246 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
1248 #undef T
1249 done:
1250 teardown_capture_of_logs();
1253 static void
1254 test_util_config_line(void *arg)
1256 char buf[1024];
1257 char *k=NULL, *v=NULL;
1258 const char *str;
1260 /* Test parse_config_line_from_str */
1261 (void)arg;
1262 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
1263 "k2\n"
1264 "k3 \n" "\n" " \n" "#comment\n"
1265 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
1266 "kseven \"a quoted 'string\"\n"
1267 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
1268 "k9 a line that\\\n spans two lines.\n\n"
1269 "k10 more than\\\n one contin\\\nuation\n"
1270 "k11 \\\ncontinuation at the start\n"
1271 "k12 line with a\\\n#comment\n embedded\n"
1272 "k13\\\ncontinuation at the very start\n"
1273 "k14 a line that has a comment and # ends with a slash \\\n"
1274 "k15 this should be the next new line\n"
1275 "k16 a line that has a comment and # ends without a slash \n"
1276 "k17 this should be the next new line\n"
1277 , sizeof(buf));
1278 str = buf;
1280 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1281 tt_str_op(k,OP_EQ, "k");
1282 tt_str_op(v,OP_EQ, "v");
1283 tor_free(k); tor_free(v);
1284 tt_assert(!strcmpstart(str, "key value with"));
1286 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1287 tt_str_op(k,OP_EQ, "key");
1288 tt_str_op(v,OP_EQ, "value with spaces");
1289 tor_free(k); tor_free(v);
1290 tt_assert(!strcmpstart(str, "keykey"));
1292 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1293 tt_str_op(k,OP_EQ, "keykey");
1294 tt_str_op(v,OP_EQ, "val");
1295 tor_free(k); tor_free(v);
1296 tt_assert(!strcmpstart(str, "k2\n"));
1298 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1299 tt_str_op(k,OP_EQ, "k2");
1300 tt_str_op(v,OP_EQ, "");
1301 tor_free(k); tor_free(v);
1302 tt_assert(!strcmpstart(str, "k3 \n"));
1304 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1305 tt_str_op(k,OP_EQ, "k3");
1306 tt_str_op(v,OP_EQ, "");
1307 tor_free(k); tor_free(v);
1308 tt_assert(!strcmpstart(str, "#comment"));
1310 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1311 tt_str_op(k,OP_EQ, "k4");
1312 tt_str_op(v,OP_EQ, "");
1313 tor_free(k); tor_free(v);
1314 tt_assert(!strcmpstart(str, "k5#abc"));
1316 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1317 tt_str_op(k,OP_EQ, "k5");
1318 tt_str_op(v,OP_EQ, "");
1319 tor_free(k); tor_free(v);
1320 tt_assert(!strcmpstart(str, "k6"));
1322 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1323 tt_str_op(k,OP_EQ, "k6");
1324 tt_str_op(v,OP_EQ, "val");
1325 tor_free(k); tor_free(v);
1326 tt_assert(!strcmpstart(str, "kseven"));
1328 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1329 tt_str_op(k,OP_EQ, "kseven");
1330 tt_str_op(v,OP_EQ, "a quoted \'string");
1331 tor_free(k); tor_free(v);
1332 tt_assert(!strcmpstart(str, "k8 "));
1334 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1335 tt_str_op(k,OP_EQ, "k8");
1336 tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
1337 tor_free(k); tor_free(v);
1339 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1340 tt_str_op(k,OP_EQ, "k9");
1341 tt_str_op(v,OP_EQ, "a line that spans two lines.");
1342 tor_free(k); tor_free(v);
1344 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1345 tt_str_op(k,OP_EQ, "k10");
1346 tt_str_op(v,OP_EQ, "more than one continuation");
1347 tor_free(k); tor_free(v);
1349 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1350 tt_str_op(k,OP_EQ, "k11");
1351 tt_str_op(v,OP_EQ, "continuation at the start");
1352 tor_free(k); tor_free(v);
1354 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1355 tt_str_op(k,OP_EQ, "k12");
1356 tt_str_op(v,OP_EQ, "line with a embedded");
1357 tor_free(k); tor_free(v);
1359 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1360 tt_str_op(k,OP_EQ, "k13");
1361 tt_str_op(v,OP_EQ, "continuation at the very start");
1362 tor_free(k); tor_free(v);
1364 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1365 tt_str_op(k,OP_EQ, "k14");
1366 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1367 tor_free(k); tor_free(v);
1369 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1370 tt_str_op(k,OP_EQ, "k15");
1371 tt_str_op(v,OP_EQ, "this should be the next new line");
1372 tor_free(k); tor_free(v);
1374 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1375 tt_str_op(k,OP_EQ, "k16");
1376 tt_str_op(v,OP_EQ, "a line that has a comment and" );
1377 tor_free(k); tor_free(v);
1379 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1380 tt_str_op(k,OP_EQ, "k17");
1381 tt_str_op(v,OP_EQ, "this should be the next new line");
1382 tor_free(k); tor_free(v);
1384 tt_str_op(str,OP_EQ, "");
1386 done:
1387 tor_free(k);
1388 tor_free(v);
1391 static void
1392 test_util_config_line_quotes(void *arg)
1394 char buf1[1024];
1395 char buf2[128];
1396 char buf3[128];
1397 char buf4[128];
1398 char *k=NULL, *v=NULL;
1399 const char *str;
1401 /* Test parse_config_line_from_str */
1402 (void)arg;
1403 strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
1404 "kTrailingGarbage \"quoted value\"trailing garbage\n"
1405 , sizeof(buf1));
1406 strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
1407 , sizeof(buf2));
1408 strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
1409 , sizeof(buf3));
1410 strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
1411 , sizeof(buf4));
1412 str = buf1;
1414 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1415 tt_str_op(k,OP_EQ, "kTrailingSpace");
1416 tt_str_op(v,OP_EQ, "quoted value");
1417 tor_free(k); tor_free(v);
1419 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1420 tt_ptr_op(str,OP_EQ, NULL);
1421 tor_free(k); tor_free(v);
1423 str = buf2;
1425 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1426 tt_ptr_op(str,OP_EQ, NULL);
1427 tor_free(k); tor_free(v);
1429 str = buf3;
1431 const char *err = NULL;
1432 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1433 tt_ptr_op(str,OP_EQ, NULL);
1434 tor_free(k); tor_free(v);
1435 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1437 str = buf4;
1439 err = NULL;
1440 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1441 tt_ptr_op(str,OP_EQ, NULL);
1442 tor_free(k); tor_free(v);
1443 tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1445 done:
1446 tor_free(k);
1447 tor_free(v);
1450 static void
1451 test_util_config_line_comment_character(void *arg)
1453 char buf[1024];
1454 char *k=NULL, *v=NULL;
1455 const char *str;
1457 /* Test parse_config_line_from_str */
1458 (void)arg;
1459 strlcpy(buf, "k1 \"# in quotes\"\n"
1460 "k2 some value # some comment\n"
1461 "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
1462 , sizeof(buf));
1463 str = buf;
1465 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1466 tt_str_op(k,OP_EQ, "k1");
1467 tt_str_op(v,OP_EQ, "# in quotes");
1468 tor_free(k); tor_free(v);
1470 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1471 tt_str_op(k,OP_EQ, "k2");
1472 tt_str_op(v,OP_EQ, "some value");
1473 tor_free(k); tor_free(v);
1475 tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
1477 #if 0
1478 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1479 test_streq(k, "k3");
1480 test_streq(v, "/home/user/myTorNetwork#2");
1481 tor_free(k); tor_free(v);
1483 test_streq(str, "");
1484 #endif /* 0 */
1486 done:
1487 tor_free(k);
1488 tor_free(v);
1491 static void
1492 test_util_config_line_escaped_content(void *arg)
1494 char buf1[1024];
1495 char buf2[128];
1496 char buf3[128];
1497 char buf4[128];
1498 char buf5[128];
1499 char buf6[128];
1500 char *k=NULL, *v=NULL;
1501 const char *str;
1503 /* Test parse_config_line_from_str */
1504 (void)arg;
1505 strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
1506 "HexadecimalUpper \"\\x2A\"\n"
1507 "HexadecimalUpperX \"\\X2A\"\n"
1508 "Octal \"\\52\"\n"
1509 "Newline \"\\n\"\n"
1510 "Tab \"\\t\"\n"
1511 "CarriageReturn \"\\r\"\n"
1512 "DoubleQuote \"\\\"\"\n"
1513 "SimpleQuote \"\\'\"\n"
1514 "Backslash \"\\\\\"\n"
1515 "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
1516 , sizeof(buf1));
1518 strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
1519 , sizeof(buf2));
1521 strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
1522 , sizeof(buf3));
1524 strlcpy(buf4, "BrokenOctal \"\\8\"\n"
1525 , sizeof(buf4));
1527 strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
1528 , sizeof(buf5));
1530 strlcpy(buf6, "BrokenEscape \"\\"
1531 , sizeof(buf6));
1533 str = buf1;
1535 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1536 tt_str_op(k,OP_EQ, "HexadecimalLower");
1537 tt_str_op(v,OP_EQ, "*");
1538 tor_free(k); tor_free(v);
1540 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1541 tt_str_op(k,OP_EQ, "HexadecimalUpper");
1542 tt_str_op(v,OP_EQ, "*");
1543 tor_free(k); tor_free(v);
1545 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1546 tt_str_op(k,OP_EQ, "HexadecimalUpperX");
1547 tt_str_op(v,OP_EQ, "*");
1548 tor_free(k); tor_free(v);
1550 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1551 tt_str_op(k,OP_EQ, "Octal");
1552 tt_str_op(v,OP_EQ, "*");
1553 tor_free(k); tor_free(v);
1555 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1556 tt_str_op(k,OP_EQ, "Newline");
1557 tt_str_op(v,OP_EQ, "\n");
1558 tor_free(k); tor_free(v);
1560 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1561 tt_str_op(k,OP_EQ, "Tab");
1562 tt_str_op(v,OP_EQ, "\t");
1563 tor_free(k); tor_free(v);
1565 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1566 tt_str_op(k,OP_EQ, "CarriageReturn");
1567 tt_str_op(v,OP_EQ, "\r");
1568 tor_free(k); tor_free(v);
1570 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1571 tt_str_op(k,OP_EQ, "DoubleQuote");
1572 tt_str_op(v,OP_EQ, "\"");
1573 tor_free(k); tor_free(v);
1575 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1576 tt_str_op(k,OP_EQ, "SimpleQuote");
1577 tt_str_op(v,OP_EQ, "'");
1578 tor_free(k); tor_free(v);
1580 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1581 tt_str_op(k,OP_EQ, "Backslash");
1582 tt_str_op(v,OP_EQ, "\\");
1583 tor_free(k); tor_free(v);
1585 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1586 tt_str_op(k,OP_EQ, "Mix");
1587 tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
1588 tor_free(k); tor_free(v);
1589 tt_str_op(str,OP_EQ, "");
1591 str = buf2;
1593 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1594 tt_ptr_op(str,OP_EQ, NULL);
1595 tor_free(k); tor_free(v);
1597 str = buf3;
1599 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1600 tt_ptr_op(str,OP_EQ, NULL);
1601 tor_free(k); tor_free(v);
1603 str = buf4;
1605 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1606 tt_ptr_op(str,OP_EQ, NULL);
1607 tor_free(k); tor_free(v);
1609 #if 0
1610 str = buf5;
1612 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1613 tt_ptr_op(str, OP_EQ, NULL);
1614 tor_free(k); tor_free(v);
1615 #endif /* 0 */
1617 str = buf6;
1619 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1620 tt_ptr_op(str,OP_EQ, NULL);
1621 tor_free(k); tor_free(v);
1623 /* more things to try. */
1624 /* Bad hex: */
1625 strlcpy(buf1, "Foo \"\\x9g\"\n", sizeof(buf1));
1626 strlcpy(buf2, "Foo \"\\xg0\"\n", sizeof(buf2));
1627 strlcpy(buf3, "Foo \"\\xf\"\n", sizeof(buf3));
1628 /* bad escape */
1629 strlcpy(buf4, "Foo \"\\q\"\n", sizeof(buf4));
1630 /* missing endquote */
1631 strlcpy(buf5, "Foo \"hello\n", sizeof(buf5));
1632 /* extra stuff */
1633 strlcpy(buf6, "Foo \"hello\" world\n", sizeof(buf6));
1635 str=buf1;
1636 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1637 tt_ptr_op(str,OP_EQ, NULL);
1638 tor_free(k); tor_free(v);
1640 str=buf2;
1641 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1642 tt_ptr_op(str,OP_EQ, NULL);
1643 tor_free(k); tor_free(v);
1645 str=buf3;
1646 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1647 tt_ptr_op(str,OP_EQ, NULL);
1648 tor_free(k); tor_free(v);
1650 str=buf4;
1651 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1652 tt_ptr_op(str,OP_EQ, NULL);
1653 tor_free(k); tor_free(v);
1655 str=buf5;
1657 str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1658 tt_ptr_op(str,OP_EQ, NULL);
1659 tor_free(k); tor_free(v);
1661 str=buf6;
1662 const char *err = NULL;
1663 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1664 tt_ptr_op(str,OP_EQ, NULL);
1665 tor_free(k); tor_free(v);
1666 tt_str_op(err,OP_EQ, "Excess data after quoted string");
1668 done:
1669 tor_free(k);
1670 tor_free(v);
1673 static void
1674 test_util_config_line_crlf(void *arg)
1676 char *k=NULL, *v=NULL;
1677 const char *err = NULL;
1678 (void)arg;
1679 const char *str =
1680 "Hello world\r\n"
1681 "Hello \"nice big world\"\r\n";
1683 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1684 tt_assert(str);
1685 tt_str_op(k,OP_EQ,"Hello");
1686 tt_str_op(v,OP_EQ,"world");
1687 tt_ptr_op(err, OP_EQ, NULL);
1688 tor_free(k); tor_free(v);
1690 str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1691 tt_assert(str);
1692 tt_str_op(k,OP_EQ,"Hello");
1693 tt_str_op(v,OP_EQ,"nice big world");
1694 tt_ptr_op(err, OP_EQ, NULL);
1695 tor_free(k); tor_free(v);
1696 tt_str_op(str,OP_EQ, "");
1698 done:
1699 tor_free(k); tor_free(v);
1702 #ifndef _WIN32
1703 static void
1704 test_util_expand_filename(void *arg)
1706 char *str;
1708 (void)arg;
1709 setenv("HOME", "/home/itv", 1); /* For "internal test value" */
1711 str = expand_filename("");
1712 tt_str_op("",OP_EQ, str);
1713 tor_free(str);
1715 str = expand_filename("/normal/path");
1716 tt_str_op("/normal/path",OP_EQ, str);
1717 tor_free(str);
1719 str = expand_filename("/normal/trailing/path/");
1720 tt_str_op("/normal/trailing/path/",OP_EQ, str);
1721 tor_free(str);
1723 str = expand_filename("~");
1724 tt_str_op("/home/itv/",OP_EQ, str);
1725 tor_free(str);
1727 str = expand_filename("$HOME/nodice");
1728 tt_str_op("$HOME/nodice",OP_EQ, str);
1729 tor_free(str);
1731 str = expand_filename("~/");
1732 tt_str_op("/home/itv/",OP_EQ, str);
1733 tor_free(str);
1735 str = expand_filename("~/foobarqux");
1736 tt_str_op("/home/itv/foobarqux",OP_EQ, str);
1737 tor_free(str);
1739 str = expand_filename("~/../../etc/passwd");
1740 tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
1741 tor_free(str);
1743 str = expand_filename("~/trailing/");
1744 tt_str_op("/home/itv/trailing/",OP_EQ, str);
1745 tor_free(str);
1746 /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
1747 have to somehow inject/fake the get_user_homedir call) */
1749 /* $HOME ending in a trailing slash */
1750 setenv("HOME", "/home/itv/", 1);
1752 str = expand_filename("~");
1753 tt_str_op("/home/itv/",OP_EQ, str);
1754 tor_free(str);
1756 str = expand_filename("~/");
1757 tt_str_op("/home/itv/",OP_EQ, str);
1758 tor_free(str);
1760 str = expand_filename("~/foo");
1761 tt_str_op("/home/itv/foo",OP_EQ, str);
1762 tor_free(str);
1764 /* Try with empty $HOME */
1766 setenv("HOME", "", 1);
1768 str = expand_filename("~");
1769 tt_str_op("/",OP_EQ, str);
1770 tor_free(str);
1772 str = expand_filename("~/");
1773 tt_str_op("/",OP_EQ, str);
1774 tor_free(str);
1776 str = expand_filename("~/foobar");
1777 tt_str_op("/foobar",OP_EQ, str);
1778 tor_free(str);
1780 /* Try with $HOME unset */
1782 unsetenv("HOME");
1784 str = expand_filename("~");
1785 tt_str_op("/",OP_EQ, str);
1786 tor_free(str);
1788 str = expand_filename("~/");
1789 tt_str_op("/",OP_EQ, str);
1790 tor_free(str);
1792 str = expand_filename("~/foobar");
1793 tt_str_op("/foobar",OP_EQ, str);
1794 tor_free(str);
1796 done:
1797 tor_free(str);
1799 #endif /* !defined(_WIN32) */
1801 /** Test tor_escape_str_for_pt_args(). */
1802 static void
1803 test_util_escape_string_socks(void *arg)
1805 char *escaped_string = NULL;
1807 /** Simple backslash escape. */
1808 (void)arg;
1809 escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
1810 tt_assert(escaped_string);
1811 tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
1812 tor_free(escaped_string);
1814 /** Simple semicolon escape. */
1815 escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
1816 tt_assert(escaped_string);
1817 tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
1818 tor_free(escaped_string);
1820 /** Empty string. */
1821 escaped_string = tor_escape_str_for_pt_args("", ";\\");
1822 tt_assert(escaped_string);
1823 tt_str_op(escaped_string,OP_EQ, "");
1824 tor_free(escaped_string);
1826 /** Escape all characters. */
1827 escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
1828 tt_assert(escaped_string);
1829 tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
1830 tor_free(escaped_string);
1832 escaped_string = tor_escape_str_for_pt_args(";", ";\\");
1833 tt_assert(escaped_string);
1834 tt_str_op(escaped_string,OP_EQ, "\\;");
1835 tor_free(escaped_string);
1837 done:
1838 tor_free(escaped_string);
1841 static void
1842 test_util_string_is_key_value(void *ptr)
1844 (void)ptr;
1845 tt_assert(string_is_key_value(LOG_WARN, "key=value"));
1846 tt_assert(string_is_key_value(LOG_WARN, "k=v"));
1847 tt_assert(string_is_key_value(LOG_WARN, "key="));
1848 tt_assert(string_is_key_value(LOG_WARN, "x="));
1849 tt_assert(string_is_key_value(LOG_WARN, "xx="));
1850 tt_assert(!string_is_key_value(LOG_WARN, "=value"));
1851 tt_assert(!string_is_key_value(LOG_WARN, "=x"));
1852 tt_assert(!string_is_key_value(LOG_WARN, "="));
1854 /* ??? */
1855 /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
1856 done:
1860 /** Test basic string functionality. */
1861 static void
1862 test_util_strmisc(void *arg)
1864 char buf[1024];
1865 char *cp_tmp = NULL;
1867 /* Test strl operations */
1868 (void)arg;
1869 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
1870 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
1871 tt_str_op(buf,OP_EQ, "Hello");
1872 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
1873 tt_str_op(buf,OP_EQ, "Hello");
1874 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
1875 tt_str_op(buf,OP_EQ, "Hell");
1876 strlcpy(buf, "Hello", sizeof(buf));
1877 tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
1879 /* Test strstrip() */
1880 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
1881 tor_strstrip(buf, ",!");
1882 tt_str_op(buf,OP_EQ, "Testing 1 2 3");
1883 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
1884 tor_strstrip(buf, "!? ");
1885 tt_str_op(buf,OP_EQ, "Testing123");
1886 strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
1887 tor_strstrip(buf, "!? ");
1888 tt_str_op(buf,OP_EQ, "Testing123");
1890 /* Test snprintf */
1891 /* Returning -1 when there's not enough room in the output buffer */
1892 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
1893 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
1894 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
1895 tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
1896 /* Always NUL-terminate the output */
1897 tor_snprintf(buf, 5, "abcdef");
1898 tt_int_op(0,OP_EQ, buf[4]);
1899 tor_snprintf(buf, 10, "abcdef");
1900 tt_int_op(0,OP_EQ, buf[6]);
1901 /* uint64 */
1902 tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
1903 U64_PRINTF_ARG(U64_LITERAL(12345678901)));
1904 tt_str_op("x!12345678901!x",OP_EQ, buf);
1906 /* Test str{,case}cmpstart */
1907 tt_assert(strcmpstart("abcdef", "abcdef")==0);
1908 tt_assert(strcmpstart("abcdef", "abc")==0);
1909 tt_assert(strcmpstart("abcdef", "abd")<0);
1910 tt_assert(strcmpstart("abcdef", "abb")>0);
1911 tt_assert(strcmpstart("ab", "abb")<0);
1912 tt_assert(strcmpstart("ab", "")==0);
1913 tt_assert(strcmpstart("ab", "ab ")<0);
1914 tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
1915 tt_assert(strcasecmpstart("abcDeF", "abc")==0);
1916 tt_assert(strcasecmpstart("abcdef", "Abd")<0);
1917 tt_assert(strcasecmpstart("Abcdef", "abb")>0);
1918 tt_assert(strcasecmpstart("ab", "Abb")<0);
1919 tt_assert(strcasecmpstart("ab", "")==0);
1920 tt_assert(strcasecmpstart("ab", "ab ")<0);
1922 /* Test str{,case}cmpend */
1923 tt_assert(strcmpend("abcdef", "abcdef")==0);
1924 tt_assert(strcmpend("abcdef", "def")==0);
1925 tt_assert(strcmpend("abcdef", "deg")<0);
1926 tt_assert(strcmpend("abcdef", "dee")>0);
1927 tt_assert(strcmpend("ab", "aab")>0);
1928 tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
1929 tt_assert(strcasecmpend("abcdef", "dEF")==0);
1930 tt_assert(strcasecmpend("abcdef", "Deg")<0);
1931 tt_assert(strcasecmpend("abcDef", "dee")>0);
1932 tt_assert(strcasecmpend("AB", "abb")<0);
1934 /* Test digest_is_zero */
1935 memset(buf,0,20);
1936 buf[20] = 'x';
1937 tt_assert(tor_digest_is_zero(buf));
1938 buf[19] = 'x';
1939 tt_assert(!tor_digest_is_zero(buf));
1941 /* Test mem_is_zero */
1942 memset(buf,0,128);
1943 buf[128] = 'x';
1944 tt_assert(tor_mem_is_zero(buf, 10));
1945 tt_assert(tor_mem_is_zero(buf, 20));
1946 tt_assert(tor_mem_is_zero(buf, 128));
1947 tt_assert(!tor_mem_is_zero(buf, 129));
1948 buf[60] = (char)255;
1949 tt_assert(!tor_mem_is_zero(buf, 128));
1950 buf[0] = (char)1;
1951 tt_assert(!tor_mem_is_zero(buf, 10));
1953 /* Test 'escaped' */
1954 tt_ptr_op(escaped(NULL), OP_EQ, NULL);
1955 tt_str_op("\"\"",OP_EQ, escaped(""));
1956 tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
1957 tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
1958 tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
1959 escaped("unnecessary \'backslashes\'"));
1960 /* Non-printable characters appear as octal */
1961 tt_str_op("\"z\\001abc\\277d\"",OP_EQ, escaped("z\001abc\277d"));
1962 tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
1964 /* Other cases of esc_for_log{,_len} */
1965 cp_tmp = esc_for_log(NULL);
1966 tt_str_op(cp_tmp, OP_EQ, "(null)");
1967 tor_free(cp_tmp);
1968 cp_tmp = esc_for_log_len("abcdefg", 3);
1969 tt_str_op(cp_tmp, OP_EQ, "\"abc\"");
1970 tor_free(cp_tmp);
1971 cp_tmp = esc_for_log_len("abcdefg", 100);
1972 tt_str_op(cp_tmp, OP_EQ, "\"abcdefg\"");
1973 tor_free(cp_tmp);
1975 /* Test strndup and memdup */
1977 const char *s = "abcdefghijklmnopqrstuvwxyz";
1978 cp_tmp = tor_strndup(s, 30);
1979 tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
1980 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
1981 tor_free(cp_tmp);
1983 cp_tmp = tor_strndup(s, 5);
1984 tt_str_op(cp_tmp,OP_EQ, "abcde");
1985 tor_free(cp_tmp);
1987 s = "a\0b\0c\0d\0e\0";
1988 cp_tmp = tor_memdup(s,10);
1989 tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
1990 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
1991 tor_free(cp_tmp);
1994 /* Test str-foo functions */
1995 cp_tmp = tor_strdup("abcdef");
1996 tt_assert(tor_strisnonupper(cp_tmp));
1997 cp_tmp[3] = 'D';
1998 tt_assert(!tor_strisnonupper(cp_tmp));
1999 tor_strupper(cp_tmp);
2000 tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
2001 tor_strlower(cp_tmp);
2002 tt_str_op(cp_tmp,OP_EQ, "abcdef");
2003 tt_assert(tor_strisnonupper(cp_tmp));
2004 tt_assert(tor_strisprint(cp_tmp));
2005 cp_tmp[3] = 3;
2006 tt_assert(!tor_strisprint(cp_tmp));
2007 tor_free(cp_tmp);
2009 /* Test memmem and memstr */
2011 const char *haystack = "abcde";
2012 tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL);
2013 tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
2014 tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
2015 tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL);
2016 haystack = "ababcad";
2017 tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
2018 tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
2019 tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
2020 tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL);
2021 tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL);
2022 /* memstr */
2023 tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
2024 tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
2025 tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL);
2026 tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL);
2027 tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL);
2028 tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL);
2031 /* Test hex_str */
2033 char binary_data[68];
2034 size_t idx;
2035 for (idx = 0; idx < sizeof(binary_data); ++idx)
2036 binary_data[idx] = idx;
2037 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2038 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2039 tt_str_op(hex_str(binary_data, 17),OP_EQ,
2040 "000102030405060708090A0B0C0D0E0F10");
2041 tt_str_op(hex_str(binary_data, 32),OP_EQ,
2042 "000102030405060708090A0B0C0D0E0F"
2043 "101112131415161718191A1B1C1D1E1F");
2044 tt_str_op(hex_str(binary_data, 34),OP_EQ,
2045 "000102030405060708090A0B0C0D0E0F"
2046 "101112131415161718191A1B1C1D1E1F");
2047 /* Repeat these tests for shorter strings after longer strings
2048 have been tried, to make sure we're correctly terminating strings */
2049 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2050 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2053 /* Test strcmp_opt */
2054 tt_int_op(strcmp_opt("", "foo"), OP_LT, 0);
2055 tt_int_op(strcmp_opt("", ""), OP_EQ, 0);
2056 tt_int_op(strcmp_opt("foo", ""), OP_GT, 0);
2058 tt_int_op(strcmp_opt(NULL, ""), OP_LT, 0);
2059 tt_int_op(strcmp_opt(NULL, NULL), OP_EQ, 0);
2060 tt_int_op(strcmp_opt("", NULL), OP_GT, 0);
2062 tt_int_op(strcmp_opt(NULL, "foo"), OP_LT, 0);
2063 tt_int_op(strcmp_opt("foo", NULL), OP_GT, 0);
2065 /* Test strcmp_len */
2066 tt_int_op(strcmp_len("foo", "bar", 3), OP_GT, 0);
2067 tt_int_op(strcmp_len("foo", "bar", 2), OP_LT, 0);
2068 tt_int_op(strcmp_len("foo2", "foo1", 4), OP_GT, 0);
2069 tt_int_op(strcmp_len("foo2", "foo1", 3), OP_LT, 0); /* Really stop at len */
2070 tt_int_op(strcmp_len("foo2", "foo", 3), OP_EQ, 0); /* Really stop at len */
2071 tt_int_op(strcmp_len("blah", "", 4), OP_GT, 0);
2072 tt_int_op(strcmp_len("blah", "", 0), OP_EQ, 0);
2074 done:
2075 tor_free(cp_tmp);
2078 static void
2079 test_util_parse_integer(void *arg)
2081 (void)arg;
2082 int i;
2083 char *cp;
2085 /* Test parse_long */
2086 /* Empty/zero input */
2087 tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
2088 tt_int_op(0,OP_EQ, i);
2089 tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
2090 tt_int_op(1,OP_EQ, i);
2091 /* Normal cases */
2092 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
2093 tt_int_op(1,OP_EQ, i);
2094 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
2095 tt_int_op(1,OP_EQ, i);
2096 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
2097 tt_int_op(1,OP_EQ, i);
2098 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
2099 tt_int_op(1,OP_EQ, i);
2100 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
2101 tt_int_op(1,OP_EQ, i);
2102 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
2103 tt_int_op(1,OP_EQ, i);
2104 /* Extra garbage */
2105 tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
2106 tt_int_op(0,OP_EQ, i);
2107 tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
2108 tt_int_op(0,OP_EQ, i);
2109 tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
2110 tt_int_op(1,OP_EQ, i);
2111 tt_str_op(cp,OP_EQ, "m");
2112 tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
2113 tt_int_op(1,OP_EQ, i);
2114 tt_str_op(cp,OP_EQ, " plus garbage");
2115 /* Illogical min max */
2116 tor_capture_bugs_(1);
2117 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL));
2118 tt_int_op(0,OP_EQ, i);
2119 tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
2120 tt_str_op("!(max < min)", OP_EQ,
2121 smartlist_get(tor_get_captured_bug_log_(), 0));
2122 tor_end_capture_bugs_();
2123 tor_capture_bugs_(1);
2124 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL));
2125 tt_int_op(0,OP_EQ, i);
2126 tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
2127 tt_str_op("!(max < min)", OP_EQ,
2128 smartlist_get(tor_get_captured_bug_log_(), 0));
2129 tor_end_capture_bugs_();
2130 /* Out of bounds */
2131 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
2132 tt_int_op(0,OP_EQ, i);
2133 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,0,100,&i,NULL));
2134 tt_int_op(0,OP_EQ, i);
2135 /* Base different than 10 */
2136 tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL));
2137 tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
2138 tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
2139 tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
2140 tor_capture_bugs_(2);
2141 tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
2142 tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
2143 tt_int_op(2, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
2144 tor_end_capture_bugs_();
2145 tt_int_op(i,OP_EQ, 0);
2147 /* Test parse_ulong */
2148 tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
2149 tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
2150 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
2151 tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
2152 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
2153 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
2154 tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
2155 tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
2156 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
2157 tor_capture_bugs_(1);
2158 tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
2159 tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
2160 tor_end_capture_bugs_();
2161 tt_int_op(0,OP_EQ, i);
2162 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
2163 tt_int_op(0,OP_EQ, i);
2165 /* Test parse_uint64 */
2166 tt_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
2167 tt_int_op(1,OP_EQ, i);
2168 tt_str_op(cp,OP_EQ, " x");
2169 tt_assert(U64_LITERAL(12345678901) ==
2170 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
2171 tt_int_op(1,OP_EQ, i);
2172 tt_str_op(cp,OP_EQ, "");
2173 tt_assert(U64_LITERAL(0) ==
2174 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
2175 tt_int_op(0,OP_EQ, i);
2176 tor_capture_bugs_(1);
2177 tt_assert(U64_LITERAL(0) ==
2178 tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
2179 tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_()));
2180 tor_end_capture_bugs_();
2181 tt_int_op(0,OP_EQ, i);
2184 /* Test parse_double */
2185 double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
2186 tt_int_op(1,OP_EQ, i);
2187 tt_assert(DBL_TO_U64(d) == 10);
2188 d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
2189 tt_int_op(1,OP_EQ, i);
2190 tt_assert(DBL_TO_U64(d) == 0);
2191 d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
2192 tt_double_op(fabs(d), OP_LT, 1e-10);
2193 tt_int_op(0,OP_EQ, i);
2194 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL);
2195 tt_double_op(fabs(d), OP_LT, 1e-10);
2196 tt_int_op(0,OP_EQ, i);
2197 d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp);
2198 tt_double_op(fabs(d), OP_LT, 1e-10);
2199 tt_int_op(1,OP_EQ, i);
2200 d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
2201 tt_int_op(1,OP_EQ, i);
2202 tt_assert(DBL_TO_U64(d) == 0);
2203 d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
2204 tt_int_op(1,OP_EQ, i);
2205 tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
2209 /* Test tor_parse_* where we overflow/underflow the underlying type. */
2210 /* This string should overflow 64-bit ints. */
2211 #define TOOBIG "100000000000000000000000000"
2212 tt_int_op(0L, OP_EQ,
2213 tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2214 tt_int_op(i,OP_EQ, 0);
2215 tt_int_op(0L,OP_EQ,
2216 tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2217 tt_int_op(i,OP_EQ, 0);
2218 tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
2219 tt_int_op(i,OP_EQ, 0);
2220 tt_u64_op(U64_LITERAL(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
2221 0, UINT64_MAX, &i, NULL));
2222 tt_int_op(i,OP_EQ, 0);
2224 done:
2225 tor_end_capture_bugs_();
2228 static void
2229 test_util_pow2(void *arg)
2231 /* Test tor_log2(). */
2232 (void)arg;
2233 tt_int_op(tor_log2(64),OP_EQ, 6);
2234 tt_int_op(tor_log2(65),OP_EQ, 6);
2235 tt_int_op(tor_log2(63),OP_EQ, 5);
2236 /* incorrect mathematically, but as specified: */
2237 tt_int_op(tor_log2(0),OP_EQ, 0);
2238 tt_int_op(tor_log2(1),OP_EQ, 0);
2239 tt_int_op(tor_log2(2),OP_EQ, 1);
2240 tt_int_op(tor_log2(3),OP_EQ, 1);
2241 tt_int_op(tor_log2(4),OP_EQ, 2);
2242 tt_int_op(tor_log2(5),OP_EQ, 2);
2243 tt_int_op(tor_log2(U64_LITERAL(40000000000000000)),OP_EQ, 55);
2244 tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
2246 /* Test round_to_power_of_2 */
2247 tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
2248 tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
2249 tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
2250 tt_u64_op(round_to_power_of_2(U64_LITERAL(40000000000000000)), OP_EQ,
2251 U64_LITERAL(1)<<55);
2252 tt_u64_op(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), OP_EQ,
2253 U64_LITERAL(1)<<63);
2254 tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
2255 tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
2256 tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
2257 tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
2258 tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
2259 tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
2260 tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
2261 tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
2263 done:
2267 static void
2268 test_util_compress_impl(compress_method_t method)
2270 char *buf1=NULL, *buf2=NULL, *buf3=NULL;
2271 size_t len1, len2;
2273 tt_assert(tor_compress_supports_method(method));
2275 if (method != NO_METHOD) {
2276 tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
2277 tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
2280 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
2281 tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
2283 tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
2284 tt_ptr_op(buf2, OP_NE, NULL);
2285 if (method == NO_METHOD) {
2286 // The identity transform doesn't actually compress, and it isn't
2287 // detectable as "the identity transform."
2288 tt_int_op(len1, OP_EQ, strlen(buf1)+1);
2289 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
2290 } else {
2291 tt_int_op(len1, OP_LT, strlen(buf1));
2292 tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
2295 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
2296 tt_ptr_op(buf3, OP_NE, NULL);
2297 tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
2298 tt_str_op(buf1, OP_EQ, buf3);
2299 tt_int_op(buf3[len2], OP_EQ, 0);
2301 /* Check whether we can uncompress concatenated, compressed strings. */
2302 tor_free(buf3);
2303 buf2 = tor_reallocarray(buf2, len1, 2);
2304 memcpy(buf2+len1, buf2, len1);
2305 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
2306 tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
2307 tt_mem_op(buf3, OP_EQ,
2308 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
2309 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
2310 (strlen(buf1)+1)*2);
2311 tt_int_op(buf3[len2], OP_EQ, 0);
2313 /* Check whether we can uncompress partial strings */
2315 tor_free(buf1);
2316 tor_free(buf2);
2317 tor_free(buf3);
2319 size_t b1len = 1<<10;
2320 if (method == ZSTD_METHOD) {
2321 // zstd needs a big input before it starts generating output that it
2322 // can partially decompress.
2323 b1len = 1<<18;
2325 buf1 = tor_malloc(b1len);
2326 crypto_rand(buf1, b1len);
2327 tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
2328 tt_int_op(len1, OP_GT, 16);
2329 /* when we allow an incomplete output we should succeed.*/
2330 tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
2331 method, 0, LOG_INFO));
2332 tt_int_op(len2, OP_GT, 5);
2333 tt_int_op(len2, OP_LE, len1);
2334 tt_assert(fast_memeq(buf1, buf3, len2));
2335 tt_int_op(buf3[len2], OP_EQ, 0);
2337 /* when we demand a complete output from a real compression method, this
2338 * must fail. */
2339 tor_free(buf3);
2340 if (method != NO_METHOD) {
2341 tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
2342 method, 1, LOG_INFO));
2343 tt_ptr_op(buf3, OP_EQ, NULL);
2346 done:
2347 tor_free(buf1);
2348 tor_free(buf2);
2349 tor_free(buf3);
2352 static void
2353 test_util_compress_stream_impl(compress_method_t method,
2354 compression_level_t level)
2356 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
2357 const char *ccp2;
2358 size_t len1, len2;
2360 tor_compress_state_t *state = NULL;
2361 state = tor_compress_new(1, method, level);
2362 tt_assert(state);
2363 cp1 = buf1 = tor_malloc(1024);
2364 len1 = 1024;
2365 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
2366 len2 = 21;
2367 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
2368 OP_EQ, TOR_COMPRESS_OK);
2369 tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
2370 tt_assert(cp1 > buf1);
2372 len2 = 0;
2373 cp2 = cp1;
2374 tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
2375 OP_EQ, TOR_COMPRESS_DONE);
2376 tt_int_op(0, OP_EQ, len2);
2377 if (method == NO_METHOD) {
2378 tt_ptr_op(cp1, OP_EQ, cp2);
2379 } else {
2380 tt_assert(cp1 > cp2); /* Make sure we really added something. */
2383 tt_int_op(tor_compress_state_size(state), OP_GT, 0);
2385 tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
2386 method, 1, LOG_WARN));
2387 /* Make sure it compressed right. */
2388 tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
2389 tt_int_op(21, OP_EQ, len2);
2391 done:
2392 if (state)
2393 tor_compress_free(state);
2394 tor_free(buf1);
2395 tor_free(buf2);
2396 tor_free(buf3);
2399 /** Run unit tests for compression functions */
2400 static void
2401 test_util_compress(void *arg)
2403 const char *methodname = arg;
2404 tt_assert(methodname);
2406 compress_method_t method = compression_method_get_by_name(methodname);
2407 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2409 if (! tor_compress_supports_method(method)) {
2410 tt_skip();
2413 compression_level_t levels[] = {
2414 BEST_COMPRESSION,
2415 HIGH_COMPRESSION,
2416 MEDIUM_COMPRESSION,
2417 LOW_COMPRESSION
2420 test_util_compress_impl(method);
2422 for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
2423 compression_level_t level = levels[l];
2424 test_util_compress_stream_impl(method, level);
2426 done:
2430 static void
2431 test_util_decompress_concatenated_impl(compress_method_t method)
2433 char input[4096];
2434 char *c1 = NULL, *c2 = NULL, *c3 = NULL;
2435 char *result = NULL;
2436 size_t sz1, sz2, sz3, szr;
2437 int r;
2439 crypto_rand(input, sizeof(input));
2441 /* Compress the input in two chunks. */
2442 r = tor_compress(&c1, &sz1, input, 2048, method);
2443 tt_int_op(r, OP_EQ, 0);
2444 r = tor_compress(&c2, &sz2, input+2048, 2048, method);
2445 tt_int_op(r, OP_EQ, 0);
2447 /* concatenate the chunks. */
2448 sz3 = sz1 + sz2;
2449 c3 = tor_malloc(sz3);
2450 memcpy(c3, c1, sz1);
2451 memcpy(c3+sz1, c2, sz2);
2453 /* decompress the concatenated result */
2454 r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
2455 tt_int_op(r, OP_EQ, 0);
2456 tt_int_op(szr, OP_EQ, sizeof(input));
2457 tt_mem_op(result, OP_EQ, input, sizeof(input));
2459 done:
2460 tor_free(c1);
2461 tor_free(c2);
2462 tor_free(c3);
2463 tor_free(result);
2466 static void
2467 test_util_decompress_concatenated(void *arg)
2469 const char *methodname = arg;
2470 tt_assert(methodname);
2472 compress_method_t method = compression_method_get_by_name(methodname);
2473 tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2474 if (! tor_compress_supports_method(method)) {
2475 tt_skip();
2478 test_util_decompress_concatenated_impl(method);
2479 done:
2483 static void
2484 test_util_gzip_compression_bomb(void *arg)
2486 /* A 'compression bomb' is a very small object that uncompresses to a huge
2487 * one. Most compression formats support them, but they can be a DOS vector.
2488 * In Tor we try not to generate them, and we don't accept them.
2490 (void) arg;
2491 size_t one_million = 1<<20;
2492 char *one_mb = tor_malloc_zero(one_million);
2493 char *result = NULL;
2494 size_t result_len = 0;
2495 tor_compress_state_t *state = NULL;
2497 /* Make sure we can't produce a compression bomb */
2498 setup_full_capture_of_logs(LOG_WARN);
2499 tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
2500 one_mb, one_million,
2501 ZLIB_METHOD));
2502 expect_single_log_msg_containing(
2503 "We compressed something and got an insanely high "
2504 "compression factor; other Tors would think this "
2505 "was a compression bomb.");
2506 teardown_capture_of_logs();
2508 /* Here's a compression bomb that we made manually. */
2509 const char compression_bomb[1039] =
2510 { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
2511 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
2512 tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
2513 compression_bomb, 1039,
2514 ZLIB_METHOD, 0, LOG_WARN));
2516 /* Now try streaming that. */
2517 state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
2518 tor_compress_output_t r;
2519 const char *inp = compression_bomb;
2520 size_t inlen = 1039;
2521 do {
2522 char *outp = one_mb;
2523 size_t outleft = 4096; /* small on purpose */
2524 r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
2525 tt_int_op(inlen, OP_NE, 0);
2526 } while (r == TOR_COMPRESS_BUFFER_FULL);
2528 tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
2530 done:
2531 tor_free(one_mb);
2532 tor_compress_free(state);
2535 /** Run unit tests for mmap() wrapper functionality. */
2536 static void
2537 test_util_mmap(void *arg)
2539 char *fname1 = tor_strdup(get_fname("mapped_1"));
2540 char *fname2 = tor_strdup(get_fname("mapped_2"));
2541 char *fname3 = tor_strdup(get_fname("mapped_3"));
2542 const size_t buflen = 17000;
2543 char *buf = tor_malloc(17000);
2544 tor_mmap_t *mapping = NULL;
2546 (void)arg;
2547 crypto_rand(buf, buflen);
2549 mapping = tor_mmap_file(fname1);
2550 tt_ptr_op(mapping, OP_EQ, NULL);
2552 write_str_to_file(fname1, "Short file.", 1);
2554 mapping = tor_mmap_file(fname1);
2555 tt_assert(mapping);
2556 tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
2557 tt_str_op(mapping->data,OP_EQ, "Short file.");
2558 #ifdef _WIN32
2559 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2560 mapping = NULL;
2561 tt_assert(unlink(fname1) == 0);
2562 #else
2563 /* make sure we can unlink. */
2564 tt_assert(unlink(fname1) == 0);
2565 tt_str_op(mapping->data,OP_EQ, "Short file.");
2566 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2567 mapping = NULL;
2568 #endif /* defined(_WIN32) */
2570 /* Now a zero-length file. */
2571 write_str_to_file(fname1, "", 1);
2572 mapping = tor_mmap_file(fname1);
2573 tt_ptr_op(mapping,OP_EQ, NULL);
2574 tt_int_op(ERANGE,OP_EQ, errno);
2575 unlink(fname1);
2577 /* Make sure that we fail to map a no-longer-existent file. */
2578 mapping = tor_mmap_file(fname1);
2579 tt_ptr_op(mapping, OP_EQ, NULL);
2581 /* Now try a big file that stretches across a few pages and isn't aligned */
2582 write_bytes_to_file(fname2, buf, buflen, 1);
2583 mapping = tor_mmap_file(fname2);
2584 tt_assert(mapping);
2585 tt_int_op(mapping->size,OP_EQ, buflen);
2586 tt_mem_op(mapping->data,OP_EQ, buf, buflen);
2587 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2588 mapping = NULL;
2590 /* Now try a big aligned file. */
2591 write_bytes_to_file(fname3, buf, 16384, 1);
2592 mapping = tor_mmap_file(fname3);
2593 tt_assert(mapping);
2594 tt_int_op(mapping->size,OP_EQ, 16384);
2595 tt_mem_op(mapping->data,OP_EQ, buf, 16384);
2596 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2597 mapping = NULL;
2599 done:
2600 unlink(fname1);
2601 unlink(fname2);
2602 unlink(fname3);
2604 tor_free(fname1);
2605 tor_free(fname2);
2606 tor_free(fname3);
2607 tor_free(buf);
2609 tor_munmap_file(mapping);
2612 /** Run unit tests for escaping/unescaping data for use by controllers. */
2613 static void
2614 test_util_control_formats(void *arg)
2616 char *out = NULL;
2617 const char *inp =
2618 "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
2619 size_t sz;
2621 (void)arg;
2622 sz = read_escaped_data(inp, strlen(inp), &out);
2623 tt_str_op(out,OP_EQ,
2624 ".This is a test\nof the emergency \n.system.\n\rZ.\n");
2625 tt_int_op(sz,OP_EQ, strlen(out));
2627 done:
2628 tor_free(out);
2631 #define test_feq(value1,value2) do { \
2632 double v1 = (value1), v2=(value2); \
2633 double tf_diff = v1-v2; \
2634 double tf_tolerance = ((v1+v2)/2.0)/1e8; \
2635 if (tf_diff<0) tf_diff=-tf_diff; \
2636 if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
2637 if (tf_diff<tf_tolerance) { \
2638 TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
2639 } else { \
2640 TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
2642 } while (0)
2644 static void
2645 test_util_sscanf(void *arg)
2647 unsigned u1, u2, u3;
2648 unsigned long ulng;
2649 char s1[20], s2[10], s3[10], ch, *huge = NULL;
2650 int r;
2651 long lng1,lng2;
2652 int int1, int2;
2653 double d1,d2,d3,d4;
2655 /* Simple tests (malformed patterns, literal matching, ...) */
2656 (void)arg;
2657 tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
2658 tt_int_op(-1,OP_EQ,
2659 tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
2660 tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
2661 /* this will fail because we don't allow widths longer than 9999 */
2663 huge = tor_malloc(1000000);
2664 r = tor_sscanf("prettylongstring", "%99999s", huge);
2665 tor_free(huge);
2666 tt_int_op(-1,OP_EQ, r);
2668 #if 0
2669 /* GCC thinks these two are illegal. */
2670 test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
2671 test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
2672 #endif
2673 /* No '%'-strings: always "success" */
2674 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
2675 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
2676 /* Excess data */
2677 tt_int_op(0,OP_EQ,
2678 tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
2679 tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
2680 tt_int_op(0,OP_EQ,
2681 tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
2682 tt_int_op(1,OP_EQ,
2683 tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
2685 /* Numbers (ie. %u) */
2686 tt_int_op(0,OP_EQ,
2687 tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
2688 tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
2689 tt_int_op(12345u,OP_EQ, u1);
2690 tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
2691 tt_int_op(12346u,OP_EQ, u1);
2692 tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
2693 tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
2694 tt_int_op(12348u,OP_EQ, u1);
2695 tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
2696 tt_int_op(0u,OP_EQ, u1);
2697 tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
2698 tt_int_op(0u,OP_EQ, u2);
2699 tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
2700 tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
2701 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
2703 /* Numbers with size (eg. %2u) */
2704 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
2705 tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
2706 tt_int_op(12u,OP_EQ, u1);
2707 tt_int_op(3456u,OP_EQ, u2);
2708 tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
2709 tt_int_op(123456u,OP_EQ, u1);
2710 tt_int_op(1,OP_EQ, tor_sscanf("123457 ", "%8u", &u1));
2711 tt_int_op(123457u,OP_EQ, u1);
2712 tt_int_op(0,OP_EQ, tor_sscanf(" 123456", "%8u", &u1));
2713 tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
2714 tt_int_op(12u,OP_EQ, u1);
2715 tt_int_op(3u,OP_EQ, u2);
2716 tt_int_op(456u,OP_EQ, u3);
2717 tt_int_op(3,OP_EQ,
2718 tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
2719 tt_int_op(67u,OP_EQ, u1);
2720 tt_int_op(8u,OP_EQ, u2);
2721 tt_int_op(99u,OP_EQ, u3);
2722 /* %u does not match space.*/
2723 tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
2724 tt_int_op(12u,OP_EQ, u1);
2725 tt_int_op(3u,OP_EQ, u2);
2726 /* %u does not match negative numbers. */
2727 tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
2728 tt_int_op(67u,OP_EQ, u1);
2729 tt_int_op(8u,OP_EQ, u2);
2730 /* Arbitrary amounts of 0-padding are okay */
2731 tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
2732 &u1, &u2, &u3));
2733 tt_int_op(12u,OP_EQ, u1);
2734 tt_int_op(3u,OP_EQ, u2);
2735 tt_int_op(99u,OP_EQ, u3);
2737 /* Hex (ie. %x) */
2738 tt_int_op(3,OP_EQ,
2739 tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
2740 tt_int_op(0x1234,OP_EQ, u1);
2741 tt_int_op(0x2ABCDEF,OP_EQ, u2);
2742 tt_int_op(0xFF,OP_EQ, u3);
2743 /* Width works on %x */
2744 tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
2745 tt_int_op(0xf00d,OP_EQ, u1);
2746 tt_int_op(0xcafe,OP_EQ, u2);
2747 tt_int_op(444,OP_EQ, u3);
2749 /* Literal '%' (ie. '%%') */
2750 tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
2751 tt_int_op(99,OP_EQ, u1);
2752 tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
2753 tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
2754 tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
2755 tt_int_op(99,OP_EQ, u1);
2756 tt_str_op(s1,OP_EQ, "fresh");
2757 tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
2758 tt_str_op("boo",OP_EQ, s1);
2760 /* Strings (ie. %s) */
2761 tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
2762 tt_str_op(s1,OP_EQ, "hel");
2763 tt_str_op(s2,OP_EQ, "lo");
2764 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
2765 tt_str_op(s3,OP_EQ, "WD");
2766 tt_int_op(40,OP_EQ, u1);
2767 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
2768 tt_str_op(s3,OP_EQ, "WD4");
2769 tt_int_op(0,OP_EQ, u1);
2770 tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
2771 tt_int_op(76,OP_EQ, u1);
2772 tt_str_op(s1,OP_EQ, "trombones");
2774 huge = tor_malloc(1000);
2775 r = tor_sscanf("prettylongstring", "%999s", huge);
2776 tt_int_op(1,OP_EQ, r);
2777 tt_str_op(huge,OP_EQ, "prettylongstring");
2778 tor_free(huge);
2780 /* %s doesn't eat spaces */
2781 tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
2782 tt_str_op(s1,OP_EQ, "hello");
2783 tt_str_op(s2,OP_EQ, "world");
2784 tt_int_op(2,OP_EQ, tor_sscanf("bye world?", "%9s %9s", s1, s2));
2785 tt_str_op(s1,OP_EQ, "bye");
2786 tt_str_op(s2,OP_EQ, "");
2787 tt_int_op(3,OP_EQ,
2788 tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
2789 tt_str_op(s1,OP_EQ, "hi");
2790 tt_str_op(s2,OP_EQ, "");
2791 tt_str_op(s3,OP_EQ, "");
2793 tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
2794 tt_int_op(4,OP_EQ,
2795 tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
2796 tt_int_op(' ',OP_EQ, ch);
2798 r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
2799 tt_int_op(r,OP_EQ, 3);
2800 tt_int_op(int1,OP_EQ, 12345);
2801 tt_int_op(lng1,OP_EQ, -67890);
2802 tt_int_op(int2,OP_EQ, -1);
2804 #if SIZEOF_INT == 4
2805 /* %u */
2806 /* UINT32_MAX should work */
2807 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
2808 tt_int_op(4294967295U,OP_EQ, u1);
2810 /* But UINT32_MAX + 1 shouldn't work */
2811 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
2812 /* but parsing only 9... */
2813 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
2814 tt_int_op(429496729U,OP_EQ, u1);
2816 /* %x */
2817 /* UINT32_MAX should work */
2818 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
2819 tt_int_op(0xFFFFFFFF,OP_EQ, u1);
2821 /* But UINT32_MAX + 1 shouldn't work */
2822 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
2824 /* %d */
2825 /* INT32_MIN and INT32_MAX should work */
2826 r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
2827 tt_int_op(r,OP_EQ, 2);
2828 tt_int_op(int1,OP_EQ, -2147483647 - 1);
2829 tt_int_op(int2,OP_EQ, 2147483647);
2831 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
2832 r = tor_sscanf("-2147483649.", "%d.", &int1);
2833 tt_int_op(r,OP_EQ, 0);
2835 r = tor_sscanf("2147483648.", "%d.", &int1);
2836 tt_int_op(r,OP_EQ, 0);
2838 /* and the first failure stops further processing */
2839 r = tor_sscanf("-2147483648. 2147483648.",
2840 "%d. %d.", &int1, &int2);
2841 tt_int_op(r,OP_EQ, 1);
2843 r = tor_sscanf("-2147483649. 2147483647.",
2844 "%d. %d.", &int1, &int2);
2845 tt_int_op(r,OP_EQ, 0);
2847 r = tor_sscanf("2147483648. -2147483649.",
2848 "%d. %d.", &int1, &int2);
2849 tt_int_op(r,OP_EQ, 0);
2850 #elif SIZEOF_INT == 8
2851 /* %u */
2852 /* UINT64_MAX should work */
2853 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
2854 tt_int_op(18446744073709551615U,OP_EQ, u1);
2856 /* But UINT64_MAX + 1 shouldn't work */
2857 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
2858 /* but parsing only 19... */
2859 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
2860 tt_int_op(1844674407370955161U,OP_EQ, u1);
2862 /* %x */
2863 /* UINT64_MAX should work */
2864 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
2865 tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
2867 /* But UINT64_MAX + 1 shouldn't work */
2868 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
2870 /* %d */
2871 /* INT64_MIN and INT64_MAX should work */
2872 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
2873 "%d. %d.", &int1, &int2);
2874 tt_int_op(r,OP_EQ, 2);
2875 tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
2876 tt_int_op(int2,OP_EQ, 9223372036854775807);
2878 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
2879 r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
2880 tt_int_op(r,OP_EQ, 0);
2882 r = tor_sscanf("9223372036854775808.", "%d.", &int1);
2883 tt_int_op(r,OP_EQ, 0);
2885 /* and the first failure stops further processing */
2886 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
2887 "%d. %d.", &int1, &int2);
2888 tt_int_op(r,OP_EQ, 1);
2890 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
2891 "%d. %d.", &int1, &int2);
2892 tt_int_op(r,OP_EQ, 0);
2894 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
2895 "%d. %d.", &int1, &int2);
2896 tt_int_op(r,OP_EQ, 0);
2897 #endif /* SIZEOF_INT == 4 || ... */
2899 #if SIZEOF_LONG == 4
2900 /* %lu */
2901 /* UINT32_MAX should work */
2902 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
2903 tt_int_op(4294967295UL,OP_EQ, ulng);
2905 /* But UINT32_MAX + 1 shouldn't work */
2906 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
2907 /* but parsing only 9... */
2908 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
2909 tt_int_op(429496729UL,OP_EQ, ulng);
2911 /* %lx */
2912 /* UINT32_MAX should work */
2913 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
2914 tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
2916 /* But UINT32_MAX + 1 shouldn't work */
2917 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
2919 /* %ld */
2920 /* INT32_MIN and INT32_MAX should work */
2921 r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
2922 tt_int_op(r,OP_EQ, 2);
2923 tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
2924 tt_int_op(lng2,OP_EQ, 2147483647L);
2926 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
2927 r = tor_sscanf("-2147483649.", "%ld.", &lng1);
2928 tt_int_op(r,OP_EQ, 0);
2930 r = tor_sscanf("2147483648.", "%ld.", &lng1);
2931 tt_int_op(r,OP_EQ, 0);
2933 /* and the first failure stops further processing */
2934 r = tor_sscanf("-2147483648. 2147483648.",
2935 "%ld. %ld.", &lng1, &lng2);
2936 tt_int_op(r,OP_EQ, 1);
2938 r = tor_sscanf("-2147483649. 2147483647.",
2939 "%ld. %ld.", &lng1, &lng2);
2940 tt_int_op(r,OP_EQ, 0);
2942 r = tor_sscanf("2147483648. -2147483649.",
2943 "%ld. %ld.", &lng1, &lng2);
2944 tt_int_op(r,OP_EQ, 0);
2945 #elif SIZEOF_LONG == 8
2946 /* %lu */
2947 /* UINT64_MAX should work */
2948 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
2949 tt_int_op(18446744073709551615UL,OP_EQ, ulng);
2951 /* But UINT64_MAX + 1 shouldn't work */
2952 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
2953 /* but parsing only 19... */
2954 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
2955 tt_int_op(1844674407370955161UL,OP_EQ, ulng);
2957 /* %lx */
2958 /* UINT64_MAX should work */
2959 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
2960 tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
2962 /* But UINT64_MAX + 1 shouldn't work */
2963 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
2965 /* %ld */
2966 /* INT64_MIN and INT64_MAX should work */
2967 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
2968 "%ld. %ld.", &lng1, &lng2);
2969 tt_int_op(r,OP_EQ, 2);
2970 tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
2971 tt_int_op(lng2,OP_EQ, 9223372036854775807L);
2973 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
2974 r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
2975 tt_int_op(r,OP_EQ, 0);
2977 r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
2978 tt_int_op(r,OP_EQ, 0);
2980 /* and the first failure stops further processing */
2981 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
2982 "%ld. %ld.", &lng1, &lng2);
2983 tt_int_op(r,OP_EQ, 1);
2985 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
2986 "%ld. %ld.", &lng1, &lng2);
2987 tt_int_op(r,OP_EQ, 0);
2989 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
2990 "%ld. %ld.", &lng1, &lng2);
2991 tt_int_op(r,OP_EQ, 0);
2992 #endif /* SIZEOF_LONG == 4 || ... */
2994 r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
2995 "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
2996 tt_int_op(r,OP_EQ, 4);
2997 test_feq(d1, 123.456);
2998 test_feq(d2, .000007);
2999 test_feq(d3, -900123123.2000787);
3000 test_feq(d4, 3.2);
3002 done:
3003 tor_free(huge);
3006 #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
3007 #define tt_ci_char_op(a,op,b) \
3008 tt_char_op(TOR_TOLOWER((int)a),op,TOR_TOLOWER((int)b))
3010 #ifndef HAVE_STRNLEN
3011 static size_t
3012 strnlen(const char *s, size_t len)
3014 const char *p = memchr(s, 0, len);
3015 if (!p)
3016 return len;
3017 return p - s;
3019 #endif /* !defined(HAVE_STRNLEN) */
3021 static void
3022 test_util_format_time_interval(void *arg)
3024 /* use the same sized buffer and integers as tor uses */
3025 #define DBUF_SIZE 64
3026 char dbuf[DBUF_SIZE];
3027 #define T_ "%ld"
3028 long sec, min, hour, day;
3030 /* we don't care about the exact spelling of the
3031 * second(s), minute(s), hour(s), day(s) labels */
3032 #define LABEL_SIZE 21
3033 #define L_ "%20s"
3034 char label_s[LABEL_SIZE];
3035 char label_m[LABEL_SIZE];
3036 char label_h[LABEL_SIZE];
3037 char label_d[LABEL_SIZE];
3039 #define TL_ T_ " " L_
3041 int r;
3043 (void)arg;
3045 /* In these tests, we're not picky about
3046 * spelling or abbreviations */
3048 /* seconds: 0, 1, 9, 10, 59 */
3050 /* ignore exact spelling of "second(s)"*/
3051 format_time_interval(dbuf, sizeof(dbuf), 0);
3052 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3053 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3054 tt_int_op(r,OP_EQ, 2);
3055 tt_ci_char_op(label_s[0],OP_EQ, 's');
3056 tt_int_op(sec,OP_EQ, 0);
3058 format_time_interval(dbuf, sizeof(dbuf), 1);
3059 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3060 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3061 tt_int_op(r,OP_EQ, 2);
3062 tt_ci_char_op(label_s[0],OP_EQ, 's');
3063 tt_int_op(sec,OP_EQ, 1);
3065 format_time_interval(dbuf, sizeof(dbuf), 10);
3066 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3067 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3068 tt_int_op(r,OP_EQ, 2);
3069 tt_ci_char_op(label_s[0],OP_EQ, 's');
3070 tt_int_op(sec,OP_EQ, 10);
3072 format_time_interval(dbuf, sizeof(dbuf), 59);
3073 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3074 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3075 tt_int_op(r,OP_EQ, 2);
3076 tt_ci_char_op(label_s[0],OP_EQ, 's');
3077 tt_int_op(sec,OP_EQ, 59);
3079 /* negative seconds are reported as their absolute value */
3081 format_time_interval(dbuf, sizeof(dbuf), -4);
3082 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3083 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3084 tt_int_op(r,OP_EQ, 2);
3085 tt_ci_char_op(label_s[0],OP_EQ, 's');
3086 tt_int_op(sec,OP_EQ, 4);
3087 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3089 format_time_interval(dbuf, sizeof(dbuf), -32);
3090 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3091 r = tor_sscanf(dbuf, TL_, &sec, label_s);
3092 tt_int_op(r,OP_EQ, 2);
3093 tt_ci_char_op(label_s[0],OP_EQ, 's');
3094 tt_int_op(sec,OP_EQ, 32);
3095 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3097 /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
3099 /* ignore trailing "0 second(s)", if present */
3100 format_time_interval(dbuf, sizeof(dbuf), 60);
3101 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3102 r = tor_sscanf(dbuf, TL_, &min, label_m);
3103 tt_int_op(r,OP_EQ, 2);
3104 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3105 tt_int_op(min,OP_EQ, 1);
3106 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3108 /* ignore exact spelling of "minute(s)," and "second(s)" */
3109 format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
3110 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3111 r = tor_sscanf(dbuf, TL_ " " TL_,
3112 &min, label_m, &sec, label_s);
3113 tt_int_op(r,OP_EQ, 4);
3114 tt_int_op(min,OP_EQ, 1);
3115 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3116 tt_int_op(sec,OP_EQ, 1);
3117 tt_ci_char_op(label_s[0],OP_EQ, 's');
3118 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3120 format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
3121 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3122 r = tor_sscanf(dbuf, TL_ " " TL_,
3123 &min, label_m, &sec, label_s);
3124 tt_int_op(r,OP_EQ, 4);
3125 tt_int_op(min,OP_EQ, 1);
3126 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3127 tt_int_op(sec,OP_EQ, 59);
3128 tt_ci_char_op(label_s[0],OP_EQ, 's');
3130 /* ignore trailing "0 second(s)", if present */
3131 format_time_interval(dbuf, sizeof(dbuf), 60*2);
3132 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3133 r = tor_sscanf(dbuf, TL_, &min, label_m);
3134 tt_int_op(r,OP_EQ, 2);
3135 tt_int_op(min,OP_EQ, 2);
3136 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3138 /* ignore exact spelling of "minute(s)," and "second(s)" */
3139 format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
3140 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3141 r = tor_sscanf(dbuf, TL_ " " TL_,
3142 &min, label_m, &sec, label_s);
3143 tt_int_op(r,OP_EQ, 4);
3144 tt_int_op(min,OP_EQ, 2);
3145 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3146 tt_int_op(sec,OP_EQ, 1);
3147 tt_ci_char_op(label_s[0],OP_EQ, 's');
3149 format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
3150 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3151 r = tor_sscanf(dbuf, TL_ " " TL_,
3152 &min, label_m, &sec, label_s);
3153 tt_int_op(r,OP_EQ, 4);
3154 tt_int_op(min,OP_EQ, 59);
3155 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3156 tt_int_op(sec,OP_EQ, 59);
3157 tt_ci_char_op(label_s[0],OP_EQ, 's');
3159 /* negative minutes are reported as their absolute value */
3161 /* ignore trailing "0 second(s)", if present */
3162 format_time_interval(dbuf, sizeof(dbuf), -3*60);
3163 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3164 r = tor_sscanf(dbuf, TL_, &min, label_m);
3165 tt_int_op(r,OP_EQ, 2);
3166 tt_int_op(min,OP_EQ, 3);
3167 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3169 /* ignore exact spelling of "minute(s)," and "second(s)" */
3170 format_time_interval(dbuf, sizeof(dbuf), -96);
3171 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3172 r = tor_sscanf(dbuf, TL_ " " TL_,
3173 &min, label_m, &sec, label_s);
3174 tt_int_op(r,OP_EQ, 4);
3175 tt_int_op(min,OP_EQ, 1);
3176 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3177 tt_int_op(sec,OP_EQ, 36);
3178 tt_ci_char_op(label_s[0],OP_EQ, 's');
3180 format_time_interval(dbuf, sizeof(dbuf), -2815);
3181 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3182 r = tor_sscanf(dbuf, TL_ " " TL_,
3183 &min, label_m, &sec, label_s);
3184 tt_int_op(r,OP_EQ, 4);
3185 tt_int_op(min,OP_EQ, 46);
3186 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3187 tt_int_op(sec,OP_EQ, 55);
3188 tt_ci_char_op(label_s[0],OP_EQ, 's');
3190 /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
3191 /* always ignore trailing seconds, if present */
3193 /* ignore trailing "0 minute(s)" etc., if present */
3194 format_time_interval(dbuf, sizeof(dbuf), 60*60);
3195 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3196 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3197 tt_int_op(r,OP_EQ, 2);
3198 tt_int_op(hour,OP_EQ, 1);
3199 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3201 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
3202 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3203 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3204 tt_int_op(r,OP_EQ, 2);
3205 tt_int_op(hour,OP_EQ, 1);
3206 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3208 /* ignore exact spelling of "hour(s)," etc. */
3209 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
3210 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3211 r = tor_sscanf(dbuf, TL_ " " TL_,
3212 &hour, label_h, &min, label_m);
3213 tt_int_op(r,OP_EQ, 4);
3214 tt_int_op(hour,OP_EQ, 1);
3215 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3216 tt_int_op(min,OP_EQ, 1);
3217 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3219 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
3220 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3221 r = tor_sscanf(dbuf, TL_ " " TL_,
3222 &hour, label_h, &min, label_m);
3223 tt_int_op(r,OP_EQ, 4);
3224 tt_int_op(hour,OP_EQ, 23);
3225 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3226 tt_int_op(min,OP_EQ, 59);
3227 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3229 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
3230 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3231 r = tor_sscanf(dbuf, TL_ " " TL_,
3232 &hour, label_h, &min, label_m);
3233 tt_int_op(r,OP_EQ, 4);
3234 tt_int_op(hour,OP_EQ, 23);
3235 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3236 tt_int_op(min,OP_EQ, 59);
3237 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3239 /* negative hours are reported as their absolute value */
3241 /* ignore exact spelling of "hour(s)," etc., if present */
3242 format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
3243 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3244 r = tor_sscanf(dbuf, TL_, &hour, label_h);
3245 tt_int_op(r,OP_EQ, 2);
3246 tt_int_op(hour,OP_EQ, 2);
3247 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3249 format_time_interval(dbuf, sizeof(dbuf), -75804);
3250 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3251 r = tor_sscanf(dbuf, TL_ " " TL_,
3252 &hour, label_h, &min, label_m);
3253 tt_int_op(r,OP_EQ, 4);
3254 tt_int_op(hour,OP_EQ, 21);
3255 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3256 tt_int_op(min,OP_EQ, 3);
3257 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3259 /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
3260 /* always ignore trailing seconds, if present */
3262 /* ignore trailing "0 hours(s)" etc., if present */
3263 format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
3264 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3265 r = tor_sscanf(dbuf, TL_, &day, label_d);
3266 tt_int_op(r,OP_EQ, 2);
3267 tt_int_op(day,OP_EQ, 1);
3268 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3270 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
3271 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3272 r = tor_sscanf(dbuf, TL_, &day, label_d);
3273 tt_int_op(r,OP_EQ, 2);
3274 tt_int_op(day,OP_EQ, 1);
3275 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3277 /* ignore exact spelling of "days(s)," etc. */
3278 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
3279 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3280 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3281 &day, label_d, &hour, label_h, &min, label_m);
3282 if (r == -1) {
3283 /* ignore 0 hours(s), if present */
3284 r = tor_sscanf(dbuf, TL_ " " TL_,
3285 &day, label_d, &min, label_m);
3287 tt_assert(r == 4 || r == 6);
3288 tt_int_op(day,OP_EQ, 1);
3289 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3290 if (r == 6) {
3291 tt_int_op(hour,OP_EQ, 0);
3292 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3294 tt_int_op(min,OP_EQ, 1);
3295 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3297 /* ignore trailing "0 minutes(s)" etc., if present */
3298 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
3299 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3300 r = tor_sscanf(dbuf, TL_ " " TL_,
3301 &day, label_d, &hour, label_h);
3302 tt_int_op(r,OP_EQ, 4);
3303 tt_int_op(day,OP_EQ, 1);
3304 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3305 tt_int_op(hour,OP_EQ, 1);
3306 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3308 /* negative days are reported as their absolute value */
3310 format_time_interval(dbuf, sizeof(dbuf), -21936184);
3311 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3312 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3313 &day, label_d, &hour, label_h, &min, label_m);
3314 tt_int_op(r,OP_EQ, 6);
3315 tt_int_op(day,OP_EQ, 253);
3316 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3317 tt_int_op(hour,OP_EQ, 21);
3318 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3319 tt_int_op(min,OP_EQ, 23);
3320 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3322 /* periods > 1 year are reported in days (warn?) */
3324 /* ignore exact spelling of "days(s)," etc., if present */
3325 format_time_interval(dbuf, sizeof(dbuf), 758635154);
3326 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3327 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3328 &day, label_d, &hour, label_h, &min, label_m);
3329 tt_int_op(r,OP_EQ, 6);
3330 tt_int_op(day,OP_EQ, 8780);
3331 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3332 tt_int_op(hour,OP_EQ, 11);
3333 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3334 tt_int_op(min,OP_EQ, 59);
3335 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3337 /* negative periods > 1 year are reported in days (warn?) */
3339 format_time_interval(dbuf, sizeof(dbuf), -1427014922);
3340 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3341 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3342 &day, label_d, &hour, label_h, &min, label_m);
3343 tt_int_op(r,OP_EQ, 6);
3344 tt_int_op(day,OP_EQ, 16516);
3345 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3346 tt_int_op(hour,OP_EQ, 9);
3347 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3348 tt_int_op(min,OP_EQ, 2);
3349 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3351 #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
3353 /* We can try INT32_MIN/MAX */
3354 /* Always ignore second(s) */
3356 /* INT32_MAX */
3357 format_time_interval(dbuf, sizeof(dbuf), 2147483647);
3358 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3359 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3360 &day, label_d, &hour, label_h, &min, label_m);
3361 tt_int_op(r,OP_EQ, 6);
3362 tt_int_op(day,OP_EQ, 24855);
3363 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3364 tt_int_op(hour,OP_EQ, 3);
3365 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3366 tt_int_op(min,OP_EQ, 14);
3367 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3368 /* and 7 seconds - ignored */
3370 /* INT32_MIN: check that we get the absolute value of interval,
3371 * which doesn't actually fit in int32_t.
3372 * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
3373 format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
3374 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3375 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3376 &day, label_d, &hour, label_h, &min, label_m);
3377 tt_int_op(r,OP_EQ, 6);
3378 tt_int_op(day,OP_EQ, 24855);
3379 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3380 tt_int_op(hour,OP_EQ, 3);
3381 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3382 tt_int_op(min,OP_EQ, 14);
3383 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3384 /* and 7 or 8 seconds - ignored */
3386 #endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */
3388 #if SIZEOF_LONG == 8
3390 /* We can try INT64_MIN/MAX */
3391 /* Always ignore second(s) */
3393 /* INT64_MAX */
3394 format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
3395 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3396 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3397 &day, label_d, &hour, label_h, &min, label_m);
3398 tt_int_op(r,OP_EQ, 6);
3399 tt_int_op(day,OP_EQ, 106751991167300L);
3400 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3401 tt_int_op(hour,OP_EQ, 15);
3402 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3403 tt_int_op(min,OP_EQ, 30);
3404 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3405 /* and 7 seconds - ignored */
3407 /* INT64_MIN: check that we get the absolute value of interval,
3408 * which doesn't actually fit in int64_t.
3409 * We expect INT64_MAX */
3410 format_time_interval(dbuf, sizeof(dbuf),
3411 -9223372036854775807L - 1L);
3412 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3413 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3414 &day, label_d, &hour, label_h, &min, label_m);
3415 tt_int_op(r,OP_EQ, 6);
3416 tt_int_op(day,OP_EQ, 106751991167300L);
3417 tt_ci_char_op(label_d[0],OP_EQ, 'd');
3418 tt_int_op(hour,OP_EQ, 15);
3419 tt_ci_char_op(label_h[0],OP_EQ, 'h');
3420 tt_int_op(min,OP_EQ, 30);
3421 tt_ci_char_op(label_m[0],OP_EQ, 'm');
3422 /* and 7 or 8 seconds - ignored */
3424 #endif /* SIZEOF_LONG == 8 */
3426 done:
3430 #undef tt_char_op
3431 #undef tt_ci_char_op
3432 #undef DBUF_SIZE
3433 #undef T_
3434 #undef LABEL_SIZE
3435 #undef L_
3436 #undef TL_
3438 static void
3439 test_util_path_is_relative(void *arg)
3441 /* OS-independent tests */
3442 (void)arg;
3443 tt_int_op(1,OP_EQ, path_is_relative(""));
3444 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3445 tt_int_op(1,OP_EQ, path_is_relative("dir/"));
3446 tt_int_op(1,OP_EQ, path_is_relative("./dir"));
3447 tt_int_op(1,OP_EQ, path_is_relative("../dir"));
3449 tt_int_op(0,OP_EQ, path_is_relative("/"));
3450 tt_int_op(0,OP_EQ, path_is_relative("/dir"));
3451 tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
3453 /* Windows */
3454 #ifdef _WIN32
3455 /* I don't have Windows so I can't test this, hence the "#ifdef
3456 0". These are tests that look useful, so please try to get them
3457 running and uncomment if it all works as it should */
3458 tt_int_op(1,OP_EQ, path_is_relative("dir"));
3459 tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
3460 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
3461 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
3462 tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
3464 tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
3465 tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
3466 tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
3467 #endif /* defined(_WIN32) */
3469 done:
3473 /** Run unittests for memory area allocator */
3474 static void
3475 test_util_memarea(void *arg)
3477 memarea_t *area = memarea_new();
3478 char *p1, *p2, *p3, *p1_orig;
3479 void *malloced_ptr = NULL;
3480 int i;
3482 #ifdef DISABLE_MEMORY_SENTINELS
3483 /* If memory sentinels are disabled, this whole module is just an alias for
3484 malloc(), which is free to lay out memory most any way it wants. */
3485 if (1)
3486 tt_skip();
3487 #endif /* defined(DISABLE_MEMORY_SENTINELS) */
3489 (void)arg;
3490 tt_assert(area);
3492 p1_orig = p1 = memarea_alloc(area,64);
3493 p2 = memarea_alloc_zero(area,52);
3494 p3 = memarea_alloc(area,11);
3496 tt_assert(memarea_owns_ptr(area, p1));
3497 tt_assert(memarea_owns_ptr(area, p2));
3498 tt_assert(memarea_owns_ptr(area, p3));
3499 /* Make sure we left enough space. */
3500 tt_assert(p1+64 <= p2);
3501 tt_assert(p2+52 <= p3);
3502 /* Make sure we aligned. */
3503 tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
3504 tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
3505 tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
3506 tt_assert(!memarea_owns_ptr(area, p3+8192));
3507 tt_assert(!memarea_owns_ptr(area, p3+30));
3508 tt_assert(tor_mem_is_zero(p2, 52));
3509 /* Make sure we don't overalign. */
3510 p1 = memarea_alloc(area, 1);
3511 p2 = memarea_alloc(area, 1);
3512 tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
3514 malloced_ptr = tor_malloc(64);
3515 tt_assert(!memarea_owns_ptr(area, malloced_ptr));
3516 tor_free(malloced_ptr);
3519 /* memarea_memdup */
3521 malloced_ptr = tor_malloc(64);
3522 crypto_rand((char*)malloced_ptr, 64);
3523 p1 = memarea_memdup(area, malloced_ptr, 64);
3524 tt_assert(p1 != malloced_ptr);
3525 tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
3526 tor_free(malloced_ptr);
3529 /* memarea_strdup. */
3530 p1 = memarea_strdup(area,"");
3531 p2 = memarea_strdup(area, "abcd");
3532 tt_assert(p1);
3533 tt_assert(p2);
3534 tt_str_op(p1,OP_EQ, "");
3535 tt_str_op(p2,OP_EQ, "abcd");
3537 /* memarea_strndup. */
3539 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
3540 /* (From Turandot, act 3.) */
3541 size_t len = strlen(s);
3542 p1 = memarea_strndup(area, s, 1000);
3543 p2 = memarea_strndup(area, s, 10);
3544 tt_str_op(p1,OP_EQ, s);
3545 tt_assert(p2 >= p1 + len + 1);
3546 tt_mem_op(s,OP_EQ, p2, 10);
3547 tt_int_op(p2[10],OP_EQ, '\0');
3548 p3 = memarea_strndup(area, s, len);
3549 tt_str_op(p3,OP_EQ, s);
3550 p3 = memarea_strndup(area, s, len-1);
3551 tt_mem_op(s,OP_EQ, p3, len-1);
3552 tt_int_op(p3[len-1],OP_EQ, '\0');
3555 memarea_clear(area);
3556 p1 = memarea_alloc(area, 1);
3557 tt_ptr_op(p1,OP_EQ, p1_orig);
3558 memarea_clear(area);
3559 size_t total = 0, initial_allocation, allocation2, dummy;
3560 memarea_get_stats(area, &initial_allocation, &dummy);
3562 /* Check for running over an area's size. */
3563 for (i = 0; i < 4096; ++i) {
3564 size_t n = crypto_rand_int(6);
3565 p1 = memarea_alloc(area, n);
3566 total += n;
3567 tt_assert(memarea_owns_ptr(area, p1));
3569 memarea_assert_ok(area);
3570 memarea_get_stats(area, &allocation2, &dummy);
3571 /* Make sure we can allocate a too-big object. */
3572 p1 = memarea_alloc_zero(area, 9000);
3573 p2 = memarea_alloc_zero(area, 16);
3574 total += 9000;
3575 total += 16;
3576 tt_assert(memarea_owns_ptr(area, p1));
3577 tt_assert(memarea_owns_ptr(area, p2));
3579 /* Now test stats... */
3580 size_t allocated = 0, used = 0;
3581 memarea_get_stats(area, &allocated, &used);
3582 tt_int_op(used, OP_LE, allocated);
3583 tt_int_op(used, OP_GE, total); /* not EQ, because of alignment and headers*/
3584 tt_int_op(allocated, OP_GT, allocation2);
3586 tt_int_op(allocation2, OP_GT, initial_allocation);
3588 memarea_clear(area);
3589 memarea_get_stats(area, &allocated, &used);
3590 tt_int_op(used, OP_LT, 128); /* Not 0, because of header */
3591 tt_int_op(allocated, OP_EQ, initial_allocation);
3593 done:
3594 memarea_drop_all(area);
3595 tor_free(malloced_ptr);
3598 /** Run unit tests for utility functions to get file names relative to
3599 * the data directory. */
3600 static void
3601 test_util_datadir(void *arg)
3603 char buf[1024];
3604 char *f = NULL;
3605 char *temp_dir = NULL;
3607 (void)arg;
3608 temp_dir = get_datadir_fname(NULL);
3609 f = get_datadir_fname("state");
3610 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
3611 tt_str_op(f,OP_EQ, buf);
3612 tor_free(f);
3613 f = get_datadir_fname2("cache", "thingy");
3614 tor_snprintf(buf, sizeof(buf),
3615 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
3616 tt_str_op(f,OP_EQ, buf);
3617 tor_free(f);
3618 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
3619 tor_snprintf(buf, sizeof(buf),
3620 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
3621 tt_str_op(f,OP_EQ, buf);
3622 tor_free(f);
3623 f = get_datadir_fname_suffix("cache", ".foo");
3624 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
3625 temp_dir);
3626 tt_str_op(f,OP_EQ, buf);
3628 done:
3629 tor_free(f);
3630 tor_free(temp_dir);
3633 static void
3634 test_util_strtok(void *arg)
3636 char buf[128];
3637 char buf2[128];
3638 int i;
3639 char *cp1, *cp2;
3641 (void)arg;
3642 for (i = 0; i < 3; i++) {
3643 const char *pad1="", *pad2="";
3644 switch (i) {
3645 case 0:
3646 break;
3647 case 1:
3648 pad1 = " ";
3649 pad2 = "!";
3650 break;
3651 case 2:
3652 pad1 = " ";
3653 pad2 = ";!";
3654 break;
3656 tor_snprintf(buf, sizeof(buf), "%s", pad1);
3657 tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
3658 tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL);
3659 tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL);
3661 tor_snprintf(buf, sizeof(buf),
3662 "%sGraved on the dark in gestures of descent%s", pad1, pad1);
3663 tor_snprintf(buf2, sizeof(buf2),
3664 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
3665 /* -- "Year's End", Richard Wilbur */
3667 tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3668 tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
3669 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
3670 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
3671 tt_str_op("on",OP_EQ, S1());
3672 tt_str_op("the",OP_EQ, S1());
3673 tt_str_op("dark",OP_EQ, S1());
3674 tt_str_op("seemed",OP_EQ, S2());
3675 tt_str_op("their",OP_EQ, S2());
3676 tt_str_op("own",OP_EQ, S2());
3677 tt_str_op("in",OP_EQ, S1());
3678 tt_str_op("gestures",OP_EQ, S1());
3679 tt_str_op("of",OP_EQ, S1());
3680 tt_str_op("most",OP_EQ, S2());
3681 tt_str_op("perfect",OP_EQ, S2());
3682 tt_str_op("descent",OP_EQ, S1());
3683 tt_str_op("monument",OP_EQ, S2());
3684 tt_ptr_op(NULL,OP_EQ, S1());
3685 tt_ptr_op(NULL,OP_EQ, S2());
3688 buf[0] = 0;
3689 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3690 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
3692 strlcpy(buf, "Howdy!", sizeof(buf));
3693 tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
3694 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
3696 strlcpy(buf, " ", sizeof(buf));
3697 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3698 strlcpy(buf, " ", sizeof(buf));
3699 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3701 strlcpy(buf, "something ", sizeof(buf));
3702 tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
3703 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
3704 done:
3708 static void
3709 test_util_find_str_at_start_of_line(void *ptr)
3711 const char *long_string =
3712 "howdy world. how are you? i hope it's fine.\n"
3713 "hello kitty\n"
3714 "third line";
3715 char *line2 = strchr(long_string,'\n')+1;
3716 char *line3 = strchr(line2,'\n')+1;
3717 const char *short_string = "hello kitty\n"
3718 "second line\n";
3719 char *short_line2 = strchr(short_string,'\n')+1;
3721 (void)ptr;
3723 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
3724 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
3725 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
3726 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
3727 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
3728 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
3729 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
3730 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
3731 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
3732 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
3733 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
3734 tt_ptr_op(line2,OP_EQ,
3735 find_str_at_start_of_line(long_string, "hello kitty\n"));
3736 tt_ptr_op(line2,OP_EQ,
3737 find_str_at_start_of_line(long_string, "hello kitty\nt"));
3738 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
3739 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
3740 tt_ptr_op(NULL, OP_EQ,
3741 find_str_at_start_of_line(long_string, "third line\n"));
3742 tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
3743 "second line\n"));
3744 done:
3748 static void
3749 test_util_string_is_C_identifier(void *ptr)
3751 (void)ptr;
3753 tt_int_op(1,OP_EQ, string_is_C_identifier("string_is_C_identifier"));
3754 tt_int_op(1,OP_EQ, string_is_C_identifier("_string_is_C_identifier"));
3755 tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
3756 tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
3757 tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
3758 tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
3759 tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
3760 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
3761 tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
3762 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
3764 tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
3765 tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
3766 tt_int_op(0,OP_EQ, string_is_C_identifier(""));
3767 tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
3768 tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
3769 tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
3770 tt_int_op(0,OP_EQ, string_is_C_identifier("í"));
3771 tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
3773 done:
3777 static void
3778 test_util_asprintf(void *ptr)
3780 #define LOREMIPSUM \
3781 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
3782 char *cp=NULL, *cp2=NULL;
3783 int r;
3784 (void)ptr;
3786 /* simple string */
3787 r = tor_asprintf(&cp, "simple string 100%% safe");
3788 tt_assert(cp);
3789 tt_str_op("simple string 100% safe",OP_EQ, cp);
3790 tt_int_op(strlen(cp),OP_EQ, r);
3791 tor_free(cp);
3793 /* empty string */
3794 r = tor_asprintf(&cp, "%s", "");
3795 tt_assert(cp);
3796 tt_str_op("",OP_EQ, cp);
3797 tt_int_op(strlen(cp),OP_EQ, r);
3798 tor_free(cp);
3800 /* numbers (%i) */
3801 r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
3802 tt_assert(cp);
3803 tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
3804 tt_int_op(strlen(cp),OP_EQ, r);
3805 /* don't free cp; next test uses it. */
3807 /* numbers (%d) */
3808 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
3809 tt_assert(cp2);
3810 tt_int_op(strlen(cp2),OP_EQ, r);
3811 tt_str_op("First=101, Second=202",OP_EQ, cp2);
3812 tt_assert(cp != cp2);
3813 tor_free(cp);
3814 tor_free(cp2);
3816 /* Glass-box test: a string exactly 128 characters long. */
3817 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
3818 tt_assert(cp);
3819 tt_int_op(128,OP_EQ, r);
3820 tt_int_op(cp[128], OP_EQ, '\0');
3821 tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
3822 tor_free(cp);
3824 /* String longer than 128 characters */
3825 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
3826 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
3827 tt_assert(cp);
3828 tt_int_op(strlen(cp),OP_EQ, r);
3829 tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
3831 done:
3832 tor_free(cp);
3833 tor_free(cp2);
3836 static void
3837 test_util_listdir(void *ptr)
3839 smartlist_t *dir_contents = NULL;
3840 char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
3841 int r;
3842 (void)ptr;
3844 fname1 = tor_strdup(get_fname("hopscotch"));
3845 fname2 = tor_strdup(get_fname("mumblety-peg"));
3846 fname3 = tor_strdup(get_fname(".hidden-file"));
3847 dir1 = tor_strdup(get_fname("some-directory"));
3848 dirname = tor_strdup(get_fname(NULL));
3850 tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
3851 tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
3852 tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
3853 #ifdef _WIN32
3854 r = mkdir(dir1);
3855 #else
3856 r = mkdir(dir1, 0700);
3857 #endif
3858 if (r) {
3859 fprintf(stderr, "Can't create directory %s:", dir1);
3860 perror("");
3861 exit(1);
3864 dir_contents = tor_listdir(dirname);
3865 tt_assert(dir_contents);
3866 /* make sure that each filename is listed. */
3867 tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
3868 tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
3869 tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
3870 tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
3872 tt_assert(!smartlist_contains_string(dir_contents, "."));
3873 tt_assert(!smartlist_contains_string(dir_contents, ".."));
3875 done:
3876 tor_free(fname1);
3877 tor_free(fname2);
3878 tor_free(fname3);
3879 tor_free(dir1);
3880 tor_free(dirname);
3881 if (dir_contents) {
3882 SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
3883 smartlist_free(dir_contents);
3887 static void
3888 test_util_parent_dir(void *ptr)
3890 char *cp;
3891 (void)ptr;
3893 #define T(output,expect_ok,input) \
3894 do { \
3895 int ok; \
3896 cp = tor_strdup(input); \
3897 ok = get_parent_directory(cp); \
3898 tt_int_op(expect_ok, OP_EQ, ok); \
3899 if (ok==0) \
3900 tt_str_op(output, OP_EQ, cp); \
3901 tor_free(cp); \
3902 } while (0);
3904 T("/home/wombat", 0, "/home/wombat/knish");
3905 T("/home/wombat", 0, "/home/wombat/knish/");
3906 T("/home/wombat", 0, "/home/wombat/knish///");
3907 T("./home/wombat", 0, "./home/wombat/knish/");
3908 T("/", 0, "/home");
3909 T("/", 0, "/home//");
3910 T(".", 0, "./wombat");
3911 T(".", 0, "./wombat/");
3912 T(".", 0, "./wombat//");
3913 T("wombat", 0, "wombat/foo");
3914 T("wombat/..", 0, "wombat/../foo");
3915 T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
3916 T("wombat/.", 0, "wombat/./foo");
3917 T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
3918 T("wombat", 0, "wombat/..//");
3919 T("wombat", 0, "wombat/foo/");
3920 T("wombat", 0, "wombat/.foo");
3921 T("wombat", 0, "wombat/.foo/");
3923 T("wombat", -1, "");
3924 T("w", -1, "");
3925 T("wombat", 0, "wombat/knish");
3927 T("/", 0, "/");
3928 T("/", 0, "////");
3930 done:
3931 tor_free(cp);
3934 static void
3935 test_util_ftruncate(void *ptr)
3937 char *buf = NULL;
3938 const char *fname;
3939 int fd = -1;
3940 const char *message = "Hello world";
3941 const char *message2 = "Hola mundo";
3942 struct stat st;
3944 (void) ptr;
3946 fname = get_fname("ftruncate");
3948 fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
3949 tt_int_op(fd, OP_GE, 0);
3951 /* Make the file be there. */
3952 tt_int_op(strlen(message), OP_EQ, write_all(fd, message, strlen(message),0));
3953 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
3954 tt_int_op(0, OP_EQ, fstat(fd, &st));
3955 tt_int_op((int)st.st_size, OP_EQ, strlen(message));
3957 /* Truncate and see if it got truncated */
3958 tt_int_op(0, OP_EQ, tor_ftruncate(fd));
3959 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
3960 tt_int_op(0, OP_EQ, fstat(fd, &st));
3961 tt_int_op((int)st.st_size, OP_EQ, 0);
3963 /* Replace, and see if it got replaced */
3964 tt_int_op(strlen(message2), OP_EQ,
3965 write_all(fd, message2, strlen(message2), 0));
3966 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
3967 tt_int_op(0, OP_EQ, fstat(fd, &st));
3968 tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
3970 close(fd);
3971 fd = -1;
3973 buf = read_file_to_str(fname, 0, NULL);
3974 tt_str_op(message2, OP_EQ, buf);
3976 done:
3977 if (fd >= 0)
3978 close(fd);
3979 tor_free(buf);
3982 static void
3983 test_util_num_cpus(void *arg)
3985 (void)arg;
3986 int num = compute_num_cpus();
3987 if (num < 0)
3988 tt_skip();
3990 tt_int_op(num, OP_GE, 1);
3991 tt_int_op(num, OP_LE, 16);
3993 done:
3997 #ifdef _WIN32
3998 static void
3999 test_util_load_win_lib(void *ptr)
4001 HANDLE h = load_windows_system_library(_T("advapi32.dll"));
4002 (void) ptr;
4004 tt_assert(h);
4005 done:
4006 if (h)
4007 FreeLibrary(h);
4009 #endif /* defined(_WIN32) */
4011 #ifndef _WIN32
4012 static void
4013 clear_hex_errno(char *hex_errno)
4015 memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
4018 static void
4019 test_util_exit_status(void *ptr)
4021 /* Leave an extra byte for a \0 so we can do string comparison */
4022 char hex_errno[HEX_ERRNO_SIZE + 1];
4023 int n;
4025 (void)ptr;
4027 clear_hex_errno(hex_errno);
4028 tt_str_op("",OP_EQ, hex_errno);
4030 clear_hex_errno(hex_errno);
4031 n = format_helper_exit_status(0, 0, hex_errno);
4032 tt_str_op("0/0\n",OP_EQ, hex_errno);
4033 tt_int_op(n,OP_EQ, strlen(hex_errno));
4035 #if SIZEOF_INT == 4
4037 clear_hex_errno(hex_errno);
4038 n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
4039 tt_str_op("0/7FFFFFFF\n",OP_EQ, hex_errno);
4040 tt_int_op(n,OP_EQ, strlen(hex_errno));
4042 clear_hex_errno(hex_errno);
4043 n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
4044 tt_str_op("FF/-80000000\n",OP_EQ, hex_errno);
4045 tt_int_op(n,OP_EQ, strlen(hex_errno));
4046 tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE);
4048 #elif SIZEOF_INT == 8
4050 clear_hex_errno(hex_errno);
4051 n = format_helper_exit_status(0, 0x7FFFFFFFFFFFFFFF, hex_errno);
4052 tt_str_op("0/7FFFFFFFFFFFFFFF\n",OP_EQ, hex_errno);
4053 tt_int_op(n,OP_EQ, strlen(hex_errno));
4055 clear_hex_errno(hex_errno);
4056 n = format_helper_exit_status(0xFF, -0x8000000000000000, hex_errno);
4057 tt_str_op("FF/-8000000000000000\n",OP_EQ, hex_errno);
4058 tt_int_op(n,OP_EQ, strlen(hex_errno));
4059 tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE);
4061 #endif /* SIZEOF_INT == 4 || ... */
4063 clear_hex_errno(hex_errno);
4064 n = format_helper_exit_status(0x7F, 0, hex_errno);
4065 tt_str_op("7F/0\n",OP_EQ, hex_errno);
4066 tt_int_op(n,OP_EQ, strlen(hex_errno));
4068 clear_hex_errno(hex_errno);
4069 n = format_helper_exit_status(0x08, -0x242, hex_errno);
4070 tt_str_op("8/-242\n",OP_EQ, hex_errno);
4071 tt_int_op(n,OP_EQ, strlen(hex_errno));
4073 clear_hex_errno(hex_errno);
4074 tt_str_op("",OP_EQ, hex_errno);
4076 done:
4079 #endif /* !defined(_WIN32) */
4081 #ifndef _WIN32
4082 static void
4083 test_util_string_from_pipe(void *ptr)
4085 int test_pipe[2] = {-1, -1};
4086 int retval = 0;
4087 enum stream_status status = IO_STREAM_TERM;
4088 ssize_t retlen;
4089 char buf[4] = { 0 };
4091 (void)ptr;
4093 errno = 0;
4095 /* Set up a pipe to test on */
4096 retval = pipe(test_pipe);
4097 tt_int_op(retval, OP_EQ, 0);
4099 /* Send in a string. */
4100 retlen = write(test_pipe[1], "ABC", 3);
4101 tt_int_op(retlen, OP_EQ, 3);
4103 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4104 tt_int_op(errno, OP_EQ, 0);
4105 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4106 tt_str_op(buf, OP_EQ, "ABC");
4107 errno = 0;
4109 /* Send in a string that contains a nul. */
4110 retlen = write(test_pipe[1], "AB\0", 3);
4111 tt_int_op(retlen, OP_EQ, 3);
4113 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4114 tt_int_op(errno, OP_EQ, 0);
4115 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4116 tt_str_op(buf, OP_EQ, "AB");
4117 errno = 0;
4119 /* Send in a string that contains a nul only. */
4120 retlen = write(test_pipe[1], "\0", 1);
4121 tt_int_op(retlen, OP_EQ, 1);
4123 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4124 tt_int_op(errno, OP_EQ, 0);
4125 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4126 tt_str_op(buf, OP_EQ, "");
4127 errno = 0;
4129 /* Send in a string that contains a trailing newline. */
4130 retlen = write(test_pipe[1], "AB\n", 3);
4131 tt_int_op(retlen, OP_EQ, 3);
4133 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4134 tt_int_op(errno, OP_EQ, 0);
4135 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4136 tt_str_op(buf, OP_EQ, "AB");
4137 errno = 0;
4139 /* Send in a string that contains a newline only. */
4140 retlen = write(test_pipe[1], "\n", 1);
4141 tt_int_op(retlen, OP_EQ, 1);
4143 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4144 tt_int_op(errno, OP_EQ, 0);
4145 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4146 tt_str_op(buf, OP_EQ, "");
4147 errno = 0;
4149 /* Send in a string and check that we nul terminate return values. */
4150 retlen = write(test_pipe[1], "AAA", 3);
4151 tt_int_op(retlen, OP_EQ, 3);
4153 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4154 tt_int_op(errno, OP_EQ, 0);
4155 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4156 tt_str_op(buf, OP_EQ, "AAA");
4157 tt_mem_op(buf, OP_EQ, "AAA\0", sizeof(buf));
4158 errno = 0;
4160 retlen = write(test_pipe[1], "B", 1);
4161 tt_int_op(retlen, OP_EQ, 1);
4163 memset(buf, '\xff', sizeof(buf));
4164 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4165 tt_int_op(errno, OP_EQ, 0);
4166 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4167 tt_str_op(buf, OP_EQ, "B");
4168 tt_mem_op(buf, OP_EQ, "B\0\xff\xff", sizeof(buf));
4169 errno = 0;
4171 /* Send in multiple lines. */
4172 retlen = write(test_pipe[1], "A\nB", 3);
4173 tt_int_op(retlen, OP_EQ, 3);
4175 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4176 tt_int_op(errno, OP_EQ, 0);
4177 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4178 tt_str_op(buf, OP_EQ, "A\nB");
4179 errno = 0;
4181 /* Send in a line and close */
4182 retlen = write(test_pipe[1], "AB", 2);
4183 tt_int_op(retlen, OP_EQ, 2);
4184 retval = close(test_pipe[1]);
4185 tt_int_op(retval, OP_EQ, 0);
4186 test_pipe[1] = -1;
4188 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4189 tt_int_op(errno, OP_EQ, 0);
4190 tt_int_op(status, OP_EQ, IO_STREAM_OKAY);
4191 tt_str_op(buf, OP_EQ, "AB");
4192 errno = 0;
4194 /* Check for EOF */
4195 status = get_string_from_pipe(test_pipe[0], buf, sizeof(buf)-1);
4196 tt_int_op(errno, OP_EQ, 0);
4197 tt_int_op(status, OP_EQ, IO_STREAM_CLOSED);
4198 errno = 0;
4200 done:
4201 if (test_pipe[0] != -1)
4202 close(test_pipe[0]);
4203 if (test_pipe[1] != -1)
4204 close(test_pipe[1]);
4207 #endif /* !defined(_WIN32) */
4210 * Test for format_hex_number_sigsafe()
4213 static void
4214 test_util_format_hex_number(void *ptr)
4216 int i, len;
4217 char buf[33];
4218 const struct {
4219 const char *str;
4220 unsigned int x;
4221 } test_data[] = {
4222 {"0", 0},
4223 {"1", 1},
4224 {"273A", 0x273a},
4225 {"FFFF", 0xffff},
4226 {"7FFFFFFF", 0x7fffffff},
4227 {"FFFFFFFF", 0xffffffff},
4228 #if UINT_MAX >= 0xffffffff
4229 {"31BC421D", 0x31bc421d},
4230 {"FFFFFFFF", 0xffffffff},
4231 #endif
4232 {NULL, 0}
4235 (void)ptr;
4237 for (i = 0; test_data[i].str != NULL; ++i) {
4238 len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
4239 tt_int_op(len,OP_NE, 0);
4240 tt_int_op(len,OP_EQ, strlen(buf));
4241 tt_str_op(buf,OP_EQ, test_data[i].str);
4244 tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
4245 tt_str_op(buf,OP_EQ, "FFFF");
4246 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
4247 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
4249 done:
4250 return;
4254 * Test for format_hex_number_sigsafe()
4257 static void
4258 test_util_format_dec_number(void *ptr)
4260 int i, len;
4261 char buf[33];
4262 const struct {
4263 const char *str;
4264 unsigned int x;
4265 } test_data[] = {
4266 {"0", 0},
4267 {"1", 1},
4268 {"1234", 1234},
4269 {"12345678", 12345678},
4270 {"99999999", 99999999},
4271 {"100000000", 100000000},
4272 {"4294967295", 4294967295u},
4273 #if UINT_MAX > 0xffffffff
4274 {"18446744073709551615", 18446744073709551615u },
4275 #endif
4276 {NULL, 0}
4279 (void)ptr;
4281 for (i = 0; test_data[i].str != NULL; ++i) {
4282 len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
4283 tt_int_op(len,OP_NE, 0);
4284 tt_int_op(len,OP_EQ, strlen(buf));
4285 tt_str_op(buf,OP_EQ, test_data[i].str);
4287 len = format_dec_number_sigsafe(test_data[i].x, buf,
4288 (int)(strlen(test_data[i].str) + 1));
4289 tt_int_op(len,OP_EQ, strlen(buf));
4290 tt_str_op(buf,OP_EQ, test_data[i].str);
4293 tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
4294 tt_str_op(buf,OP_EQ, "7331");
4295 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
4296 tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
4297 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
4299 done:
4300 return;
4304 * Test that we can properly format a Windows command line
4306 static void
4307 test_util_join_win_cmdline(void *ptr)
4309 /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
4310 * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
4311 * will try to only generate simple cases for the child process to parse;
4312 * i.e. we never embed quoted strings in arguments. */
4314 const char *argvs[][4] = {
4315 {"a", "bb", "CCC", NULL}, // Normal
4316 {NULL, NULL, NULL, NULL}, // Empty argument list
4317 {"", NULL, NULL, NULL}, // Empty argument
4318 {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
4319 {"a\tbc", "dd dd", "E", NULL}, // Whitespace
4320 {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
4321 {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
4322 {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
4323 { NULL } // Terminator
4326 const char *cmdlines[] = {
4327 "a bb CCC",
4329 "\"\"",
4330 "\\\"a b\\\"b CCC\\\"",
4331 "\"a\tbc\" \"dd dd\" E",
4332 "a\\\\\\b \"de fg\" H",
4333 "a\\\\\\\"b \\c D\\",
4334 "\"a\\\\b c\" d E",
4335 NULL // Terminator
4338 int i;
4339 char *joined_argv = NULL;
4341 (void)ptr;
4343 for (i=0; cmdlines[i]!=NULL; i++) {
4344 log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
4345 joined_argv = tor_join_win_cmdline(argvs[i]);
4346 tt_str_op(cmdlines[i],OP_EQ, joined_argv);
4347 tor_free(joined_argv);
4350 done:
4351 tor_free(joined_argv);
4354 #define MAX_SPLIT_LINE_COUNT 4
4355 struct split_lines_test_t {
4356 const char *orig_line; // Line to be split (may contain \0's)
4357 int orig_length; // Length of orig_line
4358 const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
4362 * Test that we properly split a buffer into lines
4364 static void
4365 test_util_split_lines(void *ptr)
4367 /* Test cases. orig_line of last test case must be NULL.
4368 * The last element of split_line[i] must be NULL. */
4369 struct split_lines_test_t tests[] = {
4370 {"", 0, {NULL}},
4371 {"foo", 3, {"foo", NULL}},
4372 {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
4373 {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
4374 {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
4375 {"line 1\r\nline 2", 14, {"line 1", "line 2", NULL}},
4376 {"line 1\r\n\r\nline 2", 16, {"line 1", "line 2", NULL}},
4377 {"line 1\r\n\r\r\r\nline 2", 18, {"line 1", "line 2", NULL}},
4378 {"line 1\r\n\n\n\n\rline 2", 18, {"line 1", "line 2", NULL}},
4379 {"line 1\r\n\r\t\r\nline 3", 18, {"line 1", ".", "line 3", NULL}},
4380 {"\n\t\r\t\nline 3", 11, {".", ".", "line 3", NULL}},
4381 {NULL, 0, { NULL }}
4384 int i, j;
4385 char *orig_line=NULL;
4386 smartlist_t *sl=NULL;
4388 (void)ptr;
4390 for (i=0; tests[i].orig_line; i++) {
4391 sl = smartlist_new();
4392 /* Allocate space for string and trailing NULL */
4393 orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
4394 tor_split_lines(sl, orig_line, tests[i].orig_length);
4396 j = 0;
4397 log_info(LD_GENERAL, "Splitting test %d of length %d",
4398 i, tests[i].orig_length);
4399 SMARTLIST_FOREACH_BEGIN(sl, const char *, line) {
4400 /* Check we have not got too many lines */
4401 tt_int_op(MAX_SPLIT_LINE_COUNT, OP_GT, j);
4402 /* Check that there actually should be a line here */
4403 tt_ptr_op(tests[i].split_line[j], OP_NE, NULL);
4404 log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
4405 j, i, tests[i].split_line[j]);
4406 /* Check that the line is as expected */
4407 tt_str_op(line,OP_EQ, tests[i].split_line[j]);
4408 j++;
4409 } SMARTLIST_FOREACH_END(line);
4410 /* Check that we didn't miss some lines */
4411 tt_ptr_op(NULL,OP_EQ, tests[i].split_line[j]);
4412 tor_free(orig_line);
4413 smartlist_free(sl);
4414 sl = NULL;
4417 done:
4418 tor_free(orig_line);
4419 smartlist_free(sl);
4422 static void
4423 test_util_di_ops(void *arg)
4425 #define LT -1
4426 #define GT 1
4427 #define EQ 0
4428 const struct {
4429 const char *a; int want_sign; const char *b;
4430 } examples[] = {
4431 { "Foo", EQ, "Foo" },
4432 { "foo", GT, "bar", },
4433 { "foobar", EQ ,"foobar" },
4434 { "foobar", LT, "foobaw" },
4435 { "foobar", GT, "f00bar" },
4436 { "foobar", GT, "boobar" },
4437 { "", EQ, "" },
4438 { NULL, 0, NULL },
4441 int i;
4443 (void)arg;
4444 for (i = 0; examples[i].a; ++i) {
4445 size_t len = strlen(examples[i].a);
4446 int eq1, eq2, neq1, neq2, cmp1, cmp2;
4447 tt_int_op(len,OP_EQ, strlen(examples[i].b));
4448 /* We do all of the operations, with operands in both orders. */
4449 eq1 = tor_memeq(examples[i].a, examples[i].b, len);
4450 eq2 = tor_memeq(examples[i].b, examples[i].a, len);
4451 neq1 = tor_memneq(examples[i].a, examples[i].b, len);
4452 neq2 = tor_memneq(examples[i].b, examples[i].a, len);
4453 cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
4454 cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
4456 /* Check for correctness of cmp1 */
4457 if (cmp1 < 0 && examples[i].want_sign != LT)
4458 TT_DIE(("Assertion failed."));
4459 else if (cmp1 > 0 && examples[i].want_sign != GT)
4460 TT_DIE(("Assertion failed."));
4461 else if (cmp1 == 0 && examples[i].want_sign != EQ)
4462 TT_DIE(("Assertion failed."));
4464 /* Check for consistency of everything else with cmp1 */
4465 tt_int_op(eq1,OP_EQ, eq2);
4466 tt_int_op(neq1,OP_EQ, neq2);
4467 tt_int_op(cmp1,OP_EQ, -cmp2);
4468 tt_int_op(eq1,OP_EQ, cmp1 == 0);
4469 tt_int_op(neq1,OP_EQ, !eq1);
4473 uint8_t zz = 0;
4474 uint8_t ii = 0;
4475 int z;
4477 /* exhaustively test tor_memeq and tor_memcmp
4478 * against each possible single-byte numeric difference
4479 * some arithmetic bugs only appear with certain bit patterns */
4480 for (z = 0; z < 256; z++) {
4481 for (i = 0; i < 256; i++) {
4482 ii = (uint8_t)i;
4483 zz = (uint8_t)z;
4484 tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
4485 tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
4486 zz > ii ? GT : EQ);
4487 tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
4488 ii < zz ? LT : EQ);
4493 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
4494 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
4495 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
4496 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
4497 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
4498 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
4499 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
4500 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
4501 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
4503 done:
4507 static void
4508 test_util_di_map(void *arg)
4510 (void)arg;
4511 di_digest256_map_t *dimap = NULL;
4512 uint8_t key1[] = "Robert Anton Wilson ";
4513 uint8_t key2[] = "Martin Gardner, _Fads&fallacies";
4514 uint8_t key3[] = "Tom Lehrer, _Be Prepared_. ";
4515 uint8_t key4[] = "Ursula Le Guin,_A Wizard of... ";
4517 char dflt_entry[] = "'You have made a good beginning', but no more";
4519 tt_int_op(32, OP_EQ, sizeof(key1));
4520 tt_int_op(32, OP_EQ, sizeof(key2));
4521 tt_int_op(32, OP_EQ, sizeof(key3));
4523 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry));
4525 char *str1 = tor_strdup("You are precisely as big as what you love"
4526 " and precisely as small as what you allow"
4527 " to annoy you.");
4528 char *str2 = tor_strdup("Let us hope that Lysenko's success in Russia will"
4529 " serve for many generations to come as another"
4530 " reminder to the world of how quickly and easily"
4531 " a science can be corrupted when ignorant"
4532 " political leaders deem themselves competent"
4533 " to arbitrate scientific disputes");
4534 char *str3 = tor_strdup("Don't write naughty words on walls "
4535 "if you can't spell.");
4537 dimap_add_entry(&dimap, key1, str1);
4538 dimap_add_entry(&dimap, key2, str2);
4539 dimap_add_entry(&dimap, key3, str3);
4541 tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry));
4542 tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry));
4543 tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry));
4544 tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry));
4546 done:
4547 dimap_free(dimap, tor_free_);
4551 * Test counting high bits
4553 static void
4554 test_util_n_bits_set(void *ptr)
4556 (void)ptr;
4557 tt_int_op(0,OP_EQ, n_bits_set_u8(0));
4558 tt_int_op(1,OP_EQ, n_bits_set_u8(1));
4559 tt_int_op(3,OP_EQ, n_bits_set_u8(7));
4560 tt_int_op(1,OP_EQ, n_bits_set_u8(8));
4561 tt_int_op(2,OP_EQ, n_bits_set_u8(129));
4562 tt_int_op(8,OP_EQ, n_bits_set_u8(255));
4563 done:
4568 * Test LHS whitespace (and comment) eater
4570 static void
4571 test_util_eat_whitespace(void *ptr)
4573 const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
4574 char str[80];
4575 size_t i;
4577 (void)ptr;
4579 /* Try one leading ws */
4580 strlcpy(str, "fuubaar", sizeof(str));
4581 for (i = 0; i < sizeof(ws); ++i) {
4582 str[0] = ws[i];
4583 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
4584 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4585 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
4586 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4588 str[0] = '\n';
4589 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
4590 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4591 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4592 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4594 /* Empty string */
4595 strlcpy(str, "", sizeof(str));
4596 tt_ptr_op(str,OP_EQ, eat_whitespace(str));
4597 tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
4598 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4599 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
4601 /* Only ws */
4602 strlcpy(str, " \t\r\n", sizeof(str));
4603 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4604 tt_ptr_op(str + strlen(str),OP_EQ,
4605 eat_whitespace_eos(str, str + strlen(str)));
4606 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
4607 eat_whitespace_no_nl(str));
4608 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
4609 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4611 strlcpy(str, " \t\r ", sizeof(str));
4612 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4613 tt_ptr_op(str + strlen(str),OP_EQ,
4614 eat_whitespace_eos(str, str + strlen(str)));
4615 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
4616 tt_ptr_op(str + strlen(str),OP_EQ,
4617 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4619 /* Multiple ws */
4620 strlcpy(str, "fuubaar", sizeof(str));
4621 for (i = 0; i < sizeof(ws); ++i)
4622 str[i] = ws[i];
4623 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
4624 tt_ptr_op(str + sizeof(ws),OP_EQ,
4625 eat_whitespace_eos(str, str + strlen(str)));
4626 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
4627 tt_ptr_op(str + sizeof(ws),OP_EQ,
4628 eat_whitespace_eos_no_nl(str, str + strlen(str)));
4630 /* Eat comment */
4631 strlcpy(str, "# Comment \n No Comment", sizeof(str));
4632 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
4633 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4634 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4635 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4637 /* Eat comment & ws mix */
4638 strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
4639 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
4640 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
4641 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
4642 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4644 /* Eat entire comment */
4645 strlcpy(str, "#Comment", sizeof(str));
4646 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4647 tt_ptr_op(str + strlen(str),OP_EQ,
4648 eat_whitespace_eos(str, str + strlen(str)));
4649 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
4650 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4652 /* Blank line, then comment */
4653 strlcpy(str, " \t\n # Comment", sizeof(str));
4654 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
4655 tt_ptr_op(str + strlen(str),OP_EQ,
4656 eat_whitespace_eos(str, str + strlen(str)));
4657 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
4658 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
4660 done:
4664 /** Return a newly allocated smartlist containing the lines of text in
4665 * <b>lines</b>. The returned strings are heap-allocated, and must be
4666 * freed by the caller.
4668 * XXXX? Move to container.[hc] ? */
4669 static smartlist_t *
4670 smartlist_new_from_text_lines(const char *lines)
4672 smartlist_t *sl = smartlist_new();
4673 char *last_line;
4675 smartlist_split_string(sl, lines, "\n", 0, 0);
4677 last_line = smartlist_pop_last(sl);
4678 if (last_line != NULL && *last_line != '\0') {
4679 smartlist_add(sl, last_line);
4680 } else {
4681 tor_free(last_line);
4684 return sl;
4687 /** Test smartlist_new_from_text_lines */
4688 static void
4689 test_util_sl_new_from_text_lines(void *ptr)
4691 (void)ptr;
4693 { /* Normal usage */
4694 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
4695 int sl_len = smartlist_len(sl);
4697 tt_want_int_op(sl_len, OP_EQ, 3);
4699 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
4700 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
4701 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
4703 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4704 smartlist_free(sl);
4707 { /* No final newline */
4708 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
4709 int sl_len = smartlist_len(sl);
4711 tt_want_int_op(sl_len, OP_EQ, 3);
4713 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
4714 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
4715 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
4717 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4718 smartlist_free(sl);
4721 { /* No newlines */
4722 smartlist_t *sl = smartlist_new_from_text_lines("foo");
4723 int sl_len = smartlist_len(sl);
4725 tt_want_int_op(sl_len, OP_EQ, 1);
4727 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
4729 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4730 smartlist_free(sl);
4733 { /* No text at all */
4734 smartlist_t *sl = smartlist_new_from_text_lines("");
4735 int sl_len = smartlist_len(sl);
4737 tt_want_int_op(sl_len, OP_EQ, 0);
4739 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
4740 smartlist_free(sl);
4744 static void
4745 test_util_envnames(void *ptr)
4747 (void) ptr;
4749 tt_assert(environment_variable_names_equal("abc", "abc"));
4750 tt_assert(environment_variable_names_equal("abc", "abc="));
4751 tt_assert(environment_variable_names_equal("abc", "abc=def"));
4752 tt_assert(environment_variable_names_equal("abc=def", "abc"));
4753 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
4755 tt_assert(environment_variable_names_equal("abc", "abc"));
4756 tt_assert(environment_variable_names_equal("abc", "abc="));
4757 tt_assert(environment_variable_names_equal("abc", "abc=def"));
4758 tt_assert(environment_variable_names_equal("abc=def", "abc"));
4759 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
4761 tt_assert(!environment_variable_names_equal("abc", "abcd"));
4762 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
4763 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
4764 tt_assert(!environment_variable_names_equal("abc=", "def"));
4765 tt_assert(!environment_variable_names_equal("abc=", "def="));
4766 tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
4768 tt_assert(!environment_variable_names_equal("", "a=def"));
4769 /* A bit surprising. */
4770 tt_assert(environment_variable_names_equal("", "=def"));
4771 tt_assert(environment_variable_names_equal("=y", "=x"));
4773 done:
4777 /** Test process_environment_make */
4778 static void
4779 test_util_make_environment(void *ptr)
4781 const char *env_vars_string =
4782 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4783 "HOME=/home/foozer\n";
4784 const char expected_windows_env_block[] =
4785 "HOME=/home/foozer\000"
4786 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
4787 "\000";
4788 size_t expected_windows_env_block_len =
4789 sizeof(expected_windows_env_block) - 1;
4791 smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
4792 smartlist_t *env_vars_sorted = smartlist_new();
4793 smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
4795 process_environment_t *env;
4797 (void)ptr;
4799 env = process_environment_make(env_vars);
4801 /* Check that the Windows environment block is correct. */
4802 tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
4803 expected_windows_env_block_len));
4805 /* Now for the Unixoid environment block. We don't care which order
4806 * these environment variables are in, so we sort both lists first. */
4808 smartlist_add_all(env_vars_sorted, env_vars);
4811 char **v;
4812 for (v = env->unixoid_environment_block; *v; ++v) {
4813 smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
4817 smartlist_sort_strings(env_vars_sorted);
4818 smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
4820 tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
4821 smartlist_len(env_vars_in_unixoid_env_block_sorted));
4823 int len = smartlist_len(env_vars_sorted);
4824 int i;
4826 if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
4827 len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
4830 for (i = 0; i < len; ++i) {
4831 tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
4832 smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
4836 /* Clean up. */
4837 smartlist_free(env_vars_in_unixoid_env_block_sorted);
4838 smartlist_free(env_vars_sorted);
4840 SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
4841 smartlist_free(env_vars);
4843 process_environment_free(env);
4846 /** Test set_environment_variable_in_smartlist */
4847 static void
4848 test_util_set_env_var_in_sl(void *ptr)
4850 /* The environment variables in these strings are in arbitrary
4851 * order; we sort the resulting lists before comparing them.
4853 * (They *will not* end up in the order shown in
4854 * expected_resulting_env_vars_string.) */
4856 const char *base_env_vars_string =
4857 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4858 "HOME=/home/foozer\n"
4859 "TERM=xterm\n"
4860 "SHELL=/bin/ksh\n"
4861 "USER=foozer\n"
4862 "LOGNAME=foozer\n"
4863 "USERNAME=foozer\n"
4864 "LANG=en_US.utf8\n"
4867 const char *new_env_vars_string =
4868 "TERM=putty\n"
4869 "DISPLAY=:18.0\n"
4872 const char *expected_resulting_env_vars_string =
4873 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4874 "HOME=/home/foozer\n"
4875 "TERM=putty\n"
4876 "SHELL=/bin/ksh\n"
4877 "USER=foozer\n"
4878 "LOGNAME=foozer\n"
4879 "USERNAME=foozer\n"
4880 "LANG=en_US.utf8\n"
4881 "DISPLAY=:18.0\n"
4884 smartlist_t *merged_env_vars =
4885 smartlist_new_from_text_lines(base_env_vars_string);
4886 smartlist_t *new_env_vars =
4887 smartlist_new_from_text_lines(new_env_vars_string);
4888 smartlist_t *expected_resulting_env_vars =
4889 smartlist_new_from_text_lines(expected_resulting_env_vars_string);
4891 /* Elements of merged_env_vars are heap-allocated, and must be
4892 * freed. Some of them are (or should) be freed by
4893 * set_environment_variable_in_smartlist.
4895 * Elements of new_env_vars are heap-allocated, but are copied into
4896 * merged_env_vars, so they are not freed separately at the end of
4897 * the function.
4899 * Elements of expected_resulting_env_vars are heap-allocated, and
4900 * must be freed. */
4902 (void)ptr;
4904 SMARTLIST_FOREACH(new_env_vars, char *, env_var,
4905 set_environment_variable_in_smartlist(merged_env_vars,
4906 env_var,
4907 tor_free_,
4908 1));
4910 smartlist_sort_strings(merged_env_vars);
4911 smartlist_sort_strings(expected_resulting_env_vars);
4913 tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
4914 smartlist_len(expected_resulting_env_vars));
4916 int len = smartlist_len(merged_env_vars);
4917 int i;
4919 if (smartlist_len(expected_resulting_env_vars) < len) {
4920 len = smartlist_len(expected_resulting_env_vars);
4923 for (i = 0; i < len; ++i) {
4924 tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
4925 smartlist_get(expected_resulting_env_vars, i));
4929 /* Clean up. */
4930 SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
4931 smartlist_free(merged_env_vars);
4933 smartlist_free(new_env_vars);
4935 SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
4936 smartlist_free(expected_resulting_env_vars);
4939 static void
4940 test_util_weak_random(void *arg)
4942 int i, j, n[16];
4943 tor_weak_rng_t rng;
4944 (void) arg;
4946 tor_init_weak_random(&rng, (unsigned)time(NULL));
4948 for (i = 1; i <= 256; ++i) {
4949 for (j=0;j<100;++j) {
4950 int r = tor_weak_random_range(&rng, i);
4951 tt_int_op(0, OP_LE, r);
4952 tt_int_op(r, OP_LT, i);
4956 memset(n,0,sizeof(n));
4957 for (j=0;j<8192;++j) {
4958 n[tor_weak_random_range(&rng, 16)]++;
4961 for (i=0;i<16;++i)
4962 tt_int_op(n[i], OP_GT, 0);
4963 done:
4967 static void
4968 test_util_mathlog(void *arg)
4970 double d;
4971 (void) arg;
4973 d = tor_mathlog(2.718281828);
4974 tt_double_op(fabs(d - 1.0), OP_LT, .000001);
4975 d = tor_mathlog(10);
4976 tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
4977 done:
4981 static void
4982 test_util_fraction(void *arg)
4984 uint64_t a,b;
4985 (void)arg;
4987 a = 99; b = 30;
4988 simplify_fraction64(&a,&b);
4989 tt_u64_op(a, OP_EQ, 33);
4990 tt_u64_op(b, OP_EQ, 10);
4992 a = 3000000; b = 10000000;
4993 simplify_fraction64(&a,&b);
4994 tt_u64_op(a, OP_EQ, 3);
4995 tt_u64_op(b, OP_EQ, 10);
4997 a = 0; b = 15;
4998 simplify_fraction64(&a,&b);
4999 tt_u64_op(a, OP_EQ, 0);
5000 tt_u64_op(b, OP_EQ, 1);
5002 done:
5006 static void
5007 test_util_round_to_next_multiple_of(void *arg)
5009 (void)arg;
5011 tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0);
5012 tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0);
5014 tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99);
5015 tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105);
5016 tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99);
5018 tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ,
5019 UINT64_MAX);
5021 tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0);
5022 tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0);
5024 tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99);
5025 tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105);
5026 tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99);
5028 tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ,
5029 UINT32_MAX);
5031 tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0);
5032 tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0);
5034 tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99);
5035 tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105);
5036 tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99);
5038 tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ,
5039 UINT_MAX);
5040 done:
5044 static void
5045 test_util_laplace(void *arg)
5047 /* Sample values produced using Python's SciPy:
5049 * >>> from scipy.stats import laplace
5050 * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
5051 ... loc = 24, scale = 24)
5052 * array([ nan, -inf, -69.88855213, 24. ,
5053 * 24.48486498, 117.88855213, inf, nan])
5055 const double mu = 24.0, b = 24.0;
5056 const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
5057 (void)arg;
5059 tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0));
5060 tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01));
5061 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5));
5062 tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51));
5063 tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99));
5065 /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
5066 * ... loc = 0, scale = 50)
5067 * array([ -inf, -80.47189562, -34.65735903, 0. ,
5068 * 34.65735903, 80.47189562, 195.60115027])
5070 tt_i64_op(INT64_MIN + 20, OP_EQ,
5071 add_laplace_noise(20, 0.0, delta_f, epsilon));
5073 tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon));
5074 tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon));
5075 tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon));
5076 tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon));
5077 tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon));
5078 tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon));
5080 /* Test extreme values of signal with maximally negative values of noise
5081 * 1.0000000000000002 is the smallest number > 1
5082 * 0.0000000000000002 is the double epsilon (error when calculating near 1)
5083 * this is approximately 1/(2^52)
5084 * per https://en.wikipedia.org/wiki/Double_precision
5085 * (let's not descend into the world of subnormals)
5086 * >>> laplace.ppf([0, 0.0000000000000002], loc = 0, scale = 1)
5087 * array([ -inf, -35.45506713])
5089 const double noscale_df = 1.0, noscale_eps = 1.0;
5091 tt_i64_op(INT64_MIN, OP_EQ,
5092 add_laplace_noise(0, 0.0, noscale_df, noscale_eps));
5094 /* is it clipped to INT64_MIN? */
5095 tt_i64_op(INT64_MIN, OP_EQ,
5096 add_laplace_noise(-1, 0.0, noscale_df, noscale_eps));
5097 tt_i64_op(INT64_MIN, OP_EQ,
5098 add_laplace_noise(INT64_MIN, 0.0,
5099 noscale_df, noscale_eps));
5100 /* ... even when scaled? */
5101 tt_i64_op(INT64_MIN, OP_EQ,
5102 add_laplace_noise(0, 0.0, delta_f, epsilon));
5103 tt_i64_op(INT64_MIN, OP_EQ,
5104 add_laplace_noise(0, 0.0,
5105 DBL_MAX, 1));
5106 tt_i64_op(INT64_MIN, OP_EQ,
5107 add_laplace_noise(INT64_MIN, 0.0,
5108 DBL_MAX, 1));
5110 /* does it play nice with INT64_MAX? */
5111 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5112 add_laplace_noise(INT64_MAX, 0.0,
5113 noscale_df, noscale_eps));
5115 /* do near-zero fractional values work? */
5116 const double min_dbl_error = 0.0000000000000002;
5118 tt_i64_op(-35, OP_EQ,
5119 add_laplace_noise(0, min_dbl_error,
5120 noscale_df, noscale_eps));
5121 tt_i64_op(INT64_MIN, OP_EQ,
5122 add_laplace_noise(INT64_MIN, min_dbl_error,
5123 noscale_df, noscale_eps));
5124 tt_i64_op((-35 + INT64_MAX), OP_EQ,
5125 add_laplace_noise(INT64_MAX, min_dbl_error,
5126 noscale_df, noscale_eps));
5127 tt_i64_op(INT64_MIN, OP_EQ,
5128 add_laplace_noise(0, min_dbl_error,
5129 DBL_MAX, 1));
5130 tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ,
5131 add_laplace_noise(INT64_MAX, min_dbl_error,
5132 DBL_MAX, 1));
5133 tt_i64_op(INT64_MIN, OP_EQ,
5134 add_laplace_noise(INT64_MIN, min_dbl_error,
5135 DBL_MAX, 1));
5137 /* does it play nice with INT64_MAX? */
5138 tt_i64_op((INT64_MAX - 35), OP_EQ,
5139 add_laplace_noise(INT64_MAX, min_dbl_error,
5140 noscale_df, noscale_eps));
5142 /* Test extreme values of signal with maximally positive values of noise
5143 * 1.0000000000000002 is the smallest number > 1
5144 * 0.9999999999999998 is the greatest number < 1 by calculation
5145 * per https://en.wikipedia.org/wiki/Double_precision
5146 * >>> laplace.ppf([1.0, 0.9999999999999998], loc = 0, scale = 1)
5147 * array([inf, 35.35050621])
5148 * but the function rejects p == 1.0, so we just use max_dbl_lt_one
5150 const double max_dbl_lt_one = 0.9999999999999998;
5152 /* do near-one fractional values work? */
5153 tt_i64_op(35, OP_EQ,
5154 add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps));
5156 /* is it clipped to INT64_MAX? */
5157 tt_i64_op(INT64_MAX, OP_EQ,
5158 add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one,
5159 noscale_df, noscale_eps));
5160 tt_i64_op(INT64_MAX, OP_EQ,
5161 add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one,
5162 noscale_df, noscale_eps));
5163 tt_i64_op(INT64_MAX, OP_EQ,
5164 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5165 noscale_df, noscale_eps));
5166 /* ... even when scaled? */
5167 tt_i64_op(INT64_MAX, OP_EQ,
5168 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5169 delta_f, epsilon));
5170 tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5171 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5172 DBL_MAX, 1));
5173 tt_i64_op(INT64_MAX, OP_EQ,
5174 add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5175 DBL_MAX, 1));
5176 /* does it play nice with INT64_MIN? */
5177 tt_i64_op((INT64_MIN + 35), OP_EQ,
5178 add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5179 noscale_df, noscale_eps));
5181 done:
5185 static void
5186 test_util_clamp_double_to_int64(void *arg)
5188 (void)arg;
5190 tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL));
5191 tt_i64_op(INT64_MIN, OP_EQ,
5192 clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0));
5193 tt_i64_op(INT64_MIN, OP_EQ,
5194 clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0));
5195 tt_i64_op(((uint64_t) -1) << 53, OP_EQ,
5196 clamp_double_to_int64(-1.0 * pow(2.0, 53.0)));
5197 tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ,
5198 clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0));
5199 tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0));
5200 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9));
5201 tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1));
5202 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0));
5203 tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL));
5204 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1));
5205 tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9));
5206 tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0));
5207 tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ,
5208 clamp_double_to_int64(pow(2.0, 53.0) - 1.0));
5209 tt_i64_op(((int64_t) 1) << 53, OP_EQ,
5210 clamp_double_to_int64(pow(2.0, 53.0)));
5211 tt_i64_op(INT64_MAX, OP_EQ,
5212 clamp_double_to_int64(pow(2.0, 63.0)));
5213 tt_i64_op(INT64_MAX, OP_EQ,
5214 clamp_double_to_int64(pow(2.0, 64.0)));
5215 tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL));
5217 done:
5221 #ifdef FD_CLOEXEC
5222 #define CAN_CHECK_CLOEXEC
5223 static int
5224 fd_is_cloexec(tor_socket_t fd)
5226 int flags = fcntl(fd, F_GETFD, 0);
5227 return (flags & FD_CLOEXEC) == FD_CLOEXEC;
5229 #endif /* defined(FD_CLOEXEC) */
5231 #ifndef _WIN32
5232 #define CAN_CHECK_NONBLOCK
5233 static int
5234 fd_is_nonblocking(tor_socket_t fd)
5236 int flags = fcntl(fd, F_GETFL, 0);
5237 return (flags & O_NONBLOCK) == O_NONBLOCK;
5239 #endif /* !defined(_WIN32) */
5241 #define ERRNO_IS_EPROTO(e) (e == SOCK_ERRNO(EPROTONOSUPPORT))
5242 #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
5244 /* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
5245 static void
5246 test_util_socket(void *arg)
5248 const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
5249 tor_socket_t fd1 = TOR_INVALID_SOCKET;
5250 tor_socket_t fd2 = TOR_INVALID_SOCKET;
5251 tor_socket_t fd3 = TOR_INVALID_SOCKET;
5252 tor_socket_t fd4 = TOR_INVALID_SOCKET;
5253 int n = get_n_open_sockets();
5255 TT_BLATHER(("Starting with %d open sockets.", n));
5257 (void)arg;
5259 fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
5260 int err = tor_socket_errno(fd1);
5261 if (fd1 < 0 && (err == SOCK_ERRNO(EPROTONOSUPPORT) ||
5262 err == SOCK_ERRNO(EAFNOSUPPORT))) {
5263 /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
5264 goto done;
5266 fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
5267 tt_assert(SOCKET_OK(fd1));
5268 tt_assert(SOCKET_OK(fd2));
5269 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5270 //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
5271 //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
5272 fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
5273 fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
5274 tt_assert(SOCKET_OK(fd3));
5275 tt_assert(SOCKET_OK(fd4));
5276 tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
5278 #ifdef CAN_CHECK_CLOEXEC
5279 tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
5280 tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
5281 tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
5282 tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
5283 #endif /* defined(CAN_CHECK_CLOEXEC) */
5284 #ifdef CAN_CHECK_NONBLOCK
5285 tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
5286 tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
5287 tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
5288 tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
5289 #endif /* defined(CAN_CHECK_NONBLOCK) */
5291 tor_assert(tor_close_socket == tor_close_socket__real);
5293 /* we use close_socket__real here so that coverity can tell that we are
5294 * really closing these sockets. */
5295 tor_close_socket__real(fd1);
5296 tor_close_socket__real(fd2);
5297 fd1 = fd2 = TOR_INVALID_SOCKET;
5298 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5299 tor_close_socket__real(fd3);
5300 tor_close_socket__real(fd4);
5301 fd3 = fd4 = TOR_INVALID_SOCKET;
5302 tt_int_op(get_n_open_sockets(), OP_EQ, n);
5304 done:
5305 if (SOCKET_OK(fd1))
5306 tor_close_socket__real(fd1);
5307 if (SOCKET_OK(fd2))
5308 tor_close_socket__real(fd2);
5309 if (SOCKET_OK(fd3))
5310 tor_close_socket__real(fd3);
5311 if (SOCKET_OK(fd4))
5312 tor_close_socket__real(fd4);
5315 #if 0
5316 static int
5317 is_there_a_localhost(int family)
5319 tor_socket_t s;
5320 s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP);
5321 tor_assert(SOCKET_OK(s));
5323 int result = 0;
5324 if (family == AF_INET) {
5325 struct sockaddr_in s_in;
5326 memset(&s_in, 0, sizeof(s_in));
5327 s_in.sin_family = AF_INET;
5328 s_in.sin_addr.s_addr = htonl(0x7f000001);
5329 s_in.sin_port = 0;
5331 if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) {
5332 result = 1;
5334 } else if (family == AF_INET6) {
5335 struct sockaddr_in6 sin6;
5336 memset(&sin6, 0, sizeof(sin6));
5337 sin6.sin6_family = AF_INET6;
5338 sin6.sin6_addr.s6_addr[15] = 1;
5339 sin6.sin6_port = 0;
5341 tor_close_socket(s);
5343 return result;
5345 #endif /* 0 */
5347 /* Test for socketpair and ersatz_socketpair(). We test them both, since
5348 * the latter is a tolerably good way to exersize tor_accept_socket(). */
5349 static void
5350 test_util_socketpair(void *arg)
5352 const int ersatz = !strcmp(arg, "1");
5353 int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
5354 ersatz ? tor_ersatz_socketpair : tor_socketpair;
5355 int n = get_n_open_sockets();
5356 tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
5357 const int family = AF_UNIX;
5358 int socketpair_result = 0;
5360 socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
5362 #ifdef __FreeBSD__
5363 /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail.
5364 * Otherwise, we risk exposing a socketpair on a routable IP address. (Some
5365 * BSD jails use a routable address for localhost. Fortunately, they have
5366 * the real AF_UNIX socketpair.) */
5367 if (ersatz && socketpair_result < 0) {
5368 /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL.
5369 * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */
5370 tt_skip();
5372 #endif /* defined(__FreeBSD__) */
5373 tt_int_op(0, OP_EQ, socketpair_result);
5375 tt_assert(SOCKET_OK(fds[0]));
5376 tt_assert(SOCKET_OK(fds[1]));
5377 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5378 #ifdef CAN_CHECK_CLOEXEC
5379 tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, 1);
5380 tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, 1);
5381 #endif
5382 #ifdef CAN_CHECK_NONBLOCK
5383 tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
5384 tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
5385 #endif
5387 done:
5388 if (SOCKET_OK(fds[0]))
5389 tor_close_socket(fds[0]);
5390 if (SOCKET_OK(fds[1]))
5391 tor_close_socket(fds[1]);
5394 #undef SOCKET_EPROTO
5396 static void
5397 test_util_max_mem(void *arg)
5399 size_t memory1, memory2;
5400 int r, r2;
5401 (void) arg;
5403 r = get_total_system_memory(&memory1);
5404 r2 = get_total_system_memory(&memory2);
5405 tt_int_op(r, OP_EQ, r2);
5406 tt_uint_op(memory2, OP_EQ, memory1);
5408 TT_BLATHER(("System memory: "U64_FORMAT, U64_PRINTF_ARG(memory1)));
5410 if (r==0) {
5411 /* You have at least a megabyte. */
5412 tt_uint_op(memory1, OP_GT, (1<<20));
5413 } else {
5414 /* You do not have a petabyte. */
5415 #if SIZEOF_SIZE_T == SIZEOF_UINT64_T
5416 tt_u64_op(memory1, OP_LT, (U64_LITERAL(1)<<50));
5417 #endif
5420 done:
5424 static void
5425 test_util_hostname_validation(void *arg)
5427 (void)arg;
5429 // Lets try valid hostnames first.
5430 tt_assert(string_is_valid_hostname("torproject.org"));
5431 tt_assert(string_is_valid_hostname("ocw.mit.edu"));
5432 tt_assert(string_is_valid_hostname("i.4cdn.org"));
5433 tt_assert(string_is_valid_hostname("stanford.edu"));
5434 tt_assert(string_is_valid_hostname("multiple-words-with-hypens.jp"));
5436 // Subdomain name cannot start with '-' or '_'.
5437 tt_assert(!string_is_valid_hostname("-torproject.org"));
5438 tt_assert(!string_is_valid_hostname("subdomain.-domain.org"));
5439 tt_assert(!string_is_valid_hostname("-subdomain.domain.org"));
5440 tt_assert(!string_is_valid_hostname("___abc.org"));
5442 // Hostnames cannot contain non-alphanumeric characters.
5443 tt_assert(!string_is_valid_hostname("%%domain.\\org."));
5444 tt_assert(!string_is_valid_hostname("***x.net"));
5445 tt_assert(!string_is_valid_hostname("\xff\xffxyz.org"));
5446 tt_assert(!string_is_valid_hostname("word1 word2.net"));
5448 // Test workaround for nytimes.com stupidity, technically invalid,
5449 // but we allow it since they are big, even though they are failing to
5450 // comply with a ~30 year old standard.
5451 tt_assert(string_is_valid_hostname("core3_euw1.fabrik.nytimes.com"));
5453 // Firefox passes FQDNs with trailing '.'s directly to the SOCKS proxy,
5454 // which is redundant since the spec states DOMAINNAME addresses are fully
5455 // qualified. While unusual, this should be tollerated.
5456 tt_assert(string_is_valid_hostname("core9_euw1.fabrik.nytimes.com."));
5457 tt_assert(!string_is_valid_hostname("..washingtonpost.is.better.com"));
5458 tt_assert(!string_is_valid_hostname("so.is..ft.com"));
5459 tt_assert(!string_is_valid_hostname("..."));
5461 // XXX: do we allow single-label DNS names?
5462 // We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
5463 // but only test pathologically malformed traling '.' cases for now.
5464 tt_assert(!string_is_valid_hostname("."));
5465 tt_assert(!string_is_valid_hostname(".."));
5467 done:
5468 return;
5471 static void
5472 test_util_ipv4_validation(void *arg)
5474 (void)arg;
5476 tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
5477 tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
5479 tt_assert(!string_is_valid_ipv4_address("abcd"));
5480 tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
5481 tt_assert(!string_is_valid_ipv4_address("8.8."));
5483 done:
5484 return;
5487 static void
5488 test_util_writepid(void *arg)
5490 (void) arg;
5492 char *contents = NULL;
5493 const char *fname = get_fname("tmp_pid");
5494 unsigned long pid;
5495 char c;
5497 write_pidfile(fname);
5499 contents = read_file_to_str(fname, 0, NULL);
5500 tt_assert(contents);
5502 int n = tor_sscanf(contents, "%lu\n%c", &pid, &c);
5503 tt_int_op(n, OP_EQ, 1);
5505 #ifdef _WIN32
5506 tt_uint_op(pid, OP_EQ, _getpid());
5507 #else
5508 tt_uint_op(pid, OP_EQ, getpid());
5509 #endif
5511 done:
5512 tor_free(contents);
5515 static void
5516 test_util_get_avail_disk_space(void *arg)
5518 (void) arg;
5519 int64_t val;
5521 /* No answer for nonexistent directory */
5522 val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa");
5523 tt_i64_op(val, OP_EQ, -1);
5525 /* Try the current directory */
5526 val = tor_get_avail_disk_space(".");
5528 #if !defined(HAVE_STATVFS) && !defined(_WIN32)
5529 tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */
5530 #else
5531 tt_i64_op(val, OP_GT, 0); /* You have some space. */
5532 tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */
5533 #endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */
5535 done:
5539 static void
5540 test_util_touch_file(void *arg)
5542 (void) arg;
5543 const char *fname = get_fname("touch");
5545 const time_t now = time(NULL);
5546 struct stat st;
5547 write_bytes_to_file(fname, "abc", 3, 1);
5548 tt_int_op(0, OP_EQ, stat(fname, &st));
5549 /* A subtle point: the filesystem time is not necessarily equal to the
5550 * system clock time, since one can be using a monotonic clock, or coarse
5551 * monotonic clock, or whatever. So we might wind up with an mtime a few
5552 * microseconds ago. Let's just give it a lot of wiggle room. */
5553 tt_i64_op(st.st_mtime, OP_GE, now - 1);
5555 const time_t five_sec_ago = now - 5;
5556 struct utimbuf u = { five_sec_ago, five_sec_ago };
5557 tt_int_op(0, OP_EQ, utime(fname, &u));
5558 tt_int_op(0, OP_EQ, stat(fname, &st));
5559 /* Let's hope that utime/stat give the same second as a round-trip? */
5560 tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
5562 /* Finally we can touch the file */
5563 tt_int_op(0, OP_EQ, touch_file(fname));
5564 tt_int_op(0, OP_EQ, stat(fname, &st));
5565 tt_i64_op(st.st_mtime, OP_GE, now-1);
5567 done:
5571 #ifndef _WIN32
5572 static void
5573 test_util_pwdb(void *arg)
5575 (void) arg;
5576 const struct passwd *me = NULL, *me2, *me3;
5577 char *name = NULL;
5578 char *dir = NULL;
5580 /* Uncached case. */
5581 /* Let's assume that we exist. */
5582 me = tor_getpwuid(getuid());
5583 tt_ptr_op(me, OP_NE, NULL);
5584 name = tor_strdup(me->pw_name);
5586 /* Uncached case */
5587 me2 = tor_getpwnam(name);
5588 tt_ptr_op(me2, OP_NE, NULL);
5589 tt_int_op(me2->pw_uid, OP_EQ, getuid());
5591 /* Cached case */
5592 me3 = tor_getpwuid(getuid());
5593 tt_ptr_op(me3, OP_NE, NULL);
5594 tt_str_op(me3->pw_name, OP_EQ, name);
5596 me3 = tor_getpwnam(name);
5597 tt_ptr_op(me3, OP_NE, NULL);
5598 tt_int_op(me3->pw_uid, OP_EQ, getuid());
5600 dir = get_user_homedir(name);
5601 tt_ptr_op(dir, OP_NE, NULL);
5603 /* Try failing cases. First find a user that doesn't exist by name */
5604 char randbytes[4];
5605 char badname[9];
5606 int i, found=0;
5607 for (i = 0; i < 100; ++i) {
5608 crypto_rand(randbytes, sizeof(randbytes));
5609 base16_encode(badname, sizeof(badname), randbytes, sizeof(randbytes));
5610 if (tor_getpwnam(badname) == NULL) {
5611 found = 1;
5612 break;
5615 tt_assert(found);
5616 tor_free(dir);
5618 /* We should do a LOG_ERR */
5619 setup_full_capture_of_logs(LOG_ERR);
5620 dir = get_user_homedir(badname);
5621 tt_ptr_op(dir, OP_EQ, NULL);
5622 expect_log_msg_containing("not found");
5623 tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1);
5624 teardown_capture_of_logs();
5626 /* Now try to find a user that doesn't exist by ID. */
5627 found = 0;
5628 for (i = 0; i < 1000; ++i) {
5629 uid_t u;
5630 crypto_rand((char*)&u, sizeof(u));
5631 if (tor_getpwuid(u) == NULL) {
5632 found = 1;
5633 break;
5636 tt_assert(found);
5638 done:
5639 tor_free(name);
5640 tor_free(dir);
5641 teardown_capture_of_logs();
5643 #endif /* !defined(_WIN32) */
5645 static void
5646 test_util_calloc_check(void *arg)
5648 (void) arg;
5649 /* Easy cases that are good. */
5650 tt_assert(size_mul_check(0,0));
5651 tt_assert(size_mul_check(0,100));
5652 tt_assert(size_mul_check(100,0));
5653 tt_assert(size_mul_check(100,100));
5655 /* Harder cases that are still good. */
5656 tt_assert(size_mul_check(SIZE_MAX, 1));
5657 tt_assert(size_mul_check(1, SIZE_MAX));
5658 tt_assert(size_mul_check(SIZE_MAX / 10, 9));
5659 tt_assert(size_mul_check(11, SIZE_MAX / 12));
5660 const size_t sqrt_size_max_p1 = ((size_t)1) << (sizeof(size_t) * 4);
5661 tt_assert(size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1 - 1));
5663 /* Cases that overflow */
5664 tt_assert(! size_mul_check(SIZE_MAX, 2));
5665 tt_assert(! size_mul_check(2, SIZE_MAX));
5666 tt_assert(! size_mul_check(SIZE_MAX / 10, 11));
5667 tt_assert(! size_mul_check(11, SIZE_MAX / 10));
5668 tt_assert(! size_mul_check(SIZE_MAX / 8, 9));
5669 tt_assert(! size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1));
5671 done:
5675 static void
5676 test_util_monotonic_time(void *arg)
5678 (void)arg;
5680 monotime_t mt1, mt2;
5681 monotime_coarse_t mtc1, mtc2;
5682 uint64_t nsec1, nsec2, usec1, msec1;
5683 uint64_t nsecc1, nsecc2, usecc1, msecc1;
5685 monotime_init();
5687 monotime_get(&mt1);
5688 monotime_coarse_get(&mtc1);
5689 nsec1 = monotime_absolute_nsec();
5690 usec1 = monotime_absolute_usec();
5691 msec1 = monotime_absolute_msec();
5692 nsecc1 = monotime_coarse_absolute_nsec();
5693 usecc1 = monotime_coarse_absolute_usec();
5694 msecc1 = monotime_coarse_absolute_msec();
5696 tor_sleep_msec(200);
5698 monotime_get(&mt2);
5699 monotime_coarse_get(&mtc2);
5700 nsec2 = monotime_absolute_nsec();
5701 nsecc2 = monotime_coarse_absolute_nsec();
5703 /* We need to be a little careful here since we don't know the system load.
5705 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_GE, 175);
5706 tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_LT, 1000);
5707 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_GE, 125);
5708 tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_LT, 1000);
5709 tt_u64_op(nsec2-nsec1, OP_GE, 175000000);
5710 tt_u64_op(nsec2-nsec1, OP_LT, 1000000000);
5711 tt_u64_op(nsecc2-nsecc1, OP_GE, 125000000);
5712 tt_u64_op(nsecc2-nsecc1, OP_LT, 1000000000);
5714 tt_u64_op(msec1, OP_GE, nsec1 / 1000000);
5715 tt_u64_op(usec1, OP_GE, nsec1 / 1000);
5716 tt_u64_op(msecc1, OP_GE, nsecc1 / 1000000);
5717 tt_u64_op(usecc1, OP_GE, nsecc1 / 1000);
5718 tt_u64_op(msec1, OP_LE, nsec1 / 1000000 + 1);
5719 tt_u64_op(usec1, OP_LE, nsec1 / 1000 + 1000);
5720 tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 1);
5721 tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 1000);
5723 done:
5727 static void
5728 test_util_monotonic_time_ratchet(void *arg)
5730 (void)arg;
5731 monotime_init();
5732 monotime_reset_ratchets_for_testing();
5734 /* win32, performance counter ratchet. */
5735 tt_i64_op(100, OP_EQ, ratchet_performance_counter(100));
5736 tt_i64_op(101, OP_EQ, ratchet_performance_counter(101));
5737 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(2000));
5738 tt_i64_op(2000, OP_EQ, ratchet_performance_counter(100));
5739 tt_i64_op(2005, OP_EQ, ratchet_performance_counter(105));
5740 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1105));
5741 tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1000));
5742 tt_i64_op(3010, OP_EQ, ratchet_performance_counter(1005));
5744 /* win32, GetTickCounts32 ratchet-and-rollover-detector. */
5745 const int64_t R = ((int64_t)1) << 32;
5746 tt_i64_op(5, OP_EQ, ratchet_coarse_performance_counter(5));
5747 tt_i64_op(1000, OP_EQ, ratchet_coarse_performance_counter(1000));
5748 tt_i64_op(5+R, OP_EQ, ratchet_coarse_performance_counter(5));
5749 tt_i64_op(10+R, OP_EQ, ratchet_coarse_performance_counter(10));
5750 tt_i64_op(4+R*2, OP_EQ, ratchet_coarse_performance_counter(4));
5752 /* gettimeofday regular ratchet. */
5753 struct timeval tv_in = {0,0}, tv_out;
5754 tv_in.tv_usec = 9000;
5756 ratchet_timeval(&tv_in, &tv_out);
5757 tt_int_op(tv_out.tv_usec, OP_EQ, 9000);
5758 tt_i64_op(tv_out.tv_sec, OP_EQ, 0);
5760 tv_in.tv_sec = 1337;
5761 tv_in.tv_usec = 0;
5762 ratchet_timeval(&tv_in, &tv_out);
5763 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
5764 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
5766 tv_in.tv_sec = 1336;
5767 tv_in.tv_usec = 500000;
5768 ratchet_timeval(&tv_in, &tv_out);
5769 tt_int_op(tv_out.tv_usec, OP_EQ, 0);
5770 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
5772 tv_in.tv_sec = 1337;
5773 tv_in.tv_usec = 0;
5774 ratchet_timeval(&tv_in, &tv_out);
5775 tt_int_op(tv_out.tv_usec, OP_EQ, 500000);
5776 tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
5778 tv_in.tv_sec = 1337;
5779 tv_in.tv_usec = 600000;
5780 ratchet_timeval(&tv_in, &tv_out);
5781 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
5782 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
5784 tv_in.tv_sec = 1000;
5785 tv_in.tv_usec = 1000;
5786 ratchet_timeval(&tv_in, &tv_out);
5787 tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
5788 tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
5790 tv_in.tv_sec = 2000;
5791 tv_in.tv_usec = 2000;
5792 ratchet_timeval(&tv_in, &tv_out);
5793 tt_int_op(tv_out.tv_usec, OP_EQ, 101000);
5794 tt_i64_op(tv_out.tv_sec, OP_EQ, 2338);
5796 done:
5800 static void
5801 test_util_htonll(void *arg)
5803 (void)arg;
5804 #ifdef WORDS_BIGENDIAN
5805 const uint64_t res_be = 0x8877665544332211;
5806 #else
5807 const uint64_t res_le = 0x1122334455667788;
5808 #endif
5810 tt_u64_op(0, OP_EQ, tor_htonll(0));
5811 tt_u64_op(0, OP_EQ, tor_ntohll(0));
5812 tt_u64_op(UINT64_MAX, OP_EQ, tor_htonll(UINT64_MAX));
5813 tt_u64_op(UINT64_MAX, OP_EQ, tor_ntohll(UINT64_MAX));
5815 #ifdef WORDS_BIGENDIAN
5816 tt_u64_op(res_be, OP_EQ, tor_htonll(0x8877665544332211));
5817 tt_u64_op(res_be, OP_EQ, tor_ntohll(0x8877665544332211));
5818 #else
5819 tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211));
5820 tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211));
5821 #endif /* defined(WORDS_BIGENDIAN) */
5823 done:
5827 static void
5828 test_util_get_unquoted_path(void *arg)
5830 (void)arg;
5832 char *r = NULL;
5834 r = get_unquoted_path("\""); // "
5835 tt_ptr_op(r, OP_EQ, NULL);
5836 tor_free(r);
5838 r = get_unquoted_path("\"\"\""); // """
5839 tt_ptr_op(r, OP_EQ, NULL);
5840 tor_free(r);
5842 r = get_unquoted_path("\\\""); // \"
5843 tt_ptr_op(r, OP_EQ, NULL);
5844 tor_free(r);
5846 r = get_unquoted_path("\\\"\\\""); // \"\"
5847 tt_ptr_op(r, OP_EQ, NULL);
5848 tor_free(r);
5850 r = get_unquoted_path("A\\B\\C\""); // A\B\C"
5851 tt_ptr_op(r, OP_EQ, NULL);
5852 tor_free(r);
5854 r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
5855 tt_ptr_op(r, OP_EQ, NULL);
5856 tor_free(r);
5858 r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
5859 tt_ptr_op(r, OP_EQ, NULL);
5860 tor_free(r);
5862 r = get_unquoted_path("A\\B\"C"); // A\B"C
5863 tt_ptr_op(r, OP_EQ, NULL);
5864 tor_free(r);
5866 r = get_unquoted_path("");
5867 tt_str_op(r, OP_EQ, "");
5868 tor_free(r);
5870 r = get_unquoted_path("\"\""); // ""
5871 tt_str_op(r, OP_EQ, "");
5872 tor_free(r);
5874 r = get_unquoted_path("A\\B\\C"); // A\B\C
5875 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
5876 tor_free(r);
5878 r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
5879 tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
5880 tor_free(r);
5882 r = get_unquoted_path("\"\\\""); // "\"
5883 tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
5884 tor_free(r);
5886 r = get_unquoted_path("\"\\\"\""); // "\""
5887 tt_str_op(r, OP_EQ, "\""); // "
5888 tor_free(r);
5890 r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
5891 tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
5892 tor_free(r);
5894 r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
5895 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
5896 tor_free(r);
5898 r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
5899 tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
5901 done:
5902 tor_free(r);
5905 #define UTIL_LEGACY(name) \
5906 { #name, test_util_ ## name , 0, NULL, NULL }
5908 #define UTIL_TEST(name, flags) \
5909 { #name, test_util_ ## name, flags, NULL, NULL }
5911 #define COMPRESS(name, identifier) \
5912 { "compress/" #name, test_util_compress, 0, &passthrough_setup, \
5913 (char*)(identifier) }
5915 #define COMPRESS_CONCAT(name, identifier) \
5916 { "compress_concat/" #name, test_util_decompress_concatenated, 0, \
5917 &passthrough_setup, \
5918 (char*)(identifier) }
5920 #ifdef _WIN32
5921 #define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
5922 #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
5923 #define UTIL_LEGACY_NO_WIN(n) UTIL_TEST_NO_WIN(n, 0)
5924 #else
5925 #define UTIL_TEST_NO_WIN(n, f) UTIL_TEST(n, (f))
5926 #define UTIL_TEST_WIN_ONLY(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
5927 #define UTIL_LEGACY_NO_WIN(n) UTIL_LEGACY(n)
5928 #endif /* defined(_WIN32) */
5930 struct testcase_t util_tests[] = {
5931 UTIL_LEGACY(time),
5932 UTIL_TEST(parse_http_time, 0),
5933 UTIL_LEGACY(config_line),
5934 UTIL_LEGACY(config_line_quotes),
5935 UTIL_LEGACY(config_line_comment_character),
5936 UTIL_LEGACY(config_line_escaped_content),
5937 UTIL_LEGACY(config_line_crlf),
5938 UTIL_LEGACY_NO_WIN(expand_filename),
5939 UTIL_LEGACY(escape_string_socks),
5940 UTIL_LEGACY(string_is_key_value),
5941 UTIL_LEGACY(strmisc),
5942 UTIL_TEST(parse_integer, 0),
5943 UTIL_LEGACY(pow2),
5944 COMPRESS(zlib, "deflate"),
5945 COMPRESS(gzip, "gzip"),
5946 COMPRESS(lzma, "x-tor-lzma"),
5947 COMPRESS(zstd, "x-zstd"),
5948 COMPRESS(none, "identity"),
5949 COMPRESS_CONCAT(zlib, "deflate"),
5950 COMPRESS_CONCAT(gzip, "gzip"),
5951 COMPRESS_CONCAT(lzma, "x-tor-lzma"),
5952 COMPRESS_CONCAT(zstd, "x-zstd"),
5953 COMPRESS_CONCAT(none, "identity"),
5954 UTIL_TEST(gzip_compression_bomb, TT_FORK),
5955 UTIL_LEGACY(datadir),
5956 UTIL_LEGACY(memarea),
5957 UTIL_LEGACY(control_formats),
5958 UTIL_LEGACY(mmap),
5959 UTIL_TEST(sscanf, TT_FORK),
5960 UTIL_LEGACY(format_time_interval),
5961 UTIL_LEGACY(path_is_relative),
5962 UTIL_LEGACY(strtok),
5963 UTIL_LEGACY(di_ops),
5964 UTIL_TEST(di_map, 0),
5965 UTIL_TEST(round_to_next_multiple_of, 0),
5966 UTIL_TEST(laplace, 0),
5967 UTIL_TEST(clamp_double_to_int64, 0),
5968 UTIL_TEST(find_str_at_start_of_line, 0),
5969 UTIL_TEST(string_is_C_identifier, 0),
5970 UTIL_TEST(asprintf, 0),
5971 UTIL_TEST(listdir, 0),
5972 UTIL_TEST(parent_dir, 0),
5973 UTIL_TEST(ftruncate, 0),
5974 UTIL_TEST(num_cpus, 0),
5975 UTIL_TEST_WIN_ONLY(load_win_lib, 0),
5976 UTIL_TEST_NO_WIN(exit_status, 0),
5977 UTIL_TEST_NO_WIN(string_from_pipe, 0),
5978 UTIL_TEST(format_hex_number, 0),
5979 UTIL_TEST(format_dec_number, 0),
5980 UTIL_TEST(join_win_cmdline, 0),
5981 UTIL_TEST(split_lines, 0),
5982 UTIL_TEST(n_bits_set, 0),
5983 UTIL_TEST(eat_whitespace, 0),
5984 UTIL_TEST(sl_new_from_text_lines, 0),
5985 UTIL_TEST(envnames, 0),
5986 UTIL_TEST(make_environment, 0),
5987 UTIL_TEST(set_env_var_in_sl, 0),
5988 UTIL_TEST(read_file_eof_tiny_limit, 0),
5989 UTIL_TEST(read_file_eof_one_loop_a, 0),
5990 UTIL_TEST(read_file_eof_one_loop_b, 0),
5991 UTIL_TEST(read_file_eof_two_loops, 0),
5992 UTIL_TEST(read_file_eof_two_loops_b, 0),
5993 UTIL_TEST(read_file_eof_zero_bytes, 0),
5994 UTIL_TEST(write_chunks_to_file, 0),
5995 UTIL_TEST(mathlog, 0),
5996 UTIL_TEST(fraction, 0),
5997 UTIL_TEST(weak_random, 0),
5998 { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
5999 (void*)"4" },
6000 { "socket_ipv6", test_util_socket, TT_FORK,
6001 &passthrough_setup, (void*)"6" },
6002 { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
6003 (void*)"0" },
6004 { "socketpair_ersatz", test_util_socketpair, TT_FORK,
6005 &passthrough_setup, (void*)"1" },
6006 UTIL_TEST(max_mem, 0),
6007 UTIL_TEST(hostname_validation, 0),
6008 UTIL_TEST(ipv4_validation, 0),
6009 UTIL_TEST(writepid, 0),
6010 UTIL_TEST(get_avail_disk_space, 0),
6011 UTIL_TEST(touch_file, 0),
6012 UTIL_TEST_NO_WIN(pwdb, TT_FORK),
6013 UTIL_TEST(calloc_check, 0),
6014 UTIL_TEST(monotonic_time, 0),
6015 UTIL_TEST(monotonic_time_ratchet, TT_FORK),
6016 UTIL_TEST(htonll, 0),
6017 UTIL_TEST(get_unquoted_path, 0),
6018 END_OF_TESTCASES