Merge remote-tracking branch 'public/bug13796'
[tor.git] / src / test / test_util.c
blobe5df5b4494988cded9455da7b7769ff526e45f2f
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2015, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #include "orconfig.h"
7 #define COMPAT_PRIVATE
8 #define CONTROL_PRIVATE
9 #define MEMPOOL_PRIVATE
10 #define UTIL_PRIVATE
11 #include "or.h"
12 #include "config.h"
13 #include "control.h"
14 #include "test.h"
15 #ifdef ENABLE_MEMPOOLS
16 #include "mempool.h"
17 #endif /* ENABLE_MEMPOOLS */
18 #include "memarea.h"
19 #include "util_process.h"
21 #ifdef _WIN32
22 #include <tchar.h>
23 #endif
24 #include <math.h>
25 #include <ctype.h>
27 /* XXXX this is a minimal wrapper to make the unit tests compile with the
28 * changed tor_timegm interface. */
29 static time_t
30 tor_timegm_wrapper(const struct tm *tm)
32 time_t t;
33 if (tor_timegm(tm, &t) < 0)
34 return -1;
35 return t;
38 #define tor_timegm tor_timegm_wrapper
40 static void
41 test_util_read_until_eof_impl(const char *fname, size_t file_len,
42 size_t read_limit)
44 char *fifo_name = NULL;
45 char *test_str = NULL;
46 char *str = NULL;
47 size_t sz = 9999999;
48 int fd = -1;
49 int r;
51 fifo_name = tor_strdup(get_fname(fname));
52 test_str = tor_malloc(file_len);
53 crypto_rand(test_str, file_len);
55 r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
56 tt_int_op(r, OP_EQ, 0);
58 fd = open(fifo_name, O_RDONLY|O_BINARY);
59 tt_int_op(fd, OP_GE, 0);
60 str = read_file_to_str_until_eof(fd, read_limit, &sz);
61 tt_assert(str != NULL);
63 if (read_limit < file_len)
64 tt_int_op(sz, OP_EQ, read_limit);
65 else
66 tt_int_op(sz, OP_EQ, file_len);
68 tt_mem_op(test_str, OP_EQ, str, sz);
69 tt_int_op(str[sz], OP_EQ, '\0');
71 done:
72 unlink(fifo_name);
73 tor_free(fifo_name);
74 tor_free(test_str);
75 tor_free(str);
76 if (fd >= 0)
77 close(fd);
80 static void
81 test_util_read_file_eof_tiny_limit(void *arg)
83 (void)arg;
84 // purposely set limit shorter than what we wrote to the FIFO to
85 // test the maximum, and that it puts the NUL in the right spot
87 test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
90 static void
91 test_util_read_file_eof_one_loop_a(void *arg)
93 (void)arg;
94 test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
97 static void
98 test_util_read_file_eof_one_loop_b(void *arg)
100 (void)arg;
101 test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
104 static void
105 test_util_read_file_eof_two_loops(void *arg)
107 (void)arg;
108 // write more than 1024 bytes to the FIFO to test two passes through
109 // the loop in the method; if the re-alloc size is changed this
110 // should be updated as well.
112 test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
115 static void
116 test_util_read_file_eof_two_loops_b(void *arg)
118 (void)arg;
120 test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
123 static void
124 test_util_read_file_eof_zero_bytes(void *arg)
126 (void)arg;
127 // zero-byte fifo
128 test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
131 /* Test the basic expected behaviour for write_chunks_to_file.
132 * NOTE: This will need to be updated if we ever change the tempfile location
133 * or extension */
134 static void
135 test_util_write_chunks_to_file(void *arg)
137 char *fname = NULL;
138 char *tempname = NULL;
139 char *str = NULL;
140 int r;
141 struct stat st;
143 /* These should be two different sizes to ensure the data is different
144 * between the data file and the temp file's 'known string' */
145 int temp_str_len = 1024;
146 int data_str_len = 512;
147 char *data_str = tor_malloc(data_str_len);
148 char *temp_str = tor_malloc(temp_str_len);
150 smartlist_t *chunks = smartlist_new();
151 sized_chunk_t c = {data_str, data_str_len/2};
152 sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
153 (void)arg;
155 crypto_rand(temp_str, temp_str_len);
156 crypto_rand(data_str, data_str_len);
158 // Ensure it can write multiple chunks
160 smartlist_add(chunks, &c);
161 smartlist_add(chunks, &c2);
164 * Check if it writes using a tempfile
166 fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
167 tor_asprintf(&tempname, "%s.tmp", fname);
169 // write a known string to a file where the tempfile will be
170 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
171 tt_int_op(r, OP_EQ, 0);
173 // call write_chunks_to_file
174 r = write_chunks_to_file(fname, chunks, 1, 0);
175 tt_int_op(r, OP_EQ, 0);
177 // assert the file has been written (expected size)
178 str = read_file_to_str(fname, RFTS_BIN, &st);
179 tt_assert(str != NULL);
180 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
181 tt_mem_op(data_str, OP_EQ, str, data_str_len);
182 tor_free(str);
184 // assert that the tempfile is removed (should not leave artifacts)
185 str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
186 tt_assert(str == NULL);
188 // Remove old testfile for second test
189 r = unlink(fname);
190 tt_int_op(r, OP_EQ, 0);
191 tor_free(fname);
192 tor_free(tempname);
195 * Check if it skips using a tempfile with flags
197 fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
198 tor_asprintf(&tempname, "%s.tmp", fname);
200 // write a known string to a file where the tempfile will be
201 r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
202 tt_int_op(r, OP_EQ, 0);
204 // call write_chunks_to_file with no_tempfile = true
205 r = write_chunks_to_file(fname, chunks, 1, 1);
206 tt_int_op(r, OP_EQ, 0);
208 // assert the file has been written (expected size)
209 str = read_file_to_str(fname, RFTS_BIN, &st);
210 tt_assert(str != NULL);
211 tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
212 tt_mem_op(data_str, OP_EQ, str, data_str_len);
213 tor_free(str);
215 // assert the tempfile still contains the known string
216 str = read_file_to_str(tempname, RFTS_BIN, &st);
217 tt_assert(str != NULL);
218 tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
219 tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
221 done:
222 unlink(fname);
223 unlink(tempname);
224 smartlist_free(chunks);
225 tor_free(fname);
226 tor_free(tempname);
227 tor_free(str);
228 tor_free(data_str);
229 tor_free(temp_str);
232 #define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
233 /** test the minimum set of struct tm fields needed for a unique epoch value
234 * this is also the set we use to test tor_timegm */
235 #define TM_EQUAL(a, b) \
236 TT_STMT_BEGIN \
237 _TFE(a, b, tm_year); \
238 _TFE(a, b, tm_mon ); \
239 _TFE(a, b, tm_mday); \
240 _TFE(a, b, tm_hour); \
241 _TFE(a, b, tm_min ); \
242 _TFE(a, b, tm_sec ); \
243 TT_STMT_END
245 static void
246 test_util_time(void *arg)
248 struct timeval start, end;
249 struct tm a_time, b_time;
250 char timestr[128];
251 time_t t_res;
252 int i;
253 struct timeval tv;
255 /* Test tv_udiff */
257 (void)arg;
258 start.tv_sec = 5;
259 start.tv_usec = 5000;
261 end.tv_sec = 5;
262 end.tv_usec = 5000;
264 tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
266 end.tv_usec = 7000;
268 tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
270 end.tv_sec = 6;
272 tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
274 end.tv_usec = 0;
276 tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
278 end.tv_sec = 4;
280 tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
282 /* Test tor_timegm & tor_gmtime_r */
284 /* The test values here are confirmed to be correct on a platform
285 * with a working timegm & gmtime_r. */
287 /* Start with known-zero a_time and b_time.
288 * This avoids passing uninitialised values to TM_EQUAL in a_time.
289 * Zeroing may not be needed for b_time, as long as tor_gmtime_r
290 * never reads the existing values in the structure.
291 * But we really don't want intermittently failing tests. */
292 memset(&a_time, 0, sizeof(struct tm));
293 memset(&b_time, 0, sizeof(struct tm));
295 a_time.tm_year = 2003-1900;
296 a_time.tm_mon = 7;
297 a_time.tm_mday = 30;
298 a_time.tm_hour = 6;
299 a_time.tm_min = 14;
300 a_time.tm_sec = 55;
301 t_res = 1062224095UL;
302 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
303 tor_gmtime_r(&t_res, &b_time);
304 TM_EQUAL(a_time, b_time);
306 a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
307 t_res = 1093846495UL;
308 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
309 tor_gmtime_r(&t_res, &b_time);
310 TM_EQUAL(a_time, b_time);
312 a_time.tm_mon = 1; /* Try a leap year, in feb. */
313 a_time.tm_mday = 10;
314 t_res = 1076393695UL;
315 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
316 tor_gmtime_r(&t_res, &b_time);
317 TM_EQUAL(a_time, b_time);
319 a_time.tm_mon = 0;
320 t_res = 1073715295UL;
321 tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
322 tor_gmtime_r(&t_res, &b_time);
323 TM_EQUAL(a_time, b_time);
325 /* Test tor_timegm out of range */
327 /* year */
329 /* Wrong year < 1970 */
330 a_time.tm_year = 1969-1900;
331 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
333 a_time.tm_year = -1-1900;
334 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
336 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
337 a_time.tm_year = -1*(1 << 16);
338 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
340 /* one of the smallest tm_year values my 64 bit system supports:
341 * t_res = -9223372036854775LL without clamping */
342 a_time.tm_year = -292275055-1900;
343 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
345 a_time.tm_year = INT32_MIN;
346 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
347 #endif
349 #if SIZEOF_INT == 8
350 a_time.tm_year = -1*(1 << 48);
351 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
353 /* while unlikely, the system's gmtime(_r) could return
354 * a "correct" retrospective gregorian negative year value,
355 * which I'm pretty sure is:
356 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
357 * 730485 is the number of days in two millenia, including leap days */
358 a_time.tm_year = -292277022657-1900;
359 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
361 a_time.tm_year = INT64_MIN;
362 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
363 #endif
365 /* Wrong year >= INT32_MAX - 1900 */
366 #if SIZEOF_INT == 4 || SIZEOF_INT == 8
367 a_time.tm_year = INT32_MAX-1900;
368 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
370 a_time.tm_year = INT32_MAX;
371 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
372 #endif
374 #if SIZEOF_INT == 8
375 /* one of the largest tm_year values my 64 bit system supports */
376 a_time.tm_year = 292278994-1900;
377 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
379 /* while unlikely, the system's gmtime(_r) could return
380 * a "correct" proleptic gregorian year value,
381 * which I'm pretty sure is:
382 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
383 * 730485 is the number of days in two millenia, including leap days */
384 a_time.tm_year = 292277026596-1900;
385 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
387 a_time.tm_year = INT64_MAX-1900;
388 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
390 a_time.tm_year = INT64_MAX;
391 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
392 #endif
394 /* month */
395 a_time.tm_year = 2007-1900; /* restore valid year */
397 a_time.tm_mon = 12; /* Wrong month, it's 0-based */
398 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
400 a_time.tm_mon = -1; /* Wrong month */
401 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
403 /* day */
404 a_time.tm_mon = 6; /* Try July */
405 a_time.tm_mday = 32; /* Wrong day */
406 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
408 a_time.tm_mon = 5; /* Try June */
409 a_time.tm_mday = 31; /* Wrong day */
410 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
412 a_time.tm_year = 2008-1900; /* Try a leap year */
413 a_time.tm_mon = 1; /* in feb. */
414 a_time.tm_mday = 30; /* Wrong day */
415 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
417 a_time.tm_year = 2011-1900; /* Try a non-leap year */
418 a_time.tm_mon = 1; /* in feb. */
419 a_time.tm_mday = 29; /* Wrong day */
420 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
422 a_time.tm_mday = 0; /* Wrong day, it's 1-based (to be different) */
423 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
425 /* hour */
426 a_time.tm_mday = 3; /* restore valid month day */
428 a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
429 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
431 a_time.tm_hour = -1; /* Wrong hour */
432 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
434 /* minute */
435 a_time.tm_hour = 22; /* restore valid hour */
437 a_time.tm_min = 60; /* Wrong minute, it's 0-based */
438 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
440 a_time.tm_min = -1; /* Wrong minute */
441 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
443 /* second */
444 a_time.tm_min = 37; /* restore valid minute */
446 a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
447 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
449 a_time.tm_sec = -1; /* Wrong second */
450 tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
452 /* Test tor_gmtime_r out of range */
454 /* time_t < 0 yields a year clamped to 1 or 1970,
455 * depending on whether the implementation of the system gmtime(_r)
456 * sets struct tm (1) or not (1970) */
457 t_res = -1;
458 tor_gmtime_r(&t_res, &b_time);
459 tt_assert(b_time.tm_year == (1970-1900) ||
460 b_time.tm_year == (1969-1900));
462 if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
463 t_res = -1*(1 << 30);
464 tor_gmtime_r(&t_res, &b_time);
465 tt_assert(b_time.tm_year == (1970-1900) ||
466 b_time.tm_year == (1935-1900));
468 t_res = INT32_MIN;
469 tor_gmtime_r(&t_res, &b_time);
470 tt_assert(b_time.tm_year == (1970-1900) ||
471 b_time.tm_year == (1901-1900));
474 #if SIZEOF_TIME_T == 8
476 /* one of the smallest tm_year values my 64 bit system supports:
477 * b_time.tm_year == (-292275055LL-1900LL) without clamping */
478 t_res = -9223372036854775LL;
479 tor_gmtime_r(&t_res, &b_time);
480 tt_assert(b_time.tm_year == (1970-1900) ||
481 b_time.tm_year == (1-1900));
483 /* while unlikely, the system's gmtime(_r) could return
484 * a "correct" retrospective gregorian negative year value,
485 * which I'm pretty sure is:
486 * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
487 * 730485 is the number of days in two millenia, including leap days
488 * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
489 t_res = INT64_MIN;
490 tor_gmtime_r(&t_res, &b_time);
491 tt_assert(b_time.tm_year == (1970-1900) ||
492 b_time.tm_year == (1-1900));
494 #endif
496 /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
497 * depending on whether the implementation of the system gmtime(_r)
498 * sets struct tm (9999) or not (2037) */
499 #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
501 t_res = 3*(1 << 29);
502 tor_gmtime_r(&t_res, &b_time);
503 tt_assert(b_time.tm_year == (2021-1900));
505 t_res = INT32_MAX;
506 tor_gmtime_r(&t_res, &b_time);
507 tt_assert(b_time.tm_year == (2037-1900) ||
508 b_time.tm_year == (2038-1900));
510 #endif
512 #if SIZEOF_TIME_T == 8
514 /* one of the largest tm_year values my 64 bit system supports:
515 * b_time.tm_year == (292278994L-1900L) without clamping */
516 t_res = 9223372036854775LL;
517 tor_gmtime_r(&t_res, &b_time);
518 tt_assert(b_time.tm_year == (2037-1900) ||
519 b_time.tm_year == (9999-1900));
521 /* while unlikely, the system's gmtime(_r) could return
522 * a "correct" proleptic gregorian year value,
523 * which I'm pretty sure is:
524 * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
525 * 730485 is the number of days in two millenia, including leap days
526 * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
527 t_res = INT64_MAX;
528 tor_gmtime_r(&t_res, &b_time);
529 tt_assert(b_time.tm_year == (2037-1900) ||
530 b_time.tm_year == (9999-1900));
532 #endif
534 /* Test {format,parse}_rfc1123_time */
536 format_rfc1123_time(timestr, 0);
537 tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
538 format_rfc1123_time(timestr, (time_t)1091580502UL);
539 tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
541 t_res = 0;
542 i = parse_rfc1123_time(timestr, &t_res);
543 tt_int_op(0,OP_EQ, i);
544 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
545 /* The timezone doesn't matter */
546 t_res = 0;
547 tt_int_op(0,OP_EQ,
548 parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
549 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
550 tt_int_op(-1,OP_EQ,
551 parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
552 tt_int_op(-1,OP_EQ,
553 parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
554 tt_int_op(-1,OP_EQ,
555 parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
556 tt_int_op(-1,OP_EQ,
557 parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
558 tt_int_op(-1,OP_EQ,
559 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
560 tt_int_op(-1,OP_EQ,
561 parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
562 tt_int_op(-1,OP_EQ,
563 parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
564 tt_int_op(-1,OP_EQ,
565 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
567 tt_int_op(-1,OP_EQ,
568 parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
569 tt_int_op(-1,OP_EQ,
570 parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
572 /* Test parse_iso_time */
574 t_res = 0;
575 i = parse_iso_time("", &t_res);
576 tt_int_op(-1,OP_EQ, i);
577 t_res = 0;
578 i = parse_iso_time("2004-08-32 00:48:22", &t_res);
579 tt_int_op(-1,OP_EQ, i);
580 t_res = 0;
581 i = parse_iso_time("1969-08-03 00:48:22", &t_res);
582 tt_int_op(-1,OP_EQ, i);
584 t_res = 0;
585 i = parse_iso_time("2004-08-04 00:48:22", &t_res);
586 tt_int_op(0,OP_EQ, i);
587 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
588 t_res = 0;
589 i = parse_iso_time("2004-8-4 0:48:22", &t_res);
590 tt_int_op(0,OP_EQ, i);
591 tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
592 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
593 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
594 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
595 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
596 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
597 tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
598 tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
599 tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
600 tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
601 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
602 tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
604 /* Test tor_gettimeofday */
606 end.tv_sec = 4;
607 end.tv_usec = 999990;
608 start.tv_sec = 1;
609 start.tv_usec = 500;
611 tor_gettimeofday(&start);
612 /* now make sure time works. */
613 tor_gettimeofday(&end);
614 /* We might've timewarped a little. */
615 tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
617 /* Test format_iso_time */
619 tv.tv_sec = (time_t)1326296338;
620 tv.tv_usec = 3060;
621 format_iso_time(timestr, (time_t)tv.tv_sec);
622 tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
623 /* The output of format_local_iso_time will vary by timezone, and setting
624 our timezone for testing purposes would be a nontrivial flaky pain.
625 Skip this test for now.
626 format_local_iso_time(timestr, tv.tv_sec);
627 test_streq("2012-01-11 10:38:58", timestr);
629 format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
630 tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
631 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
632 format_iso_time_nospace_usec(timestr, &tv);
633 tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
634 tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
636 done:
640 static void
641 test_util_parse_http_time(void *arg)
643 struct tm a_time;
644 char b[ISO_TIME_LEN+1];
645 (void)arg;
647 #define T(s) do { \
648 format_iso_time(b, tor_timegm(&a_time)); \
649 tt_str_op(b, OP_EQ, (s)); \
650 b[0]='\0'; \
651 } while (0)
653 /* Test parse_http_time */
655 tt_int_op(-1,OP_EQ,
656 parse_http_time("", &a_time));
657 tt_int_op(-1,OP_EQ,
658 parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
659 tt_int_op(-1,OP_EQ,
660 parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
661 tt_int_op(-1,OP_EQ,
662 parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
663 tt_int_op(-1,OP_EQ,
664 parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
665 tt_int_op(-1,OP_EQ,
666 parse_http_time("Sunday, August the third", &a_time));
667 tt_int_op(-1,OP_EQ,
668 parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
670 tt_int_op(0,OP_EQ,
671 parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
672 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
673 T("1994-08-04 00:48:22");
674 tt_int_op(0,OP_EQ,
675 parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
676 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
677 T("1994-08-04 00:48:22");
678 tt_int_op(0,OP_EQ,
679 parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
680 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
681 T("1994-08-04 00:48:22");
682 tt_int_op(0,OP_EQ,
683 parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
684 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
685 T("1994-08-04 00:48:22");
686 tt_int_op(0,OP_EQ,
687 parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
688 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
689 T("1994-08-04 00:48:22");
690 tt_int_op(0,OP_EQ,
691 parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
692 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
693 T("1994-08-04 00:48:22");
694 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
695 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
696 T("1994-08-04 00:48:22");
697 tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
698 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
699 T("1994-08-04 00:48:22");
700 tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
701 tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
702 T("1994-08-04 00:48:22");
703 tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
704 tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
705 T("2012-01-01 00:00:00");
706 tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
707 tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
708 T("2012-12-31 00:00:00");
709 tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
710 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
711 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
712 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
713 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
714 tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
715 tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
716 tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
718 #undef T
719 done:
723 static void
724 test_util_config_line(void *arg)
726 char buf[1024];
727 char *k=NULL, *v=NULL;
728 const char *str;
730 /* Test parse_config_line_from_str */
731 (void)arg;
732 strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
733 "k2\n"
734 "k3 \n" "\n" " \n" "#comment\n"
735 "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
736 "kseven \"a quoted 'string\"\n"
737 "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
738 "k9 a line that\\\n spans two lines.\n\n"
739 "k10 more than\\\n one contin\\\nuation\n"
740 "k11 \\\ncontinuation at the start\n"
741 "k12 line with a\\\n#comment\n embedded\n"
742 "k13\\\ncontinuation at the very start\n"
743 "k14 a line that has a comment and # ends with a slash \\\n"
744 "k15 this should be the next new line\n"
745 "k16 a line that has a comment and # ends without a slash \n"
746 "k17 this should be the next new line\n"
747 , sizeof(buf));
748 str = buf;
750 str = parse_config_line_from_str(str, &k, &v);
751 tt_str_op(k,OP_EQ, "k");
752 tt_str_op(v,OP_EQ, "v");
753 tor_free(k); tor_free(v);
754 tt_assert(!strcmpstart(str, "key value with"));
756 str = parse_config_line_from_str(str, &k, &v);
757 tt_str_op(k,OP_EQ, "key");
758 tt_str_op(v,OP_EQ, "value with spaces");
759 tor_free(k); tor_free(v);
760 tt_assert(!strcmpstart(str, "keykey"));
762 str = parse_config_line_from_str(str, &k, &v);
763 tt_str_op(k,OP_EQ, "keykey");
764 tt_str_op(v,OP_EQ, "val");
765 tor_free(k); tor_free(v);
766 tt_assert(!strcmpstart(str, "k2\n"));
768 str = parse_config_line_from_str(str, &k, &v);
769 tt_str_op(k,OP_EQ, "k2");
770 tt_str_op(v,OP_EQ, "");
771 tor_free(k); tor_free(v);
772 tt_assert(!strcmpstart(str, "k3 \n"));
774 str = parse_config_line_from_str(str, &k, &v);
775 tt_str_op(k,OP_EQ, "k3");
776 tt_str_op(v,OP_EQ, "");
777 tor_free(k); tor_free(v);
778 tt_assert(!strcmpstart(str, "#comment"));
780 str = parse_config_line_from_str(str, &k, &v);
781 tt_str_op(k,OP_EQ, "k4");
782 tt_str_op(v,OP_EQ, "");
783 tor_free(k); tor_free(v);
784 tt_assert(!strcmpstart(str, "k5#abc"));
786 str = parse_config_line_from_str(str, &k, &v);
787 tt_str_op(k,OP_EQ, "k5");
788 tt_str_op(v,OP_EQ, "");
789 tor_free(k); tor_free(v);
790 tt_assert(!strcmpstart(str, "k6"));
792 str = parse_config_line_from_str(str, &k, &v);
793 tt_str_op(k,OP_EQ, "k6");
794 tt_str_op(v,OP_EQ, "val");
795 tor_free(k); tor_free(v);
796 tt_assert(!strcmpstart(str, "kseven"));
798 str = parse_config_line_from_str(str, &k, &v);
799 tt_str_op(k,OP_EQ, "kseven");
800 tt_str_op(v,OP_EQ, "a quoted \'string");
801 tor_free(k); tor_free(v);
802 tt_assert(!strcmpstart(str, "k8 "));
804 str = parse_config_line_from_str(str, &k, &v);
805 tt_str_op(k,OP_EQ, "k8");
806 tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
807 tor_free(k); tor_free(v);
809 str = parse_config_line_from_str(str, &k, &v);
810 tt_str_op(k,OP_EQ, "k9");
811 tt_str_op(v,OP_EQ, "a line that spans two lines.");
812 tor_free(k); tor_free(v);
814 str = parse_config_line_from_str(str, &k, &v);
815 tt_str_op(k,OP_EQ, "k10");
816 tt_str_op(v,OP_EQ, "more than one continuation");
817 tor_free(k); tor_free(v);
819 str = parse_config_line_from_str(str, &k, &v);
820 tt_str_op(k,OP_EQ, "k11");
821 tt_str_op(v,OP_EQ, "continuation at the start");
822 tor_free(k); tor_free(v);
824 str = parse_config_line_from_str(str, &k, &v);
825 tt_str_op(k,OP_EQ, "k12");
826 tt_str_op(v,OP_EQ, "line with a embedded");
827 tor_free(k); tor_free(v);
829 str = parse_config_line_from_str(str, &k, &v);
830 tt_str_op(k,OP_EQ, "k13");
831 tt_str_op(v,OP_EQ, "continuation at the very start");
832 tor_free(k); tor_free(v);
834 str = parse_config_line_from_str(str, &k, &v);
835 tt_str_op(k,OP_EQ, "k14");
836 tt_str_op(v,OP_EQ, "a line that has a comment and" );
837 tor_free(k); tor_free(v);
839 str = parse_config_line_from_str(str, &k, &v);
840 tt_str_op(k,OP_EQ, "k15");
841 tt_str_op(v,OP_EQ, "this should be the next new line");
842 tor_free(k); tor_free(v);
844 str = parse_config_line_from_str(str, &k, &v);
845 tt_str_op(k,OP_EQ, "k16");
846 tt_str_op(v,OP_EQ, "a line that has a comment and" );
847 tor_free(k); tor_free(v);
849 str = parse_config_line_from_str(str, &k, &v);
850 tt_str_op(k,OP_EQ, "k17");
851 tt_str_op(v,OP_EQ, "this should be the next new line");
852 tor_free(k); tor_free(v);
854 tt_str_op(str,OP_EQ, "");
856 done:
857 tor_free(k);
858 tor_free(v);
861 static void
862 test_util_config_line_quotes(void *arg)
864 char buf1[1024];
865 char buf2[128];
866 char buf3[128];
867 char buf4[128];
868 char *k=NULL, *v=NULL;
869 const char *str;
871 /* Test parse_config_line_from_str */
872 (void)arg;
873 strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
874 "kTrailingGarbage \"quoted value\"trailing garbage\n"
875 , sizeof(buf1));
876 strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
877 , sizeof(buf2));
878 strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
879 , sizeof(buf3));
880 strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
881 , sizeof(buf4));
882 str = buf1;
884 str = parse_config_line_from_str(str, &k, &v);
885 tt_str_op(k,OP_EQ, "kTrailingSpace");
886 tt_str_op(v,OP_EQ, "quoted value");
887 tor_free(k); tor_free(v);
889 str = parse_config_line_from_str(str, &k, &v);
890 tt_ptr_op(str,OP_EQ, NULL);
891 tor_free(k); tor_free(v);
893 str = buf2;
895 str = parse_config_line_from_str(str, &k, &v);
896 tt_ptr_op(str,OP_EQ, NULL);
897 tor_free(k); tor_free(v);
899 str = buf3;
901 str = parse_config_line_from_str(str, &k, &v);
902 tt_ptr_op(str,OP_EQ, NULL);
903 tor_free(k); tor_free(v);
905 str = buf4;
907 str = parse_config_line_from_str(str, &k, &v);
908 tt_ptr_op(str,OP_EQ, NULL);
909 tor_free(k); tor_free(v);
911 done:
912 tor_free(k);
913 tor_free(v);
916 static void
917 test_util_config_line_comment_character(void *arg)
919 char buf[1024];
920 char *k=NULL, *v=NULL;
921 const char *str;
923 /* Test parse_config_line_from_str */
924 (void)arg;
925 strlcpy(buf, "k1 \"# in quotes\"\n"
926 "k2 some value # some comment\n"
927 "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
928 , sizeof(buf));
929 str = buf;
931 str = parse_config_line_from_str(str, &k, &v);
932 tt_str_op(k,OP_EQ, "k1");
933 tt_str_op(v,OP_EQ, "# in quotes");
934 tor_free(k); tor_free(v);
936 str = parse_config_line_from_str(str, &k, &v);
937 tt_str_op(k,OP_EQ, "k2");
938 tt_str_op(v,OP_EQ, "some value");
939 tor_free(k); tor_free(v);
941 tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
943 #if 0
944 str = parse_config_line_from_str(str, &k, &v);
945 test_streq(k, "k3");
946 test_streq(v, "/home/user/myTorNetwork#2");
947 tor_free(k); tor_free(v);
949 test_streq(str, "");
950 #endif
952 done:
953 tor_free(k);
954 tor_free(v);
957 static void
958 test_util_config_line_escaped_content(void *arg)
960 char buf1[1024];
961 char buf2[128];
962 char buf3[128];
963 char buf4[128];
964 char buf5[128];
965 char buf6[128];
966 char *k=NULL, *v=NULL;
967 const char *str;
969 /* Test parse_config_line_from_str */
970 (void)arg;
971 strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
972 "HexadecimalUpper \"\\x2A\"\n"
973 "HexadecimalUpperX \"\\X2A\"\n"
974 "Octal \"\\52\"\n"
975 "Newline \"\\n\"\n"
976 "Tab \"\\t\"\n"
977 "CarriageReturn \"\\r\"\n"
978 "DoubleQuote \"\\\"\"\n"
979 "SimpleQuote \"\\'\"\n"
980 "Backslash \"\\\\\"\n"
981 "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
982 , sizeof(buf1));
984 strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
985 , sizeof(buf2));
987 strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
988 , sizeof(buf3));
990 strlcpy(buf4, "BrokenOctal \"\\8\"\n"
991 , sizeof(buf4));
993 strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
994 , sizeof(buf5));
996 strlcpy(buf6, "BrokenEscape \"\\"
997 , sizeof(buf6));
999 str = buf1;
1001 str = parse_config_line_from_str(str, &k, &v);
1002 tt_str_op(k,OP_EQ, "HexadecimalLower");
1003 tt_str_op(v,OP_EQ, "*");
1004 tor_free(k); tor_free(v);
1006 str = parse_config_line_from_str(str, &k, &v);
1007 tt_str_op(k,OP_EQ, "HexadecimalUpper");
1008 tt_str_op(v,OP_EQ, "*");
1009 tor_free(k); tor_free(v);
1011 str = parse_config_line_from_str(str, &k, &v);
1012 tt_str_op(k,OP_EQ, "HexadecimalUpperX");
1013 tt_str_op(v,OP_EQ, "*");
1014 tor_free(k); tor_free(v);
1016 str = parse_config_line_from_str(str, &k, &v);
1017 tt_str_op(k,OP_EQ, "Octal");
1018 tt_str_op(v,OP_EQ, "*");
1019 tor_free(k); tor_free(v);
1021 str = parse_config_line_from_str(str, &k, &v);
1022 tt_str_op(k,OP_EQ, "Newline");
1023 tt_str_op(v,OP_EQ, "\n");
1024 tor_free(k); tor_free(v);
1026 str = parse_config_line_from_str(str, &k, &v);
1027 tt_str_op(k,OP_EQ, "Tab");
1028 tt_str_op(v,OP_EQ, "\t");
1029 tor_free(k); tor_free(v);
1031 str = parse_config_line_from_str(str, &k, &v);
1032 tt_str_op(k,OP_EQ, "CarriageReturn");
1033 tt_str_op(v,OP_EQ, "\r");
1034 tor_free(k); tor_free(v);
1036 str = parse_config_line_from_str(str, &k, &v);
1037 tt_str_op(k,OP_EQ, "DoubleQuote");
1038 tt_str_op(v,OP_EQ, "\"");
1039 tor_free(k); tor_free(v);
1041 str = parse_config_line_from_str(str, &k, &v);
1042 tt_str_op(k,OP_EQ, "SimpleQuote");
1043 tt_str_op(v,OP_EQ, "'");
1044 tor_free(k); tor_free(v);
1046 str = parse_config_line_from_str(str, &k, &v);
1047 tt_str_op(k,OP_EQ, "Backslash");
1048 tt_str_op(v,OP_EQ, "\\");
1049 tor_free(k); tor_free(v);
1051 str = parse_config_line_from_str(str, &k, &v);
1052 tt_str_op(k,OP_EQ, "Mix");
1053 tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
1054 tor_free(k); tor_free(v);
1055 tt_str_op(str,OP_EQ, "");
1057 str = buf2;
1059 str = parse_config_line_from_str(str, &k, &v);
1060 tt_ptr_op(str,OP_EQ, NULL);
1061 tor_free(k); tor_free(v);
1063 str = buf3;
1065 str = parse_config_line_from_str(str, &k, &v);
1066 tt_ptr_op(str,OP_EQ, NULL);
1067 tor_free(k); tor_free(v);
1069 str = buf4;
1071 str = parse_config_line_from_str(str, &k, &v);
1072 tt_ptr_op(str,OP_EQ, NULL);
1073 tor_free(k); tor_free(v);
1075 #if 0
1076 str = buf5;
1078 str = parse_config_line_from_str(str, &k, &v);
1079 tt_ptr_op(str, OP_EQ, NULL);
1080 tor_free(k); tor_free(v);
1081 #endif
1083 str = buf6;
1085 str = parse_config_line_from_str(str, &k, &v);
1086 tt_ptr_op(str,OP_EQ, NULL);
1087 tor_free(k); tor_free(v);
1089 done:
1090 tor_free(k);
1091 tor_free(v);
1094 #ifndef _WIN32
1095 static void
1096 test_util_expand_filename(void *arg)
1098 char *str;
1100 (void)arg;
1101 setenv("HOME", "/home/itv", 1); /* For "internal test value" */
1103 str = expand_filename("");
1104 tt_str_op("",OP_EQ, str);
1105 tor_free(str);
1107 str = expand_filename("/normal/path");
1108 tt_str_op("/normal/path",OP_EQ, str);
1109 tor_free(str);
1111 str = expand_filename("/normal/trailing/path/");
1112 tt_str_op("/normal/trailing/path/",OP_EQ, str);
1113 tor_free(str);
1115 str = expand_filename("~");
1116 tt_str_op("/home/itv/",OP_EQ, str);
1117 tor_free(str);
1119 str = expand_filename("$HOME/nodice");
1120 tt_str_op("$HOME/nodice",OP_EQ, str);
1121 tor_free(str);
1123 str = expand_filename("~/");
1124 tt_str_op("/home/itv/",OP_EQ, str);
1125 tor_free(str);
1127 str = expand_filename("~/foobarqux");
1128 tt_str_op("/home/itv/foobarqux",OP_EQ, str);
1129 tor_free(str);
1131 str = expand_filename("~/../../etc/passwd");
1132 tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
1133 tor_free(str);
1135 str = expand_filename("~/trailing/");
1136 tt_str_op("/home/itv/trailing/",OP_EQ, str);
1137 tor_free(str);
1138 /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
1139 have to somehow inject/fake the get_user_homedir call) */
1141 /* $HOME ending in a trailing slash */
1142 setenv("HOME", "/home/itv/", 1);
1144 str = expand_filename("~");
1145 tt_str_op("/home/itv/",OP_EQ, str);
1146 tor_free(str);
1148 str = expand_filename("~/");
1149 tt_str_op("/home/itv/",OP_EQ, str);
1150 tor_free(str);
1152 str = expand_filename("~/foo");
1153 tt_str_op("/home/itv/foo",OP_EQ, str);
1154 tor_free(str);
1156 /* Try with empty $HOME */
1158 setenv("HOME", "", 1);
1160 str = expand_filename("~");
1161 tt_str_op("/",OP_EQ, str);
1162 tor_free(str);
1164 str = expand_filename("~/");
1165 tt_str_op("/",OP_EQ, str);
1166 tor_free(str);
1168 str = expand_filename("~/foobar");
1169 tt_str_op("/foobar",OP_EQ, str);
1170 tor_free(str);
1172 /* Try with $HOME unset */
1174 unsetenv("HOME");
1176 str = expand_filename("~");
1177 tt_str_op("/",OP_EQ, str);
1178 tor_free(str);
1180 str = expand_filename("~/");
1181 tt_str_op("/",OP_EQ, str);
1182 tor_free(str);
1184 str = expand_filename("~/foobar");
1185 tt_str_op("/foobar",OP_EQ, str);
1186 tor_free(str);
1188 done:
1189 tor_free(str);
1191 #endif
1193 /** Test tor_escape_str_for_pt_args(). */
1194 static void
1195 test_util_escape_string_socks(void *arg)
1197 char *escaped_string = NULL;
1199 /** Simple backslash escape. */
1200 (void)arg;
1201 escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
1202 tt_assert(escaped_string);
1203 tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
1204 tor_free(escaped_string);
1206 /** Simple semicolon escape. */
1207 escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
1208 tt_assert(escaped_string);
1209 tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
1210 tor_free(escaped_string);
1212 /** Empty string. */
1213 escaped_string = tor_escape_str_for_pt_args("", ";\\");
1214 tt_assert(escaped_string);
1215 tt_str_op(escaped_string,OP_EQ, "");
1216 tor_free(escaped_string);
1218 /** Escape all characters. */
1219 escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
1220 tt_assert(escaped_string);
1221 tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
1222 tor_free(escaped_string);
1224 escaped_string = tor_escape_str_for_pt_args(";", ";\\");
1225 tt_assert(escaped_string);
1226 tt_str_op(escaped_string,OP_EQ, "\\;");
1227 tor_free(escaped_string);
1229 done:
1230 tor_free(escaped_string);
1233 static void
1234 test_util_string_is_key_value(void *ptr)
1236 (void)ptr;
1237 tt_assert(string_is_key_value(LOG_WARN, "key=value"));
1238 tt_assert(string_is_key_value(LOG_WARN, "k=v"));
1239 tt_assert(string_is_key_value(LOG_WARN, "key="));
1240 tt_assert(string_is_key_value(LOG_WARN, "x="));
1241 tt_assert(string_is_key_value(LOG_WARN, "xx="));
1242 tt_assert(!string_is_key_value(LOG_WARN, "=value"));
1243 tt_assert(!string_is_key_value(LOG_WARN, "=x"));
1244 tt_assert(!string_is_key_value(LOG_WARN, "="));
1246 /* ??? */
1247 /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
1248 done:
1252 /** Test basic string functionality. */
1253 static void
1254 test_util_strmisc(void *arg)
1256 char buf[1024];
1257 int i;
1258 char *cp, *cp_tmp = NULL;
1260 /* Test strl operations */
1261 (void)arg;
1262 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
1263 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
1264 tt_str_op(buf,OP_EQ, "Hello");
1265 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
1266 tt_str_op(buf,OP_EQ, "Hello");
1267 tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
1268 tt_str_op(buf,OP_EQ, "Hell");
1269 strlcpy(buf, "Hello", sizeof(buf));
1270 tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
1272 /* Test strstrip() */
1273 strlcpy(buf, "Testing 1 2 3", sizeof(buf));
1274 tor_strstrip(buf, ",!");
1275 tt_str_op(buf,OP_EQ, "Testing 1 2 3");
1276 strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
1277 tor_strstrip(buf, "!? ");
1278 tt_str_op(buf,OP_EQ, "Testing123");
1279 strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
1280 tor_strstrip(buf, "!? ");
1281 tt_str_op(buf,OP_EQ, "Testing123");
1283 /* Test parse_long */
1284 /* Empty/zero input */
1285 tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
1286 tt_int_op(0,OP_EQ, i);
1287 tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
1288 tt_int_op(1,OP_EQ, i);
1289 /* Normal cases */
1290 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
1291 tt_int_op(1,OP_EQ, i);
1292 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
1293 tt_int_op(1,OP_EQ, i);
1294 tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
1295 tt_int_op(1,OP_EQ, i);
1296 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
1297 tt_int_op(1,OP_EQ, i);
1298 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
1299 tt_int_op(1,OP_EQ, i);
1300 tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
1301 tt_int_op(1,OP_EQ, i);
1302 /* Extra garbage */
1303 tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
1304 tt_int_op(0,OP_EQ, i);
1305 tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
1306 tt_int_op(0,OP_EQ, i);
1307 tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
1308 tt_int_op(1,OP_EQ, i);
1309 tt_str_op(cp,OP_EQ, "m");
1310 tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
1311 tt_int_op(1,OP_EQ, i);
1312 tt_str_op(cp,OP_EQ, " plus garbage");
1313 /* Out of bounds */
1314 tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
1315 tt_int_op(0,OP_EQ, i);
1316 tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,0,100,&i,NULL));
1317 tt_int_op(0,OP_EQ, i);
1318 /* Base different than 10 */
1319 tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL));
1320 tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
1321 tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
1322 tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
1323 tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
1324 tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
1325 tt_int_op(i,OP_EQ, 0);
1327 /* Test parse_ulong */
1328 tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
1329 tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
1330 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
1331 tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
1332 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
1333 tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
1334 tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
1335 tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
1336 tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,-100,100,NULL,NULL));
1337 tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
1338 tt_int_op(0,OP_EQ, i);
1340 /* Test parse_uint64 */
1341 tt_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
1342 tt_int_op(1,OP_EQ, i);
1343 tt_str_op(cp,OP_EQ, " x");
1344 tt_assert(U64_LITERAL(12345678901) ==
1345 tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
1346 tt_int_op(1,OP_EQ, i);
1347 tt_str_op(cp,OP_EQ, "");
1348 tt_assert(U64_LITERAL(0) ==
1349 tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
1350 tt_int_op(0,OP_EQ, i);
1351 tt_assert(U64_LITERAL(0) ==
1352 tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
1353 tt_int_op(0,OP_EQ, i);
1356 /* Test parse_double */
1357 double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL);
1358 tt_int_op(1,OP_EQ, i);
1359 tt_assert(DBL_TO_U64(d) == 10);
1360 d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL);
1361 tt_int_op(1,OP_EQ, i);
1362 tt_assert(DBL_TO_U64(d) == 0);
1363 d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL);
1364 tt_int_op(0,OP_EQ, i);
1365 d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL);
1366 tt_int_op(0,OP_EQ, i);
1367 d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp);
1368 tt_int_op(1,OP_EQ, i);
1369 d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL);
1370 tt_int_op(1,OP_EQ, i);
1371 tt_assert(DBL_TO_U64(d) == 0);
1372 d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
1373 tt_int_op(1,OP_EQ, i);
1374 tt_int_op(-10.0,OP_EQ, d);
1378 /* Test tor_parse_* where we overflow/underflow the underlying type. */
1379 /* This string should overflow 64-bit ints. */
1380 #define TOOBIG "100000000000000000000000000"
1381 tt_int_op(0L, OP_EQ,
1382 tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
1383 tt_int_op(i,OP_EQ, 0);
1384 tt_int_op(0L,OP_EQ,
1385 tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
1386 tt_int_op(i,OP_EQ, 0);
1387 tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
1388 tt_int_op(i,OP_EQ, 0);
1389 tt_u64_op(U64_LITERAL(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
1390 0, UINT64_MAX, &i, NULL));
1391 tt_int_op(i,OP_EQ, 0);
1394 /* Test snprintf */
1395 /* Returning -1 when there's not enough room in the output buffer */
1396 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
1397 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
1398 tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
1399 tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
1400 /* Always NUL-terminate the output */
1401 tor_snprintf(buf, 5, "abcdef");
1402 tt_int_op(0,OP_EQ, buf[4]);
1403 tor_snprintf(buf, 10, "abcdef");
1404 tt_int_op(0,OP_EQ, buf[6]);
1405 /* uint64 */
1406 tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
1407 U64_PRINTF_ARG(U64_LITERAL(12345678901)));
1408 tt_str_op("x!12345678901!x",OP_EQ, buf);
1410 /* Test str{,case}cmpstart */
1411 tt_assert(strcmpstart("abcdef", "abcdef")==0);
1412 tt_assert(strcmpstart("abcdef", "abc")==0);
1413 tt_assert(strcmpstart("abcdef", "abd")<0);
1414 tt_assert(strcmpstart("abcdef", "abb")>0);
1415 tt_assert(strcmpstart("ab", "abb")<0);
1416 tt_assert(strcmpstart("ab", "")==0);
1417 tt_assert(strcmpstart("ab", "ab ")<0);
1418 tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
1419 tt_assert(strcasecmpstart("abcDeF", "abc")==0);
1420 tt_assert(strcasecmpstart("abcdef", "Abd")<0);
1421 tt_assert(strcasecmpstart("Abcdef", "abb")>0);
1422 tt_assert(strcasecmpstart("ab", "Abb")<0);
1423 tt_assert(strcasecmpstart("ab", "")==0);
1424 tt_assert(strcasecmpstart("ab", "ab ")<0);
1426 /* Test str{,case}cmpend */
1427 tt_assert(strcmpend("abcdef", "abcdef")==0);
1428 tt_assert(strcmpend("abcdef", "def")==0);
1429 tt_assert(strcmpend("abcdef", "deg")<0);
1430 tt_assert(strcmpend("abcdef", "dee")>0);
1431 tt_assert(strcmpend("ab", "aab")>0);
1432 tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
1433 tt_assert(strcasecmpend("abcdef", "dEF")==0);
1434 tt_assert(strcasecmpend("abcdef", "Deg")<0);
1435 tt_assert(strcasecmpend("abcDef", "dee")>0);
1436 tt_assert(strcasecmpend("AB", "abb")<0);
1438 /* Test digest_is_zero */
1439 memset(buf,0,20);
1440 buf[20] = 'x';
1441 tt_assert(tor_digest_is_zero(buf));
1442 buf[19] = 'x';
1443 tt_assert(!tor_digest_is_zero(buf));
1445 /* Test mem_is_zero */
1446 memset(buf,0,128);
1447 buf[128] = 'x';
1448 tt_assert(tor_mem_is_zero(buf, 10));
1449 tt_assert(tor_mem_is_zero(buf, 20));
1450 tt_assert(tor_mem_is_zero(buf, 128));
1451 tt_assert(!tor_mem_is_zero(buf, 129));
1452 buf[60] = (char)255;
1453 tt_assert(!tor_mem_is_zero(buf, 128));
1454 buf[0] = (char)1;
1455 tt_assert(!tor_mem_is_zero(buf, 10));
1457 /* Test 'escaped' */
1458 tt_assert(NULL == escaped(NULL));
1459 tt_str_op("\"\"",OP_EQ, escaped(""));
1460 tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
1461 tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
1462 tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
1463 escaped("unnecessary \'backslashes\'"));
1464 /* Non-printable characters appear as octal */
1465 tt_str_op("\"z\\001abc\\277d\"",OP_EQ, escaped("z\001abc\277d"));
1466 tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
1468 /* Test strndup and memdup */
1470 const char *s = "abcdefghijklmnopqrstuvwxyz";
1471 cp_tmp = tor_strndup(s, 30);
1472 tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
1473 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
1474 tor_free(cp_tmp);
1476 cp_tmp = tor_strndup(s, 5);
1477 tt_str_op(cp_tmp,OP_EQ, "abcde");
1478 tor_free(cp_tmp);
1480 s = "a\0b\0c\0d\0e\0";
1481 cp_tmp = tor_memdup(s,10);
1482 tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
1483 tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
1484 tor_free(cp_tmp);
1487 /* Test str-foo functions */
1488 cp_tmp = tor_strdup("abcdef");
1489 tt_assert(tor_strisnonupper(cp_tmp));
1490 cp_tmp[3] = 'D';
1491 tt_assert(!tor_strisnonupper(cp_tmp));
1492 tor_strupper(cp_tmp);
1493 tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
1494 tor_strlower(cp_tmp);
1495 tt_str_op(cp_tmp,OP_EQ, "abcdef");
1496 tt_assert(tor_strisnonupper(cp_tmp));
1497 tt_assert(tor_strisprint(cp_tmp));
1498 cp_tmp[3] = 3;
1499 tt_assert(!tor_strisprint(cp_tmp));
1500 tor_free(cp_tmp);
1502 /* Test memmem and memstr */
1504 const char *haystack = "abcde";
1505 tt_assert(!tor_memmem(haystack, 5, "ef", 2));
1506 tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
1507 tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
1508 tt_assert(!tor_memmem(haystack, 4, "cde", 3));
1509 haystack = "ababcad";
1510 tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
1511 tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
1512 tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
1513 tt_assert(!tor_memmem(haystack, 7, "dadad", 5));
1514 tt_assert(!tor_memmem(haystack, 7, "abcdefghij", 10));
1515 /* memstr */
1516 tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
1517 tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
1518 tt_assert(!tor_memstr(haystack, 6, "cad"));
1519 tt_assert(!tor_memstr(haystack, 7, "cadd"));
1520 tt_assert(!tor_memstr(haystack, 7, "fe"));
1521 tt_assert(!tor_memstr(haystack, 7, "ababcade"));
1524 /* Test hex_str */
1526 char binary_data[68];
1527 size_t i;
1528 for (i = 0; i < sizeof(binary_data); ++i)
1529 binary_data[i] = i;
1530 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
1531 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
1532 tt_str_op(hex_str(binary_data, 17),OP_EQ,
1533 "000102030405060708090A0B0C0D0E0F10");
1534 tt_str_op(hex_str(binary_data, 32),OP_EQ,
1535 "000102030405060708090A0B0C0D0E0F"
1536 "101112131415161718191A1B1C1D1E1F");
1537 tt_str_op(hex_str(binary_data, 34),OP_EQ,
1538 "000102030405060708090A0B0C0D0E0F"
1539 "101112131415161718191A1B1C1D1E1F");
1540 /* Repeat these tests for shorter strings after longer strings
1541 have been tried, to make sure we're correctly terminating strings */
1542 tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
1543 tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
1546 /* Test strcmp_opt */
1547 tt_int_op(strcmp_opt("", "foo"), OP_LT, 0);
1548 tt_int_op(strcmp_opt("", ""), OP_EQ, 0);
1549 tt_int_op(strcmp_opt("foo", ""), OP_GT, 0);
1551 tt_int_op(strcmp_opt(NULL, ""), OP_LT, 0);
1552 tt_int_op(strcmp_opt(NULL, NULL), OP_EQ, 0);
1553 tt_int_op(strcmp_opt("", NULL), OP_GT, 0);
1555 tt_int_op(strcmp_opt(NULL, "foo"), OP_LT, 0);
1556 tt_int_op(strcmp_opt("foo", NULL), OP_GT, 0);
1558 /* Test strcmp_len */
1559 tt_int_op(strcmp_len("foo", "bar", 3), OP_GT, 0);
1560 tt_int_op(strcmp_len("foo", "bar", 2), OP_LT, 0);
1561 tt_int_op(strcmp_len("foo2", "foo1", 4), OP_GT, 0);
1562 tt_int_op(strcmp_len("foo2", "foo1", 3), OP_LT, 0); /* Really stop at len */
1563 tt_int_op(strcmp_len("foo2", "foo", 3), OP_EQ, 0); /* Really stop at len */
1564 tt_int_op(strcmp_len("blah", "", 4), OP_GT, 0);
1565 tt_int_op(strcmp_len("blah", "", 0), OP_EQ, 0);
1567 done:
1568 tor_free(cp_tmp);
1571 static void
1572 test_util_pow2(void *arg)
1574 /* Test tor_log2(). */
1575 (void)arg;
1576 tt_int_op(tor_log2(64),OP_EQ, 6);
1577 tt_int_op(tor_log2(65),OP_EQ, 6);
1578 tt_int_op(tor_log2(63),OP_EQ, 5);
1579 /* incorrect mathematically, but as specified: */
1580 tt_int_op(tor_log2(0),OP_EQ, 0);
1581 tt_int_op(tor_log2(1),OP_EQ, 0);
1582 tt_int_op(tor_log2(2),OP_EQ, 1);
1583 tt_int_op(tor_log2(3),OP_EQ, 1);
1584 tt_int_op(tor_log2(4),OP_EQ, 2);
1585 tt_int_op(tor_log2(5),OP_EQ, 2);
1586 tt_int_op(tor_log2(U64_LITERAL(40000000000000000)),OP_EQ, 55);
1587 tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
1589 /* Test round_to_power_of_2 */
1590 tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
1591 tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
1592 tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
1593 tt_u64_op(round_to_power_of_2(U64_LITERAL(40000000000000000)), OP_EQ,
1594 U64_LITERAL(1)<<55);
1595 tt_u64_op(round_to_power_of_2(U64_LITERAL(0xffffffffffffffff)), OP_EQ,
1596 U64_LITERAL(1)<<63);
1597 tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
1598 tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
1599 tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
1600 tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
1601 tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
1602 tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
1603 tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
1604 tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
1606 done:
1610 /** Run unit tests for compression functions */
1611 static void
1612 test_util_gzip(void *arg)
1614 char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
1615 const char *ccp2;
1616 size_t len1, len2;
1617 tor_zlib_state_t *state = NULL;
1619 (void)arg;
1620 buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
1621 tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
1622 if (is_gzip_supported()) {
1623 tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
1624 GZIP_METHOD));
1625 tt_assert(buf2);
1626 tt_assert(len1 < strlen(buf1));
1627 tt_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
1629 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
1630 GZIP_METHOD, 1, LOG_INFO));
1631 tt_assert(buf3);
1632 tt_int_op(strlen(buf1) + 1,OP_EQ, len2);
1633 tt_str_op(buf1,OP_EQ, buf3);
1635 tor_free(buf2);
1636 tor_free(buf3);
1639 tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
1640 ZLIB_METHOD));
1641 tt_assert(buf2);
1642 tt_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
1644 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
1645 ZLIB_METHOD, 1, LOG_INFO));
1646 tt_assert(buf3);
1647 tt_int_op(strlen(buf1) + 1,OP_EQ, len2);
1648 tt_str_op(buf1,OP_EQ, buf3);
1650 /* Check whether we can uncompress concatenated, compressed strings. */
1651 tor_free(buf3);
1652 buf2 = tor_reallocarray(buf2, len1, 2);
1653 memcpy(buf2+len1, buf2, len1);
1654 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
1655 ZLIB_METHOD, 1, LOG_INFO));
1656 tt_int_op((strlen(buf1)+1)*2,OP_EQ, len2);
1657 tt_mem_op(buf3,OP_EQ,
1658 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
1659 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
1660 (strlen(buf1)+1)*2);
1662 tor_free(buf1);
1663 tor_free(buf2);
1664 tor_free(buf3);
1666 /* Check whether we can uncompress partial strings. */
1667 buf1 =
1668 tor_strdup("String with low redundancy that won't be compressed much.");
1669 tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
1670 ZLIB_METHOD));
1671 tt_assert(len1>16);
1672 /* when we allow an incomplete string, we should succeed.*/
1673 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
1674 ZLIB_METHOD, 0, LOG_INFO));
1675 tt_assert(len2 > 5);
1676 buf3[len2]='\0';
1677 tt_assert(!strcmpstart(buf1, buf3));
1679 /* when we demand a complete string, this must fail. */
1680 tor_free(buf3);
1681 tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
1682 ZLIB_METHOD, 1, LOG_INFO));
1683 tt_assert(!buf3);
1685 /* Now, try streaming compression. */
1686 tor_free(buf1);
1687 tor_free(buf2);
1688 tor_free(buf3);
1689 state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
1690 tt_assert(state);
1691 cp1 = buf1 = tor_malloc(1024);
1692 len1 = 1024;
1693 ccp2 = "ABCDEFGHIJABCDEFGHIJ";
1694 len2 = 21;
1695 tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
1696 == TOR_ZLIB_OK);
1697 tt_int_op(0,OP_EQ, len2); /* Make sure we compressed it all. */
1698 tt_assert(cp1 > buf1);
1700 len2 = 0;
1701 cp2 = cp1;
1702 tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
1703 == TOR_ZLIB_DONE);
1704 tt_int_op(0,OP_EQ, len2);
1705 tt_assert(cp1 > cp2); /* Make sure we really added something. */
1707 tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
1708 ZLIB_METHOD, 1, LOG_WARN));
1709 /* Make sure it compressed right. */
1710 tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
1711 tt_int_op(21,OP_EQ, len2);
1713 done:
1714 if (state)
1715 tor_zlib_free(state);
1716 tor_free(buf2);
1717 tor_free(buf3);
1718 tor_free(buf1);
1721 /** Run unit tests for mmap() wrapper functionality. */
1722 static void
1723 test_util_mmap(void *arg)
1725 char *fname1 = tor_strdup(get_fname("mapped_1"));
1726 char *fname2 = tor_strdup(get_fname("mapped_2"));
1727 char *fname3 = tor_strdup(get_fname("mapped_3"));
1728 const size_t buflen = 17000;
1729 char *buf = tor_malloc(17000);
1730 tor_mmap_t *mapping = NULL;
1732 (void)arg;
1733 crypto_rand(buf, buflen);
1735 mapping = tor_mmap_file(fname1);
1736 tt_assert(! mapping);
1738 write_str_to_file(fname1, "Short file.", 1);
1740 mapping = tor_mmap_file(fname1);
1741 tt_assert(mapping);
1742 tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
1743 tt_str_op(mapping->data,OP_EQ, "Short file.");
1744 #ifdef _WIN32
1745 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
1746 mapping = NULL;
1747 tt_assert(unlink(fname1) == 0);
1748 #else
1749 /* make sure we can unlink. */
1750 tt_assert(unlink(fname1) == 0);
1751 tt_str_op(mapping->data,OP_EQ, "Short file.");
1752 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
1753 mapping = NULL;
1754 #endif
1756 /* Now a zero-length file. */
1757 write_str_to_file(fname1, "", 1);
1758 mapping = tor_mmap_file(fname1);
1759 tt_ptr_op(mapping,OP_EQ, NULL);
1760 tt_int_op(ERANGE,OP_EQ, errno);
1761 unlink(fname1);
1763 /* Make sure that we fail to map a no-longer-existent file. */
1764 mapping = tor_mmap_file(fname1);
1765 tt_assert(! mapping);
1767 /* Now try a big file that stretches across a few pages and isn't aligned */
1768 write_bytes_to_file(fname2, buf, buflen, 1);
1769 mapping = tor_mmap_file(fname2);
1770 tt_assert(mapping);
1771 tt_int_op(mapping->size,OP_EQ, buflen);
1772 tt_mem_op(mapping->data,OP_EQ, buf, buflen);
1773 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
1774 mapping = NULL;
1776 /* Now try a big aligned file. */
1777 write_bytes_to_file(fname3, buf, 16384, 1);
1778 mapping = tor_mmap_file(fname3);
1779 tt_assert(mapping);
1780 tt_int_op(mapping->size,OP_EQ, 16384);
1781 tt_mem_op(mapping->data,OP_EQ, buf, 16384);
1782 tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
1783 mapping = NULL;
1785 done:
1786 unlink(fname1);
1787 unlink(fname2);
1788 unlink(fname3);
1790 tor_free(fname1);
1791 tor_free(fname2);
1792 tor_free(fname3);
1793 tor_free(buf);
1795 tor_munmap_file(mapping);
1798 /** Run unit tests for escaping/unescaping data for use by controllers. */
1799 static void
1800 test_util_control_formats(void *arg)
1802 char *out = NULL;
1803 const char *inp =
1804 "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
1805 size_t sz;
1807 (void)arg;
1808 sz = read_escaped_data(inp, strlen(inp), &out);
1809 tt_str_op(out,OP_EQ,
1810 ".This is a test\nof the emergency \n.system.\n\rZ.\n");
1811 tt_int_op(sz,OP_EQ, strlen(out));
1813 done:
1814 tor_free(out);
1817 #define test_feq(value1,value2) do { \
1818 double v1 = (value1), v2=(value2); \
1819 double tf_diff = v1-v2; \
1820 double tf_tolerance = ((v1+v2)/2.0)/1e8; \
1821 if (tf_diff<0) tf_diff=-tf_diff; \
1822 if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
1823 if (tf_diff<tf_tolerance) { \
1824 TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
1825 } else { \
1826 TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
1828 } while (0)
1830 static void
1831 test_util_sscanf(void *arg)
1833 unsigned u1, u2, u3;
1834 unsigned long ulng;
1835 char s1[20], s2[10], s3[10], ch;
1836 int r;
1837 long lng1,lng2;
1838 int int1, int2;
1839 double d1,d2,d3,d4;
1841 /* Simple tests (malformed patterns, literal matching, ...) */
1842 (void)arg;
1843 tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
1844 tt_int_op(-1,OP_EQ,
1845 tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
1846 tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
1847 tt_int_op(-1,OP_EQ, tor_sscanf("prettylongstring", "%999999s", s1));
1848 #if 0
1849 /* GCC thinks these two are illegal. */
1850 test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
1851 test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
1852 #endif
1853 /* No '%'-strings: always "success" */
1854 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
1855 tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
1856 /* Excess data */
1857 tt_int_op(0,OP_EQ,
1858 tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
1859 tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
1860 tt_int_op(0,OP_EQ,
1861 tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
1862 tt_int_op(1,OP_EQ,
1863 tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
1865 /* Numbers (ie. %u) */
1866 tt_int_op(0,OP_EQ,
1867 tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
1868 tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
1869 tt_int_op(12345u,OP_EQ, u1);
1870 tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
1871 tt_int_op(12346u,OP_EQ, u1);
1872 tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
1873 tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
1874 tt_int_op(12348u,OP_EQ, u1);
1875 tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
1876 tt_int_op(0u,OP_EQ, u1);
1877 tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
1878 tt_int_op(0u,OP_EQ, u2);
1879 tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
1880 tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
1881 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
1883 /* Numbers with size (eg. %2u) */
1884 tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
1885 tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
1886 tt_int_op(12u,OP_EQ, u1);
1887 tt_int_op(3456u,OP_EQ, u2);
1888 tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
1889 tt_int_op(123456u,OP_EQ, u1);
1890 tt_int_op(1,OP_EQ, tor_sscanf("123457 ", "%8u", &u1));
1891 tt_int_op(123457u,OP_EQ, u1);
1892 tt_int_op(0,OP_EQ, tor_sscanf(" 123456", "%8u", &u1));
1893 tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
1894 tt_int_op(12u,OP_EQ, u1);
1895 tt_int_op(3u,OP_EQ, u2);
1896 tt_int_op(456u,OP_EQ, u3);
1897 tt_int_op(3,OP_EQ,
1898 tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
1899 tt_int_op(67u,OP_EQ, u1);
1900 tt_int_op(8u,OP_EQ, u2);
1901 tt_int_op(99u,OP_EQ, u3);
1902 /* %u does not match space.*/
1903 tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
1904 tt_int_op(12u,OP_EQ, u1);
1905 tt_int_op(3u,OP_EQ, u2);
1906 /* %u does not match negative numbers. */
1907 tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
1908 tt_int_op(67u,OP_EQ, u1);
1909 tt_int_op(8u,OP_EQ, u2);
1910 /* Arbitrary amounts of 0-padding are okay */
1911 tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
1912 &u1, &u2, &u3));
1913 tt_int_op(12u,OP_EQ, u1);
1914 tt_int_op(3u,OP_EQ, u2);
1915 tt_int_op(99u,OP_EQ, u3);
1917 /* Hex (ie. %x) */
1918 tt_int_op(3,OP_EQ,
1919 tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
1920 tt_int_op(0x1234,OP_EQ, u1);
1921 tt_int_op(0x2ABCDEF,OP_EQ, u2);
1922 tt_int_op(0xFF,OP_EQ, u3);
1923 /* Width works on %x */
1924 tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
1925 tt_int_op(0xf00d,OP_EQ, u1);
1926 tt_int_op(0xcafe,OP_EQ, u2);
1927 tt_int_op(444,OP_EQ, u3);
1929 /* Literal '%' (ie. '%%') */
1930 tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
1931 tt_int_op(99,OP_EQ, u1);
1932 tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
1933 tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
1934 tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
1935 tt_int_op(99,OP_EQ, u1);
1936 tt_str_op(s1,OP_EQ, "fresh");
1937 tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
1938 tt_str_op("boo",OP_EQ, s1);
1940 /* Strings (ie. %s) */
1941 tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
1942 tt_str_op(s1,OP_EQ, "hel");
1943 tt_str_op(s2,OP_EQ, "lo");
1944 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
1945 tt_str_op(s3,OP_EQ, "WD");
1946 tt_int_op(40,OP_EQ, u1);
1947 tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
1948 tt_str_op(s3,OP_EQ, "WD4");
1949 tt_int_op(0,OP_EQ, u1);
1950 tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
1951 tt_int_op(76,OP_EQ, u1);
1952 tt_str_op(s1,OP_EQ, "trombones");
1953 tt_int_op(1,OP_EQ, tor_sscanf("prettylongstring", "%999s", s1));
1954 tt_str_op(s1,OP_EQ, "prettylongstring");
1955 /* %s doesn't eat spaces */
1956 tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
1957 tt_str_op(s1,OP_EQ, "hello");
1958 tt_str_op(s2,OP_EQ, "world");
1959 tt_int_op(2,OP_EQ, tor_sscanf("bye world?", "%9s %9s", s1, s2));
1960 tt_str_op(s1,OP_EQ, "bye");
1961 tt_str_op(s2,OP_EQ, "");
1962 tt_int_op(3,OP_EQ,
1963 tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
1964 tt_str_op(s1,OP_EQ, "hi");
1965 tt_str_op(s2,OP_EQ, "");
1966 tt_str_op(s3,OP_EQ, "");
1968 tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
1969 tt_int_op(4,OP_EQ,
1970 tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
1971 tt_int_op(' ',OP_EQ, ch);
1973 r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
1974 tt_int_op(r,OP_EQ, 3);
1975 tt_int_op(int1,OP_EQ, 12345);
1976 tt_int_op(lng1,OP_EQ, -67890);
1977 tt_int_op(int2,OP_EQ, -1);
1979 #if SIZEOF_INT == 4
1980 /* %u */
1981 /* UINT32_MAX should work */
1982 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
1983 tt_int_op(4294967295U,OP_EQ, u1);
1985 /* But UINT32_MAX + 1 shouldn't work */
1986 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
1987 /* but parsing only 9... */
1988 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
1989 tt_int_op(429496729U,OP_EQ, u1);
1991 /* %x */
1992 /* UINT32_MAX should work */
1993 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
1994 tt_int_op(0xFFFFFFFF,OP_EQ, u1);
1996 /* But UINT32_MAX + 1 shouldn't work */
1997 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
1999 /* %d */
2000 /* INT32_MIN and INT32_MAX should work */
2001 r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
2002 tt_int_op(r,OP_EQ, 2);
2003 tt_int_op(int1,OP_EQ, -2147483647 - 1);
2004 tt_int_op(int2,OP_EQ, 2147483647);
2006 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
2007 r = tor_sscanf("-2147483649.", "%d.", &int1);
2008 tt_int_op(r,OP_EQ, 0);
2010 r = tor_sscanf("2147483648.", "%d.", &int1);
2011 tt_int_op(r,OP_EQ, 0);
2013 /* and the first failure stops further processing */
2014 r = tor_sscanf("-2147483648. 2147483648.",
2015 "%d. %d.", &int1, &int2);
2016 tt_int_op(r,OP_EQ, 1);
2018 r = tor_sscanf("-2147483649. 2147483647.",
2019 "%d. %d.", &int1, &int2);
2020 tt_int_op(r,OP_EQ, 0);
2022 r = tor_sscanf("2147483648. -2147483649.",
2023 "%d. %d.", &int1, &int2);
2024 tt_int_op(r,OP_EQ, 0);
2025 #elif SIZEOF_INT == 8
2026 /* %u */
2027 /* UINT64_MAX should work */
2028 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
2029 tt_int_op(18446744073709551615U,OP_EQ, u1);
2031 /* But UINT64_MAX + 1 shouldn't work */
2032 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
2033 /* but parsing only 19... */
2034 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
2035 tt_int_op(1844674407370955161U,OP_EQ, u1);
2037 /* %x */
2038 /* UINT64_MAX should work */
2039 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
2040 tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
2042 /* But UINT64_MAX + 1 shouldn't work */
2043 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
2045 /* %d */
2046 /* INT64_MIN and INT64_MAX should work */
2047 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
2048 "%d. %d.", &int1, &int2);
2049 tt_int_op(r,OP_EQ, 2);
2050 tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
2051 tt_int_op(int2,OP_EQ, 9223372036854775807);
2053 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
2054 r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
2055 tt_int_op(r,OP_EQ, 0);
2057 r = tor_sscanf("9223372036854775808.", "%d.", &int1);
2058 tt_int_op(r,OP_EQ, 0);
2060 /* and the first failure stops further processing */
2061 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
2062 "%d. %d.", &int1, &int2);
2063 tt_int_op(r,OP_EQ, 1);
2065 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
2066 "%d. %d.", &int1, &int2);
2067 tt_int_op(r,OP_EQ, 0);
2069 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
2070 "%d. %d.", &int1, &int2);
2071 tt_int_op(r,OP_EQ, 0);
2072 #endif
2074 #if SIZEOF_LONG == 4
2075 /* %lu */
2076 /* UINT32_MAX should work */
2077 tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
2078 tt_int_op(4294967295UL,OP_EQ, ulng);
2080 /* But UINT32_MAX + 1 shouldn't work */
2081 tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
2082 /* but parsing only 9... */
2083 tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
2084 tt_int_op(429496729UL,OP_EQ, ulng);
2086 /* %lx */
2087 /* UINT32_MAX should work */
2088 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
2089 tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
2091 /* But UINT32_MAX + 1 shouldn't work */
2092 tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
2094 /* %ld */
2095 /* INT32_MIN and INT32_MAX should work */
2096 r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
2097 tt_int_op(r,OP_EQ, 2);
2098 tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
2099 tt_int_op(lng2,OP_EQ, 2147483647L);
2101 /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
2102 r = tor_sscanf("-2147483649.", "%ld.", &lng1);
2103 tt_int_op(r,OP_EQ, 0);
2105 r = tor_sscanf("2147483648.", "%ld.", &lng1);
2106 tt_int_op(r,OP_EQ, 0);
2108 /* and the first failure stops further processing */
2109 r = tor_sscanf("-2147483648. 2147483648.",
2110 "%ld. %ld.", &lng1, &lng2);
2111 tt_int_op(r,OP_EQ, 1);
2113 r = tor_sscanf("-2147483649. 2147483647.",
2114 "%ld. %ld.", &lng1, &lng2);
2115 tt_int_op(r,OP_EQ, 0);
2117 r = tor_sscanf("2147483648. -2147483649.",
2118 "%ld. %ld.", &lng1, &lng2);
2119 tt_int_op(r,OP_EQ, 0);
2120 #elif SIZEOF_LONG == 8
2121 /* %lu */
2122 /* UINT64_MAX should work */
2123 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
2124 tt_int_op(18446744073709551615UL,OP_EQ, ulng);
2126 /* But UINT64_MAX + 1 shouldn't work */
2127 tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
2128 /* but parsing only 19... */
2129 tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
2130 tt_int_op(1844674407370955161UL,OP_EQ, ulng);
2132 /* %lx */
2133 /* UINT64_MAX should work */
2134 tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
2135 tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
2137 /* But UINT64_MAX + 1 shouldn't work */
2138 tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
2140 /* %ld */
2141 /* INT64_MIN and INT64_MAX should work */
2142 r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
2143 "%ld. %ld.", &lng1, &lng2);
2144 tt_int_op(r,OP_EQ, 2);
2145 tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
2146 tt_int_op(lng2,OP_EQ, 9223372036854775807L);
2148 /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
2149 r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
2150 tt_int_op(r,OP_EQ, 0);
2152 r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
2153 tt_int_op(r,OP_EQ, 0);
2155 /* and the first failure stops further processing */
2156 r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
2157 "%ld. %ld.", &lng1, &lng2);
2158 tt_int_op(r,OP_EQ, 1);
2160 r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
2161 "%ld. %ld.", &lng1, &lng2);
2162 tt_int_op(r,OP_EQ, 0);
2164 r = tor_sscanf("9223372036854775808. -9223372036854775809.",
2165 "%ld. %ld.", &lng1, &lng2);
2166 tt_int_op(r,OP_EQ, 0);
2167 #endif
2169 r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
2170 "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
2171 tt_int_op(r,OP_EQ, 4);
2172 test_feq(d1, 123.456);
2173 test_feq(d2, .000007);
2174 test_feq(d3, -900123123.2000787);
2175 test_feq(d4, 3.2);
2177 done:
2181 #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
2182 #define tt_ci_char_op(a,op,b) tt_char_op(tolower(a),op,tolower(b))
2184 #ifndef HAVE_STRNLEN
2185 static size_t
2186 strnlen(const char *s, size_t len)
2188 const char *p = memchr(s, 0, len);
2189 if (!p)
2190 return len;
2191 return p - s;
2193 #endif
2195 static void
2196 test_util_format_time_interval(void *arg)
2198 /* use the same sized buffer and integers as tor uses */
2199 #define DBUF_SIZE 64
2200 char dbuf[DBUF_SIZE];
2201 #define T_ "%ld"
2202 long sec, min, hour, day;
2204 /* we don't care about the exact spelling of the
2205 * second(s), minute(s), hour(s), day(s) labels */
2206 #define LABEL_SIZE 21
2207 #define L_ "%20s"
2208 char label_s[LABEL_SIZE];
2209 char label_m[LABEL_SIZE];
2210 char label_h[LABEL_SIZE];
2211 char label_d[LABEL_SIZE];
2213 #define TL_ T_ " " L_
2215 int r;
2217 (void)arg;
2219 /* In these tests, we're not picky about
2220 * spelling or abbreviations */
2222 /* seconds: 0, 1, 9, 10, 59 */
2224 /* ignore exact spelling of "second(s)"*/
2225 format_time_interval(dbuf, sizeof(dbuf), 0);
2226 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2227 r = tor_sscanf(dbuf, TL_, &sec, label_s);
2228 tt_int_op(r,OP_EQ, 2);
2229 tt_ci_char_op(label_s[0],OP_EQ, 's');
2230 tt_int_op(sec,OP_EQ, 0);
2232 format_time_interval(dbuf, sizeof(dbuf), 1);
2233 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2234 r = tor_sscanf(dbuf, TL_, &sec, label_s);
2235 tt_int_op(r,OP_EQ, 2);
2236 tt_ci_char_op(label_s[0],OP_EQ, 's');
2237 tt_int_op(sec,OP_EQ, 1);
2239 format_time_interval(dbuf, sizeof(dbuf), 10);
2240 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2241 r = tor_sscanf(dbuf, TL_, &sec, label_s);
2242 tt_int_op(r,OP_EQ, 2);
2243 tt_ci_char_op(label_s[0],OP_EQ, 's');
2244 tt_int_op(sec,OP_EQ, 10);
2246 format_time_interval(dbuf, sizeof(dbuf), 59);
2247 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2248 r = tor_sscanf(dbuf, TL_, &sec, label_s);
2249 tt_int_op(r,OP_EQ, 2);
2250 tt_ci_char_op(label_s[0],OP_EQ, 's');
2251 tt_int_op(sec,OP_EQ, 59);
2253 /* negative seconds are reported as their absolute value */
2255 format_time_interval(dbuf, sizeof(dbuf), -4);
2256 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2257 r = tor_sscanf(dbuf, TL_, &sec, label_s);
2258 tt_int_op(r,OP_EQ, 2);
2259 tt_ci_char_op(label_s[0],OP_EQ, 's');
2260 tt_int_op(sec,OP_EQ, 4);
2261 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2263 format_time_interval(dbuf, sizeof(dbuf), -32);
2264 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2265 r = tor_sscanf(dbuf, TL_, &sec, label_s);
2266 tt_int_op(r,OP_EQ, 2);
2267 tt_ci_char_op(label_s[0],OP_EQ, 's');
2268 tt_int_op(sec,OP_EQ, 32);
2269 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2271 /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
2273 /* ignore trailing "0 second(s)", if present */
2274 format_time_interval(dbuf, sizeof(dbuf), 60);
2275 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2276 r = tor_sscanf(dbuf, TL_, &min, label_m);
2277 tt_int_op(r,OP_EQ, 2);
2278 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2279 tt_int_op(min,OP_EQ, 1);
2280 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2282 /* ignore exact spelling of "minute(s)," and "second(s)" */
2283 format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
2284 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2285 r = tor_sscanf(dbuf, TL_ " " TL_,
2286 &min, label_m, &sec, label_s);
2287 tt_int_op(r,OP_EQ, 4);
2288 tt_int_op(min,OP_EQ, 1);
2289 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2290 tt_int_op(sec,OP_EQ, 1);
2291 tt_ci_char_op(label_s[0],OP_EQ, 's');
2292 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2294 format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
2295 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2296 r = tor_sscanf(dbuf, TL_ " " TL_,
2297 &min, label_m, &sec, label_s);
2298 tt_int_op(r,OP_EQ, 4);
2299 tt_int_op(min,OP_EQ, 1);
2300 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2301 tt_int_op(sec,OP_EQ, 59);
2302 tt_ci_char_op(label_s[0],OP_EQ, 's');
2304 /* ignore trailing "0 second(s)", if present */
2305 format_time_interval(dbuf, sizeof(dbuf), 60*2);
2306 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2307 r = tor_sscanf(dbuf, TL_, &min, label_m);
2308 tt_int_op(r,OP_EQ, 2);
2309 tt_int_op(min,OP_EQ, 2);
2310 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2312 /* ignore exact spelling of "minute(s)," and "second(s)" */
2313 format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
2314 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2315 r = tor_sscanf(dbuf, TL_ " " TL_,
2316 &min, label_m, &sec, label_s);
2317 tt_int_op(r,OP_EQ, 4);
2318 tt_int_op(min,OP_EQ, 2);
2319 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2320 tt_int_op(sec,OP_EQ, 1);
2321 tt_ci_char_op(label_s[0],OP_EQ, 's');
2323 format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
2324 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2325 r = tor_sscanf(dbuf, TL_ " " TL_,
2326 &min, label_m, &sec, label_s);
2327 tt_int_op(r,OP_EQ, 4);
2328 tt_int_op(min,OP_EQ, 59);
2329 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2330 tt_int_op(sec,OP_EQ, 59);
2331 tt_ci_char_op(label_s[0],OP_EQ, 's');
2333 /* negative minutes are reported as their absolute value */
2335 /* ignore trailing "0 second(s)", if present */
2336 format_time_interval(dbuf, sizeof(dbuf), -3*60);
2337 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2338 r = tor_sscanf(dbuf, TL_, &min, label_m);
2339 tt_int_op(r,OP_EQ, 2);
2340 tt_int_op(min,OP_EQ, 3);
2341 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2343 /* ignore exact spelling of "minute(s)," and "second(s)" */
2344 format_time_interval(dbuf, sizeof(dbuf), -96);
2345 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2346 r = tor_sscanf(dbuf, TL_ " " TL_,
2347 &min, label_m, &sec, label_s);
2348 tt_int_op(r,OP_EQ, 4);
2349 tt_int_op(min,OP_EQ, 1);
2350 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2351 tt_int_op(sec,OP_EQ, 36);
2352 tt_ci_char_op(label_s[0],OP_EQ, 's');
2354 format_time_interval(dbuf, sizeof(dbuf), -2815);
2355 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2356 r = tor_sscanf(dbuf, TL_ " " TL_,
2357 &min, label_m, &sec, label_s);
2358 tt_int_op(r,OP_EQ, 4);
2359 tt_int_op(min,OP_EQ, 46);
2360 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2361 tt_int_op(sec,OP_EQ, 55);
2362 tt_ci_char_op(label_s[0],OP_EQ, 's');
2364 /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
2365 /* always ignore trailing seconds, if present */
2367 /* ignore trailing "0 minute(s)" etc., if present */
2368 format_time_interval(dbuf, sizeof(dbuf), 60*60);
2369 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2370 r = tor_sscanf(dbuf, TL_, &hour, label_h);
2371 tt_int_op(r,OP_EQ, 2);
2372 tt_int_op(hour,OP_EQ, 1);
2373 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2375 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
2376 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2377 r = tor_sscanf(dbuf, TL_, &hour, label_h);
2378 tt_int_op(r,OP_EQ, 2);
2379 tt_int_op(hour,OP_EQ, 1);
2380 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2382 /* ignore exact spelling of "hour(s)," etc. */
2383 format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
2384 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2385 r = tor_sscanf(dbuf, TL_ " " TL_,
2386 &hour, label_h, &min, label_m);
2387 tt_int_op(r,OP_EQ, 4);
2388 tt_int_op(hour,OP_EQ, 1);
2389 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2390 tt_int_op(min,OP_EQ, 1);
2391 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2393 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
2394 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2395 r = tor_sscanf(dbuf, TL_ " " TL_,
2396 &hour, label_h, &min, label_m);
2397 tt_int_op(r,OP_EQ, 4);
2398 tt_int_op(hour,OP_EQ, 23);
2399 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2400 tt_int_op(min,OP_EQ, 59);
2401 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2403 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
2404 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2405 r = tor_sscanf(dbuf, TL_ " " TL_,
2406 &hour, label_h, &min, label_m);
2407 tt_int_op(r,OP_EQ, 4);
2408 tt_int_op(hour,OP_EQ, 23);
2409 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2410 tt_int_op(min,OP_EQ, 59);
2411 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2413 /* negative hours are reported as their absolute value */
2415 /* ignore exact spelling of "hour(s)," etc., if present */
2416 format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
2417 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2418 r = tor_sscanf(dbuf, TL_, &hour, label_h);
2419 tt_int_op(r,OP_EQ, 2);
2420 tt_int_op(hour,OP_EQ, 2);
2421 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2423 format_time_interval(dbuf, sizeof(dbuf), -75804);
2424 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2425 r = tor_sscanf(dbuf, TL_ " " TL_,
2426 &hour, label_h, &min, label_m);
2427 tt_int_op(r,OP_EQ, 4);
2428 tt_int_op(hour,OP_EQ, 21);
2429 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2430 tt_int_op(min,OP_EQ, 3);
2431 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2433 /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
2434 /* always ignore trailing seconds, if present */
2436 /* ignore trailing "0 hours(s)" etc., if present */
2437 format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
2438 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2439 r = tor_sscanf(dbuf, TL_, &day, label_d);
2440 tt_int_op(r,OP_EQ, 2);
2441 tt_int_op(day,OP_EQ, 1);
2442 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2444 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
2445 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2446 r = tor_sscanf(dbuf, TL_, &day, label_d);
2447 tt_int_op(r,OP_EQ, 2);
2448 tt_int_op(day,OP_EQ, 1);
2449 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2451 /* ignore exact spelling of "days(s)," etc. */
2452 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
2453 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2454 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2455 &day, label_d, &hour, label_h, &min, label_m);
2456 if (r == -1) {
2457 /* ignore 0 hours(s), if present */
2458 r = tor_sscanf(dbuf, TL_ " " TL_,
2459 &day, label_d, &min, label_m);
2461 tt_assert(r == 4 || r == 6);
2462 tt_int_op(day,OP_EQ, 1);
2463 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2464 if (r == 6) {
2465 tt_int_op(hour,OP_EQ, 0);
2466 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2468 tt_int_op(min,OP_EQ, 1);
2469 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2471 /* ignore trailing "0 minutes(s)" etc., if present */
2472 format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
2473 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2474 r = tor_sscanf(dbuf, TL_ " " TL_,
2475 &day, label_d, &hour, label_h);
2476 tt_int_op(r,OP_EQ, 4);
2477 tt_int_op(day,OP_EQ, 1);
2478 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2479 tt_int_op(hour,OP_EQ, 1);
2480 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2482 /* negative days are reported as their absolute value */
2484 format_time_interval(dbuf, sizeof(dbuf), -21936184);
2485 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2486 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2487 &day, label_d, &hour, label_h, &min, label_m);
2488 tt_int_op(r,OP_EQ, 6);
2489 tt_int_op(day,OP_EQ, 253);
2490 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2491 tt_int_op(hour,OP_EQ, 21);
2492 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2493 tt_int_op(min,OP_EQ, 23);
2494 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2496 /* periods > 1 year are reported in days (warn?) */
2498 /* ignore exact spelling of "days(s)," etc., if present */
2499 format_time_interval(dbuf, sizeof(dbuf), 758635154);
2500 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2501 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2502 &day, label_d, &hour, label_h, &min, label_m);
2503 tt_int_op(r,OP_EQ, 6);
2504 tt_int_op(day,OP_EQ, 8780);
2505 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2506 tt_int_op(hour,OP_EQ, 11);
2507 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2508 tt_int_op(min,OP_EQ, 59);
2509 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2511 /* negative periods > 1 year are reported in days (warn?) */
2513 format_time_interval(dbuf, sizeof(dbuf), -1427014922);
2514 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2515 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2516 &day, label_d, &hour, label_h, &min, label_m);
2517 tt_int_op(r,OP_EQ, 6);
2518 tt_int_op(day,OP_EQ, 16516);
2519 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2520 tt_int_op(hour,OP_EQ, 9);
2521 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2522 tt_int_op(min,OP_EQ, 2);
2523 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2525 #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
2527 /* We can try INT32_MIN/MAX */
2528 /* Always ignore second(s) */
2530 /* INT32_MAX */
2531 format_time_interval(dbuf, sizeof(dbuf), 2147483647);
2532 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2533 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2534 &day, label_d, &hour, label_h, &min, label_m);
2535 tt_int_op(r,OP_EQ, 6);
2536 tt_int_op(day,OP_EQ, 24855);
2537 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2538 tt_int_op(hour,OP_EQ, 3);
2539 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2540 tt_int_op(min,OP_EQ, 14);
2541 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2542 /* and 7 seconds - ignored */
2544 /* INT32_MIN: check that we get the absolute value of interval,
2545 * which doesn't actually fit in int32_t.
2546 * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
2547 format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
2548 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2549 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2550 &day, label_d, &hour, label_h, &min, label_m);
2551 tt_int_op(r,OP_EQ, 6);
2552 tt_int_op(day,OP_EQ, 24855);
2553 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2554 tt_int_op(hour,OP_EQ, 3);
2555 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2556 tt_int_op(min,OP_EQ, 14);
2557 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2558 /* and 7 or 8 seconds - ignored */
2560 #endif
2562 #if SIZEOF_LONG == 8
2564 /* We can try INT64_MIN/MAX */
2565 /* Always ignore second(s) */
2567 /* INT64_MAX */
2568 format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
2569 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2570 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2571 &day, label_d, &hour, label_h, &min, label_m);
2572 tt_int_op(r,OP_EQ, 6);
2573 tt_int_op(day,OP_EQ, 106751991167300L);
2574 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2575 tt_int_op(hour,OP_EQ, 15);
2576 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2577 tt_int_op(min,OP_EQ, 30);
2578 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2579 /* and 7 seconds - ignored */
2581 /* INT64_MIN: check that we get the absolute value of interval,
2582 * which doesn't actually fit in int64_t.
2583 * We expect INT64_MAX */
2584 format_time_interval(dbuf, sizeof(dbuf),
2585 -9223372036854775807L - 1L);
2586 tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
2587 r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
2588 &day, label_d, &hour, label_h, &min, label_m);
2589 tt_int_op(r,OP_EQ, 6);
2590 tt_int_op(day,OP_EQ, 106751991167300L);
2591 tt_ci_char_op(label_d[0],OP_EQ, 'd');
2592 tt_int_op(hour,OP_EQ, 15);
2593 tt_ci_char_op(label_h[0],OP_EQ, 'h');
2594 tt_int_op(min,OP_EQ, 30);
2595 tt_ci_char_op(label_m[0],OP_EQ, 'm');
2596 /* and 7 or 8 seconds - ignored */
2598 #endif
2600 done:
2604 #undef tt_char_op
2605 #undef tt_ci_char_op
2606 #undef DBUF_SIZE
2607 #undef T_
2608 #undef LABEL_SIZE
2609 #undef L_
2610 #undef TL_
2612 static void
2613 test_util_path_is_relative(void *arg)
2615 /* OS-independent tests */
2616 (void)arg;
2617 tt_int_op(1,OP_EQ, path_is_relative(""));
2618 tt_int_op(1,OP_EQ, path_is_relative("dir"));
2619 tt_int_op(1,OP_EQ, path_is_relative("dir/"));
2620 tt_int_op(1,OP_EQ, path_is_relative("./dir"));
2621 tt_int_op(1,OP_EQ, path_is_relative("../dir"));
2623 tt_int_op(0,OP_EQ, path_is_relative("/"));
2624 tt_int_op(0,OP_EQ, path_is_relative("/dir"));
2625 tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
2627 /* Windows */
2628 #ifdef _WIN32
2629 /* I don't have Windows so I can't test this, hence the "#ifdef
2630 0". These are tests that look useful, so please try to get them
2631 running and uncomment if it all works as it should */
2632 tt_int_op(1,OP_EQ, path_is_relative("dir"));
2633 tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
2634 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
2635 tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
2636 tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
2638 tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
2639 tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
2640 tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
2641 #endif
2643 done:
2647 #ifdef ENABLE_MEMPOOLS
2649 /** Run unittests for memory pool allocator */
2650 static void
2651 test_util_mempool(void *arg)
2653 mp_pool_t *pool = NULL;
2654 smartlist_t *allocated = NULL;
2655 int i;
2657 (void)arg;
2658 pool = mp_pool_new(1, 100);
2659 tt_assert(pool);
2660 tt_assert(pool->new_chunk_capacity >= 100);
2661 tt_assert(pool->item_alloc_size >= sizeof(void*)+1);
2662 mp_pool_destroy(pool);
2663 pool = NULL;
2665 pool = mp_pool_new(241, 2500);
2666 tt_assert(pool);
2667 tt_assert(pool->new_chunk_capacity >= 10);
2668 tt_assert(pool->item_alloc_size >= sizeof(void*)+241);
2669 tt_int_op(pool->item_alloc_size & 0x03,OP_EQ, 0);
2670 tt_assert(pool->new_chunk_capacity < 60);
2672 allocated = smartlist_new();
2673 for (i = 0; i < 20000; ++i) {
2674 if (smartlist_len(allocated) < 20 || crypto_rand_int(2)) {
2675 void *m = mp_pool_get(pool);
2676 memset(m, 0x09, 241);
2677 smartlist_add(allocated, m);
2678 //printf("%d: %p\n", i, m);
2679 //mp_pool_assert_ok(pool);
2680 } else {
2681 int idx = crypto_rand_int(smartlist_len(allocated));
2682 void *m = smartlist_get(allocated, idx);
2683 //printf("%d: free %p\n", i, m);
2684 smartlist_del(allocated, idx);
2685 mp_pool_release(m);
2686 //mp_pool_assert_ok(pool);
2688 if (crypto_rand_int(777)==0)
2689 mp_pool_clean(pool, 1, 1);
2691 if (i % 777)
2692 mp_pool_assert_ok(pool);
2695 done:
2696 if (allocated) {
2697 SMARTLIST_FOREACH(allocated, void *, m, mp_pool_release(m));
2698 mp_pool_assert_ok(pool);
2699 mp_pool_clean(pool, 0, 0);
2700 mp_pool_assert_ok(pool);
2701 smartlist_free(allocated);
2704 if (pool)
2705 mp_pool_destroy(pool);
2708 #endif /* ENABLE_MEMPOOLS */
2710 /** Run unittests for memory area allocator */
2711 static void
2712 test_util_memarea(void *arg)
2714 memarea_t *area = memarea_new();
2715 char *p1, *p2, *p3, *p1_orig;
2716 void *malloced_ptr = NULL;
2717 int i;
2719 (void)arg;
2720 tt_assert(area);
2722 p1_orig = p1 = memarea_alloc(area,64);
2723 p2 = memarea_alloc_zero(area,52);
2724 p3 = memarea_alloc(area,11);
2726 tt_assert(memarea_owns_ptr(area, p1));
2727 tt_assert(memarea_owns_ptr(area, p2));
2728 tt_assert(memarea_owns_ptr(area, p3));
2729 /* Make sure we left enough space. */
2730 tt_assert(p1+64 <= p2);
2731 tt_assert(p2+52 <= p3);
2732 /* Make sure we aligned. */
2733 tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
2734 tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
2735 tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
2736 tt_assert(!memarea_owns_ptr(area, p3+8192));
2737 tt_assert(!memarea_owns_ptr(area, p3+30));
2738 tt_assert(tor_mem_is_zero(p2, 52));
2739 /* Make sure we don't overalign. */
2740 p1 = memarea_alloc(area, 1);
2741 p2 = memarea_alloc(area, 1);
2742 tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
2744 malloced_ptr = tor_malloc(64);
2745 tt_assert(!memarea_owns_ptr(area, malloced_ptr));
2746 tor_free(malloced_ptr);
2749 /* memarea_memdup */
2751 malloced_ptr = tor_malloc(64);
2752 crypto_rand((char*)malloced_ptr, 64);
2753 p1 = memarea_memdup(area, malloced_ptr, 64);
2754 tt_assert(p1 != malloced_ptr);
2755 tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
2756 tor_free(malloced_ptr);
2759 /* memarea_strdup. */
2760 p1 = memarea_strdup(area,"");
2761 p2 = memarea_strdup(area, "abcd");
2762 tt_assert(p1);
2763 tt_assert(p2);
2764 tt_str_op(p1,OP_EQ, "");
2765 tt_str_op(p2,OP_EQ, "abcd");
2767 /* memarea_strndup. */
2769 const char *s = "Ad ogni porta batte la morte e grida: il nome!";
2770 /* (From Turandot, act 3.) */
2771 size_t len = strlen(s);
2772 p1 = memarea_strndup(area, s, 1000);
2773 p2 = memarea_strndup(area, s, 10);
2774 tt_str_op(p1,OP_EQ, s);
2775 tt_assert(p2 >= p1 + len + 1);
2776 tt_mem_op(s,OP_EQ, p2, 10);
2777 tt_int_op(p2[10],OP_EQ, '\0');
2778 p3 = memarea_strndup(area, s, len);
2779 tt_str_op(p3,OP_EQ, s);
2780 p3 = memarea_strndup(area, s, len-1);
2781 tt_mem_op(s,OP_EQ, p3, len-1);
2782 tt_int_op(p3[len-1],OP_EQ, '\0');
2785 memarea_clear(area);
2786 p1 = memarea_alloc(area, 1);
2787 tt_ptr_op(p1,OP_EQ, p1_orig);
2788 memarea_clear(area);
2790 /* Check for running over an area's size. */
2791 for (i = 0; i < 512; ++i) {
2792 p1 = memarea_alloc(area, crypto_rand_int(5)+1);
2793 tt_assert(memarea_owns_ptr(area, p1));
2795 memarea_assert_ok(area);
2796 /* Make sure we can allocate a too-big object. */
2797 p1 = memarea_alloc_zero(area, 9000);
2798 p2 = memarea_alloc_zero(area, 16);
2799 tt_assert(memarea_owns_ptr(area, p1));
2800 tt_assert(memarea_owns_ptr(area, p2));
2802 done:
2803 memarea_drop_all(area);
2804 tor_free(malloced_ptr);
2807 /** Run unit tests for utility functions to get file names relative to
2808 * the data directory. */
2809 static void
2810 test_util_datadir(void *arg)
2812 char buf[1024];
2813 char *f = NULL;
2814 char *temp_dir = NULL;
2816 (void)arg;
2817 temp_dir = get_datadir_fname(NULL);
2818 f = get_datadir_fname("state");
2819 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
2820 tt_str_op(f,OP_EQ, buf);
2821 tor_free(f);
2822 f = get_datadir_fname2("cache", "thingy");
2823 tor_snprintf(buf, sizeof(buf),
2824 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
2825 tt_str_op(f,OP_EQ, buf);
2826 tor_free(f);
2827 f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
2828 tor_snprintf(buf, sizeof(buf),
2829 "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
2830 tt_str_op(f,OP_EQ, buf);
2831 tor_free(f);
2832 f = get_datadir_fname_suffix("cache", ".foo");
2833 tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
2834 temp_dir);
2835 tt_str_op(f,OP_EQ, buf);
2837 done:
2838 tor_free(f);
2839 tor_free(temp_dir);
2842 static void
2843 test_util_strtok(void *arg)
2845 char buf[128];
2846 char buf2[128];
2847 int i;
2848 char *cp1, *cp2;
2850 (void)arg;
2851 for (i = 0; i < 3; i++) {
2852 const char *pad1="", *pad2="";
2853 switch (i) {
2854 case 0:
2855 break;
2856 case 1:
2857 pad1 = " ";
2858 pad2 = "!";
2859 break;
2860 case 2:
2861 pad1 = " ";
2862 pad2 = ";!";
2863 break;
2865 tor_snprintf(buf, sizeof(buf), "%s", pad1);
2866 tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
2867 tt_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1));
2868 tt_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2));
2870 tor_snprintf(buf, sizeof(buf),
2871 "%sGraved on the dark in gestures of descent%s", pad1, pad1);
2872 tor_snprintf(buf2, sizeof(buf2),
2873 "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
2874 /* -- "Year's End", Richard Wilbur */
2876 tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
2877 tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
2878 #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
2879 #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
2880 tt_str_op("on",OP_EQ, S1());
2881 tt_str_op("the",OP_EQ, S1());
2882 tt_str_op("dark",OP_EQ, S1());
2883 tt_str_op("seemed",OP_EQ, S2());
2884 tt_str_op("their",OP_EQ, S2());
2885 tt_str_op("own",OP_EQ, S2());
2886 tt_str_op("in",OP_EQ, S1());
2887 tt_str_op("gestures",OP_EQ, S1());
2888 tt_str_op("of",OP_EQ, S1());
2889 tt_str_op("most",OP_EQ, S2());
2890 tt_str_op("perfect",OP_EQ, S2());
2891 tt_str_op("descent",OP_EQ, S1());
2892 tt_str_op("monument",OP_EQ, S2());
2893 tt_ptr_op(NULL,OP_EQ, S1());
2894 tt_ptr_op(NULL,OP_EQ, S2());
2897 buf[0] = 0;
2898 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
2899 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
2901 strlcpy(buf, "Howdy!", sizeof(buf));
2902 tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
2903 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
2905 strlcpy(buf, " ", sizeof(buf));
2906 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
2907 strlcpy(buf, " ", sizeof(buf));
2908 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
2910 strlcpy(buf, "something ", sizeof(buf));
2911 tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
2912 tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
2913 done:
2917 static void
2918 test_util_find_str_at_start_of_line(void *ptr)
2920 const char *long_string =
2921 "howdy world. how are you? i hope it's fine.\n"
2922 "hello kitty\n"
2923 "third line";
2924 char *line2 = strchr(long_string,'\n')+1;
2925 char *line3 = strchr(line2,'\n')+1;
2926 const char *short_string = "hello kitty\n"
2927 "second line\n";
2928 char *short_line2 = strchr(short_string,'\n')+1;
2930 (void)ptr;
2932 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
2933 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
2934 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
2935 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
2936 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
2937 tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
2938 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
2939 tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
2940 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
2941 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
2942 tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
2943 tt_ptr_op(line2,OP_EQ,
2944 find_str_at_start_of_line(long_string, "hello kitty\n"));
2945 tt_ptr_op(line2,OP_EQ,
2946 find_str_at_start_of_line(long_string, "hello kitty\nt"));
2947 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
2948 tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
2949 tt_ptr_op(NULL, OP_EQ,
2950 find_str_at_start_of_line(long_string, "third line\n"));
2951 tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
2952 "second line\n"));
2953 done:
2957 static void
2958 test_util_string_is_C_identifier(void *ptr)
2960 (void)ptr;
2962 tt_int_op(1,OP_EQ, string_is_C_identifier("string_is_C_identifier"));
2963 tt_int_op(1,OP_EQ, string_is_C_identifier("_string_is_C_identifier"));
2964 tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
2965 tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
2966 tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
2967 tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
2968 tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
2969 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
2970 tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
2971 tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
2973 tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
2974 tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
2975 tt_int_op(0,OP_EQ, string_is_C_identifier(""));
2976 tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
2977 tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
2978 tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
2979 tt_int_op(0,OP_EQ, string_is_C_identifier("í"));
2980 tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
2982 done:
2986 static void
2987 test_util_asprintf(void *ptr)
2989 #define LOREMIPSUM \
2990 "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
2991 char *cp=NULL, *cp2=NULL;
2992 int r;
2993 (void)ptr;
2995 /* simple string */
2996 r = tor_asprintf(&cp, "simple string 100%% safe");
2997 tt_assert(cp);
2998 tt_str_op("simple string 100% safe",OP_EQ, cp);
2999 tt_int_op(strlen(cp),OP_EQ, r);
3000 tor_free(cp);
3002 /* empty string */
3003 r = tor_asprintf(&cp, "%s", "");
3004 tt_assert(cp);
3005 tt_str_op("",OP_EQ, cp);
3006 tt_int_op(strlen(cp),OP_EQ, r);
3007 tor_free(cp);
3009 /* numbers (%i) */
3010 r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
3011 tt_assert(cp);
3012 tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
3013 tt_int_op(strlen(cp),OP_EQ, r);
3014 /* don't free cp; next test uses it. */
3016 /* numbers (%d) */
3017 r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
3018 tt_assert(cp2);
3019 tt_int_op(strlen(cp2),OP_EQ, r);
3020 tt_str_op("First=101, Second=202",OP_EQ, cp2);
3021 tt_assert(cp != cp2);
3022 tor_free(cp);
3023 tor_free(cp2);
3025 /* Glass-box test: a string exactly 128 characters long. */
3026 r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
3027 tt_assert(cp);
3028 tt_int_op(128,OP_EQ, r);
3029 tt_int_op(cp[128], OP_EQ, '\0');
3030 tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
3031 tor_free(cp);
3033 /* String longer than 128 characters */
3034 r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
3035 LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
3036 tt_assert(cp);
3037 tt_int_op(strlen(cp),OP_EQ, r);
3038 tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
3040 done:
3041 tor_free(cp);
3042 tor_free(cp2);
3045 static void
3046 test_util_listdir(void *ptr)
3048 smartlist_t *dir_contents = NULL;
3049 char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
3050 int r;
3051 (void)ptr;
3053 fname1 = tor_strdup(get_fname("hopscotch"));
3054 fname2 = tor_strdup(get_fname("mumblety-peg"));
3055 fname3 = tor_strdup(get_fname(".hidden-file"));
3056 dir1 = tor_strdup(get_fname("some-directory"));
3057 dirname = tor_strdup(get_fname(NULL));
3059 tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
3060 tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
3061 tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
3062 #ifdef _WIN32
3063 r = mkdir(dir1);
3064 #else
3065 r = mkdir(dir1, 0700);
3066 #endif
3067 if (r) {
3068 fprintf(stderr, "Can't create directory %s:", dir1);
3069 perror("");
3070 exit(1);
3073 dir_contents = tor_listdir(dirname);
3074 tt_assert(dir_contents);
3075 /* make sure that each filename is listed. */
3076 tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
3077 tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
3078 tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
3079 tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
3081 tt_assert(!smartlist_contains_string(dir_contents, "."));
3082 tt_assert(!smartlist_contains_string(dir_contents, ".."));
3084 done:
3085 tor_free(fname1);
3086 tor_free(fname2);
3087 tor_free(fname3);
3088 tor_free(dir1);
3089 tor_free(dirname);
3090 if (dir_contents) {
3091 SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
3092 smartlist_free(dir_contents);
3096 static void
3097 test_util_parent_dir(void *ptr)
3099 char *cp;
3100 (void)ptr;
3102 #define T(output,expect_ok,input) \
3103 do { \
3104 int ok; \
3105 cp = tor_strdup(input); \
3106 ok = get_parent_directory(cp); \
3107 tt_int_op(expect_ok, OP_EQ, ok); \
3108 if (ok==0) \
3109 tt_str_op(output, OP_EQ, cp); \
3110 tor_free(cp); \
3111 } while (0);
3113 T("/home/wombat", 0, "/home/wombat/knish");
3114 T("/home/wombat", 0, "/home/wombat/knish/");
3115 T("/home/wombat", 0, "/home/wombat/knish///");
3116 T("./home/wombat", 0, "./home/wombat/knish/");
3117 T("/", 0, "/home");
3118 T("/", 0, "/home//");
3119 T(".", 0, "./wombat");
3120 T(".", 0, "./wombat/");
3121 T(".", 0, "./wombat//");
3122 T("wombat", 0, "wombat/foo");
3123 T("wombat/..", 0, "wombat/../foo");
3124 T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
3125 T("wombat/.", 0, "wombat/./foo");
3126 T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
3127 T("wombat", 0, "wombat/..//");
3128 T("wombat", 0, "wombat/foo/");
3129 T("wombat", 0, "wombat/.foo");
3130 T("wombat", 0, "wombat/.foo/");
3132 T("wombat", -1, "");
3133 T("w", -1, "");
3134 T("wombat", 0, "wombat/knish");
3136 T("/", 0, "/");
3137 T("/", 0, "////");
3139 done:
3140 tor_free(cp);
3143 static void
3144 test_util_ftruncate(void *ptr)
3146 char *buf = NULL;
3147 const char *fname;
3148 int fd = -1;
3149 const char *message = "Hello world";
3150 const char *message2 = "Hola mundo";
3151 struct stat st;
3153 (void) ptr;
3155 fname = get_fname("ftruncate");
3157 fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
3158 tt_int_op(fd, OP_GE, 0);
3160 /* Make the file be there. */
3161 tt_int_op(strlen(message), OP_EQ, write_all(fd, message, strlen(message),0));
3162 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
3163 tt_int_op(0, OP_EQ, fstat(fd, &st));
3164 tt_int_op((int)st.st_size, OP_EQ, strlen(message));
3166 /* Truncate and see if it got truncated */
3167 tt_int_op(0, OP_EQ, tor_ftruncate(fd));
3168 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
3169 tt_int_op(0, OP_EQ, fstat(fd, &st));
3170 tt_int_op((int)st.st_size, OP_EQ, 0);
3172 /* Replace, and see if it got replaced */
3173 tt_int_op(strlen(message2), OP_EQ,
3174 write_all(fd, message2, strlen(message2), 0));
3175 tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
3176 tt_int_op(0, OP_EQ, fstat(fd, &st));
3177 tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
3179 close(fd);
3180 fd = -1;
3182 buf = read_file_to_str(fname, 0, NULL);
3183 tt_str_op(message2, OP_EQ, buf);
3185 done:
3186 if (fd >= 0)
3187 close(fd);
3188 tor_free(buf);
3191 #ifdef _WIN32
3192 static void
3193 test_util_load_win_lib(void *ptr)
3195 HANDLE h = load_windows_system_library(_T("advapi32.dll"));
3196 (void) ptr;
3198 tt_assert(h);
3199 done:
3200 if (h)
3201 FreeLibrary(h);
3203 #endif
3205 #ifndef _WIN32
3206 static void
3207 clear_hex_errno(char *hex_errno)
3209 memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
3212 static void
3213 test_util_exit_status(void *ptr)
3215 /* Leave an extra byte for a \0 so we can do string comparison */
3216 char hex_errno[HEX_ERRNO_SIZE + 1];
3217 int n;
3219 (void)ptr;
3221 clear_hex_errno(hex_errno);
3222 tt_str_op("",OP_EQ, hex_errno);
3224 clear_hex_errno(hex_errno);
3225 n = format_helper_exit_status(0, 0, hex_errno);
3226 tt_str_op("0/0\n",OP_EQ, hex_errno);
3227 tt_int_op(n,OP_EQ, strlen(hex_errno));
3229 #if SIZEOF_INT == 4
3231 clear_hex_errno(hex_errno);
3232 n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
3233 tt_str_op("0/7FFFFFFF\n",OP_EQ, hex_errno);
3234 tt_int_op(n,OP_EQ, strlen(hex_errno));
3236 clear_hex_errno(hex_errno);
3237 n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
3238 tt_str_op("FF/-80000000\n",OP_EQ, hex_errno);
3239 tt_int_op(n,OP_EQ, strlen(hex_errno));
3240 tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE);
3242 #elif SIZEOF_INT == 8
3244 clear_hex_errno(hex_errno);
3245 n = format_helper_exit_status(0, 0x7FFFFFFFFFFFFFFF, hex_errno);
3246 tt_str_op("0/7FFFFFFFFFFFFFFF\n",OP_EQ, hex_errno);
3247 tt_int_op(n,OP_EQ, strlen(hex_errno));
3249 clear_hex_errno(hex_errno);
3250 n = format_helper_exit_status(0xFF, -0x8000000000000000, hex_errno);
3251 tt_str_op("FF/-8000000000000000\n",OP_EQ, hex_errno);
3252 tt_int_op(n,OP_EQ, strlen(hex_errno));
3253 tt_int_op(n,OP_EQ, HEX_ERRNO_SIZE);
3255 #endif
3257 clear_hex_errno(hex_errno);
3258 n = format_helper_exit_status(0x7F, 0, hex_errno);
3259 tt_str_op("7F/0\n",OP_EQ, hex_errno);
3260 tt_int_op(n,OP_EQ, strlen(hex_errno));
3262 clear_hex_errno(hex_errno);
3263 n = format_helper_exit_status(0x08, -0x242, hex_errno);
3264 tt_str_op("8/-242\n",OP_EQ, hex_errno);
3265 tt_int_op(n,OP_EQ, strlen(hex_errno));
3267 clear_hex_errno(hex_errno);
3268 tt_str_op("",OP_EQ, hex_errno);
3270 done:
3273 #endif
3275 #ifndef _WIN32
3276 /* Check that fgets with a non-blocking pipe returns partial lines and sets
3277 * EAGAIN, returns full lines and sets no error, and returns NULL on EOF and
3278 * sets no error */
3279 static void
3280 test_util_fgets_eagain(void *ptr)
3282 int test_pipe[2] = {-1, -1};
3283 int retval;
3284 ssize_t retlen;
3285 char *retptr;
3286 FILE *test_stream = NULL;
3287 char buf[4] = { 0 };
3289 (void)ptr;
3291 errno = 0;
3293 /* Set up a pipe to test on */
3294 retval = pipe(test_pipe);
3295 tt_int_op(retval, OP_EQ, 0);
3297 /* Set up the read-end to be non-blocking */
3298 retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
3299 tt_int_op(retval, OP_EQ, 0);
3301 /* Open it as a stdio stream */
3302 test_stream = fdopen(test_pipe[0], "r");
3303 tt_ptr_op(test_stream, OP_NE, NULL);
3305 /* Send in a partial line */
3306 retlen = write(test_pipe[1], "A", 1);
3307 tt_int_op(retlen, OP_EQ, 1);
3308 retptr = fgets(buf, sizeof(buf), test_stream);
3309 tt_int_op(errno, OP_EQ, EAGAIN);
3310 tt_ptr_op(retptr, OP_EQ, buf);
3311 tt_str_op(buf, OP_EQ, "A");
3312 errno = 0;
3314 /* Send in the rest */
3315 retlen = write(test_pipe[1], "B\n", 2);
3316 tt_int_op(retlen, OP_EQ, 2);
3317 retptr = fgets(buf, sizeof(buf), test_stream);
3318 tt_int_op(errno, OP_EQ, 0);
3319 tt_ptr_op(retptr, OP_EQ, buf);
3320 tt_str_op(buf, OP_EQ, "B\n");
3321 errno = 0;
3323 /* Send in a full line */
3324 retlen = write(test_pipe[1], "CD\n", 3);
3325 tt_int_op(retlen, OP_EQ, 3);
3326 retptr = fgets(buf, sizeof(buf), test_stream);
3327 tt_int_op(errno, OP_EQ, 0);
3328 tt_ptr_op(retptr, OP_EQ, buf);
3329 tt_str_op(buf, OP_EQ, "CD\n");
3330 errno = 0;
3332 /* Send in a partial line */
3333 retlen = write(test_pipe[1], "E", 1);
3334 tt_int_op(retlen, OP_EQ, 1);
3335 retptr = fgets(buf, sizeof(buf), test_stream);
3336 tt_int_op(errno, OP_EQ, EAGAIN);
3337 tt_ptr_op(retptr, OP_EQ, buf);
3338 tt_str_op(buf, OP_EQ, "E");
3339 errno = 0;
3341 /* Send in the rest */
3342 retlen = write(test_pipe[1], "F\n", 2);
3343 tt_int_op(retlen, OP_EQ, 2);
3344 retptr = fgets(buf, sizeof(buf), test_stream);
3345 tt_int_op(errno, OP_EQ, 0);
3346 tt_ptr_op(retptr, OP_EQ, buf);
3347 tt_str_op(buf, OP_EQ, "F\n");
3348 errno = 0;
3350 /* Send in a full line and close */
3351 retlen = write(test_pipe[1], "GH", 2);
3352 tt_int_op(retlen, OP_EQ, 2);
3353 retval = close(test_pipe[1]);
3354 tt_int_op(retval, OP_EQ, 0);
3355 test_pipe[1] = -1;
3356 retptr = fgets(buf, sizeof(buf), test_stream);
3357 tt_int_op(errno, OP_EQ, 0);
3358 tt_ptr_op(retptr, OP_EQ, buf);
3359 tt_str_op(buf, OP_EQ, "GH");
3360 errno = 0;
3362 /* Check for EOF */
3363 retptr = fgets(buf, sizeof(buf), test_stream);
3364 tt_int_op(errno, OP_EQ, 0);
3365 tt_ptr_op(retptr, OP_EQ, NULL);
3366 retval = feof(test_stream);
3367 tt_int_op(retval, OP_NE, 0);
3368 errno = 0;
3370 /* Check that buf is unchanged according to C99 and C11 */
3371 tt_str_op(buf, OP_EQ, "GH");
3373 done:
3374 if (test_stream != NULL)
3375 fclose(test_stream);
3376 if (test_pipe[0] != -1)
3377 close(test_pipe[0]);
3378 if (test_pipe[1] != -1)
3379 close(test_pipe[1]);
3381 #endif
3384 * Test for format_hex_number_sigsafe()
3387 static void
3388 test_util_format_hex_number(void *ptr)
3390 int i, len;
3391 char buf[33];
3392 const struct {
3393 const char *str;
3394 unsigned int x;
3395 } test_data[] = {
3396 {"0", 0},
3397 {"1", 1},
3398 {"273A", 0x273a},
3399 {"FFFF", 0xffff},
3400 {"7FFFFFFF", 0x7fffffff},
3401 {"FFFFFFFF", 0xffffffff},
3402 #if UINT_MAX >= 0xffffffff
3403 {"31BC421D", 0x31bc421d},
3404 {"FFFFFFFF", 0xffffffff},
3405 #endif
3406 {NULL, 0}
3409 (void)ptr;
3411 for (i = 0; test_data[i].str != NULL; ++i) {
3412 len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
3413 tt_int_op(len,OP_NE, 0);
3414 tt_int_op(len,OP_EQ, strlen(buf));
3415 tt_str_op(buf,OP_EQ, test_data[i].str);
3418 tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
3419 tt_str_op(buf,OP_EQ, "FFFF");
3420 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
3421 tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
3423 done:
3424 return;
3428 * Test for format_hex_number_sigsafe()
3431 static void
3432 test_util_format_dec_number(void *ptr)
3434 int i, len;
3435 char buf[33];
3436 const struct {
3437 const char *str;
3438 unsigned int x;
3439 } test_data[] = {
3440 {"0", 0},
3441 {"1", 1},
3442 {"1234", 1234},
3443 {"12345678", 12345678},
3444 {"99999999", 99999999},
3445 {"100000000", 100000000},
3446 {"4294967295", 4294967295u},
3447 #if UINT_MAX > 0xffffffff
3448 {"18446744073709551615", 18446744073709551615u },
3449 #endif
3450 {NULL, 0}
3453 (void)ptr;
3455 for (i = 0; test_data[i].str != NULL; ++i) {
3456 len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
3457 tt_int_op(len,OP_NE, 0);
3458 tt_int_op(len,OP_EQ, strlen(buf));
3459 tt_str_op(buf,OP_EQ, test_data[i].str);
3461 len = format_dec_number_sigsafe(test_data[i].x, buf,
3462 (int)(strlen(test_data[i].str) + 1));
3463 tt_int_op(len,OP_EQ, strlen(buf));
3464 tt_str_op(buf,OP_EQ, test_data[i].str);
3467 tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
3468 tt_str_op(buf,OP_EQ, "7331");
3469 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
3470 tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
3471 tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
3473 done:
3474 return;
3478 * Test that we can properly format a Windows command line
3480 static void
3481 test_util_join_win_cmdline(void *ptr)
3483 /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
3484 * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
3485 * will try to only generate simple cases for the child process to parse;
3486 * i.e. we never embed quoted strings in arguments. */
3488 const char *argvs[][4] = {
3489 {"a", "bb", "CCC", NULL}, // Normal
3490 {NULL, NULL, NULL, NULL}, // Empty argument list
3491 {"", NULL, NULL, NULL}, // Empty argument
3492 {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
3493 {"a\tbc", "dd dd", "E", NULL}, // Whitespace
3494 {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
3495 {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
3496 {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
3497 { NULL } // Terminator
3500 const char *cmdlines[] = {
3501 "a bb CCC",
3503 "\"\"",
3504 "\\\"a b\\\"b CCC\\\"",
3505 "\"a\tbc\" \"dd dd\" E",
3506 "a\\\\\\b \"de fg\" H",
3507 "a\\\\\\\"b \\c D\\",
3508 "\"a\\\\b c\" d E",
3509 NULL // Terminator
3512 int i;
3513 char *joined_argv = NULL;
3515 (void)ptr;
3517 for (i=0; cmdlines[i]!=NULL; i++) {
3518 log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
3519 joined_argv = tor_join_win_cmdline(argvs[i]);
3520 tt_str_op(cmdlines[i],OP_EQ, joined_argv);
3521 tor_free(joined_argv);
3524 done:
3525 tor_free(joined_argv);
3528 #define MAX_SPLIT_LINE_COUNT 4
3529 struct split_lines_test_t {
3530 const char *orig_line; // Line to be split (may contain \0's)
3531 int orig_length; // Length of orig_line
3532 const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
3536 * Test that we properly split a buffer into lines
3538 static void
3539 test_util_split_lines(void *ptr)
3541 /* Test cases. orig_line of last test case must be NULL.
3542 * The last element of split_line[i] must be NULL. */
3543 struct split_lines_test_t tests[] = {
3544 {"", 0, {NULL}},
3545 {"foo", 3, {"foo", NULL}},
3546 {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
3547 {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
3548 {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
3549 {"line 1\r\nline 2", 14, {"line 1", "line 2", NULL}},
3550 {"line 1\r\n\r\nline 2", 16, {"line 1", "line 2", NULL}},
3551 {"line 1\r\n\r\r\r\nline 2", 18, {"line 1", "line 2", NULL}},
3552 {"line 1\r\n\n\n\n\rline 2", 18, {"line 1", "line 2", NULL}},
3553 {"line 1\r\n\r\t\r\nline 3", 18, {"line 1", ".", "line 3", NULL}},
3554 {"\n\t\r\t\nline 3", 11, {".", ".", "line 3", NULL}},
3555 {NULL, 0, { NULL }}
3558 int i, j;
3559 char *orig_line=NULL;
3560 smartlist_t *sl=NULL;
3562 (void)ptr;
3564 for (i=0; tests[i].orig_line; i++) {
3565 sl = smartlist_new();
3566 /* Allocate space for string and trailing NULL */
3567 orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
3568 tor_split_lines(sl, orig_line, tests[i].orig_length);
3570 j = 0;
3571 log_info(LD_GENERAL, "Splitting test %d of length %d",
3572 i, tests[i].orig_length);
3573 SMARTLIST_FOREACH_BEGIN(sl, const char *, line) {
3574 /* Check we have not got too many lines */
3575 tt_int_op(MAX_SPLIT_LINE_COUNT, OP_GT, j);
3576 /* Check that there actually should be a line here */
3577 tt_assert(tests[i].split_line[j] != NULL);
3578 log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
3579 j, i, tests[i].split_line[j]);
3580 /* Check that the line is as expected */
3581 tt_str_op(line,OP_EQ, tests[i].split_line[j]);
3582 j++;
3583 } SMARTLIST_FOREACH_END(line);
3584 /* Check that we didn't miss some lines */
3585 tt_ptr_op(NULL,OP_EQ, tests[i].split_line[j]);
3586 tor_free(orig_line);
3587 smartlist_free(sl);
3588 sl = NULL;
3591 done:
3592 tor_free(orig_line);
3593 smartlist_free(sl);
3596 static void
3597 test_util_di_ops(void *arg)
3599 #define LT -1
3600 #define GT 1
3601 #define EQ 0
3602 const struct {
3603 const char *a; int want_sign; const char *b;
3604 } examples[] = {
3605 { "Foo", EQ, "Foo" },
3606 { "foo", GT, "bar", },
3607 { "foobar", EQ ,"foobar" },
3608 { "foobar", LT, "foobaw" },
3609 { "foobar", GT, "f00bar" },
3610 { "foobar", GT, "boobar" },
3611 { "", EQ, "" },
3612 { NULL, 0, NULL },
3615 int i;
3617 (void)arg;
3618 for (i = 0; examples[i].a; ++i) {
3619 size_t len = strlen(examples[i].a);
3620 int eq1, eq2, neq1, neq2, cmp1, cmp2;
3621 tt_int_op(len,OP_EQ, strlen(examples[i].b));
3622 /* We do all of the operations, with operands in both orders. */
3623 eq1 = tor_memeq(examples[i].a, examples[i].b, len);
3624 eq2 = tor_memeq(examples[i].b, examples[i].a, len);
3625 neq1 = tor_memneq(examples[i].a, examples[i].b, len);
3626 neq2 = tor_memneq(examples[i].b, examples[i].a, len);
3627 cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
3628 cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
3630 /* Check for correctness of cmp1 */
3631 if (cmp1 < 0 && examples[i].want_sign != LT)
3632 TT_DIE(("Assertion failed."));
3633 else if (cmp1 > 0 && examples[i].want_sign != GT)
3634 TT_DIE(("Assertion failed."));
3635 else if (cmp1 == 0 && examples[i].want_sign != EQ)
3636 TT_DIE(("Assertion failed."));
3638 /* Check for consistency of everything else with cmp1 */
3639 tt_int_op(eq1,OP_EQ, eq2);
3640 tt_int_op(neq1,OP_EQ, neq2);
3641 tt_int_op(cmp1,OP_EQ, -cmp2);
3642 tt_int_op(eq1,OP_EQ, cmp1 == 0);
3643 tt_int_op(neq1,OP_EQ, !eq1);
3647 uint8_t zz = 0;
3648 uint8_t ii = 0;
3649 int z;
3651 /* exhaustively test tor_memeq and tor_memcmp
3652 * against each possible single-byte numeric difference
3653 * some arithmetic bugs only appear with certain bit patterns */
3654 for (z = 0; z < 256; z++) {
3655 for (i = 0; i < 256; i++) {
3656 ii = (uint8_t)i;
3657 zz = (uint8_t)z;
3658 tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
3659 tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
3660 zz > ii ? GT : EQ);
3661 tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
3662 ii < zz ? LT : EQ);
3667 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
3668 tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
3669 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
3670 tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
3671 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
3672 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
3673 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
3674 tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
3675 tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
3677 done:
3682 * Test counting high bits
3684 static void
3685 test_util_n_bits_set(void *ptr)
3687 (void)ptr;
3688 tt_int_op(0,OP_EQ, n_bits_set_u8(0));
3689 tt_int_op(1,OP_EQ, n_bits_set_u8(1));
3690 tt_int_op(3,OP_EQ, n_bits_set_u8(7));
3691 tt_int_op(1,OP_EQ, n_bits_set_u8(8));
3692 tt_int_op(2,OP_EQ, n_bits_set_u8(129));
3693 tt_int_op(8,OP_EQ, n_bits_set_u8(255));
3694 done:
3699 * Test LHS whitespace (and comment) eater
3701 static void
3702 test_util_eat_whitespace(void *ptr)
3704 const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
3705 char str[80];
3706 size_t i;
3708 (void)ptr;
3710 /* Try one leading ws */
3711 strlcpy(str, "fuubaar", sizeof(str));
3712 for (i = 0; i < sizeof(ws); ++i) {
3713 str[0] = ws[i];
3714 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
3715 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
3716 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
3717 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
3719 str[0] = '\n';
3720 tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
3721 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
3722 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
3723 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
3725 /* Empty string */
3726 strlcpy(str, "", sizeof(str));
3727 tt_ptr_op(str,OP_EQ, eat_whitespace(str));
3728 tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
3729 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
3730 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
3732 /* Only ws */
3733 strlcpy(str, " \t\r\n", sizeof(str));
3734 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
3735 tt_ptr_op(str + strlen(str),OP_EQ,
3736 eat_whitespace_eos(str, str + strlen(str)));
3737 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
3738 eat_whitespace_no_nl(str));
3739 tt_ptr_op(str + strlen(str) - 1,OP_EQ,
3740 eat_whitespace_eos_no_nl(str, str + strlen(str)));
3742 strlcpy(str, " \t\r ", sizeof(str));
3743 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
3744 tt_ptr_op(str + strlen(str),OP_EQ,
3745 eat_whitespace_eos(str, str + strlen(str)));
3746 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
3747 tt_ptr_op(str + strlen(str),OP_EQ,
3748 eat_whitespace_eos_no_nl(str, str + strlen(str)));
3750 /* Multiple ws */
3751 strlcpy(str, "fuubaar", sizeof(str));
3752 for (i = 0; i < sizeof(ws); ++i)
3753 str[i] = ws[i];
3754 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
3755 tt_ptr_op(str + sizeof(ws),OP_EQ,
3756 eat_whitespace_eos(str, str + strlen(str)));
3757 tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
3758 tt_ptr_op(str + sizeof(ws),OP_EQ,
3759 eat_whitespace_eos_no_nl(str, str + strlen(str)));
3761 /* Eat comment */
3762 strlcpy(str, "# Comment \n No Comment", sizeof(str));
3763 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
3764 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
3765 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
3766 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
3768 /* Eat comment & ws mix */
3769 strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
3770 tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
3771 tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
3772 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
3773 tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
3775 /* Eat entire comment */
3776 strlcpy(str, "#Comment", sizeof(str));
3777 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
3778 tt_ptr_op(str + strlen(str),OP_EQ,
3779 eat_whitespace_eos(str, str + strlen(str)));
3780 tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
3781 tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
3783 /* Blank line, then comment */
3784 strlcpy(str, " \t\n # Comment", sizeof(str));
3785 tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
3786 tt_ptr_op(str + strlen(str),OP_EQ,
3787 eat_whitespace_eos(str, str + strlen(str)));
3788 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
3789 tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
3791 done:
3795 /** Return a newly allocated smartlist containing the lines of text in
3796 * <b>lines</b>. The returned strings are heap-allocated, and must be
3797 * freed by the caller.
3799 * XXXX? Move to container.[hc] ? */
3800 static smartlist_t *
3801 smartlist_new_from_text_lines(const char *lines)
3803 smartlist_t *sl = smartlist_new();
3804 char *last_line;
3806 smartlist_split_string(sl, lines, "\n", 0, 0);
3808 last_line = smartlist_pop_last(sl);
3809 if (last_line != NULL && *last_line != '\0') {
3810 smartlist_add(sl, last_line);
3811 } else {
3812 tor_free(last_line);
3815 return sl;
3818 /** Test smartlist_new_from_text_lines */
3819 static void
3820 test_util_sl_new_from_text_lines(void *ptr)
3822 (void)ptr;
3824 { /* Normal usage */
3825 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
3826 int sl_len = smartlist_len(sl);
3828 tt_want_int_op(sl_len, OP_EQ, 3);
3830 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
3831 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
3832 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
3834 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
3835 smartlist_free(sl);
3838 { /* No final newline */
3839 smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
3840 int sl_len = smartlist_len(sl);
3842 tt_want_int_op(sl_len, OP_EQ, 3);
3844 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
3845 if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
3846 if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
3848 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
3849 smartlist_free(sl);
3852 { /* No newlines */
3853 smartlist_t *sl = smartlist_new_from_text_lines("foo");
3854 int sl_len = smartlist_len(sl);
3856 tt_want_int_op(sl_len, OP_EQ, 1);
3858 if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
3860 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
3861 smartlist_free(sl);
3864 { /* No text at all */
3865 smartlist_t *sl = smartlist_new_from_text_lines("");
3866 int sl_len = smartlist_len(sl);
3868 tt_want_int_op(sl_len, OP_EQ, 0);
3870 SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
3871 smartlist_free(sl);
3875 static void
3876 test_util_envnames(void *ptr)
3878 (void) ptr;
3880 tt_assert(environment_variable_names_equal("abc", "abc"));
3881 tt_assert(environment_variable_names_equal("abc", "abc="));
3882 tt_assert(environment_variable_names_equal("abc", "abc=def"));
3883 tt_assert(environment_variable_names_equal("abc=def", "abc"));
3884 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
3886 tt_assert(environment_variable_names_equal("abc", "abc"));
3887 tt_assert(environment_variable_names_equal("abc", "abc="));
3888 tt_assert(environment_variable_names_equal("abc", "abc=def"));
3889 tt_assert(environment_variable_names_equal("abc=def", "abc"));
3890 tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
3892 tt_assert(!environment_variable_names_equal("abc", "abcd"));
3893 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
3894 tt_assert(!environment_variable_names_equal("abc=", "abcd"));
3895 tt_assert(!environment_variable_names_equal("abc=", "def"));
3896 tt_assert(!environment_variable_names_equal("abc=", "def="));
3897 tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
3899 tt_assert(!environment_variable_names_equal("", "a=def"));
3900 /* A bit surprising. */
3901 tt_assert(environment_variable_names_equal("", "=def"));
3902 tt_assert(environment_variable_names_equal("=y", "=x"));
3904 done:
3908 /** Test process_environment_make */
3909 static void
3910 test_util_make_environment(void *ptr)
3912 const char *env_vars_string =
3913 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
3914 "HOME=/home/foozer\n";
3915 const char expected_windows_env_block[] =
3916 "HOME=/home/foozer\000"
3917 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
3918 "\000";
3919 size_t expected_windows_env_block_len =
3920 sizeof(expected_windows_env_block) - 1;
3922 smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
3923 smartlist_t *env_vars_sorted = smartlist_new();
3924 smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
3926 process_environment_t *env;
3928 (void)ptr;
3930 env = process_environment_make(env_vars);
3932 /* Check that the Windows environment block is correct. */
3933 tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
3934 expected_windows_env_block_len));
3936 /* Now for the Unixoid environment block. We don't care which order
3937 * these environment variables are in, so we sort both lists first. */
3939 smartlist_add_all(env_vars_sorted, env_vars);
3942 char **v;
3943 for (v = env->unixoid_environment_block; *v; ++v) {
3944 smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
3948 smartlist_sort_strings(env_vars_sorted);
3949 smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
3951 tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
3952 smartlist_len(env_vars_in_unixoid_env_block_sorted));
3954 int len = smartlist_len(env_vars_sorted);
3955 int i;
3957 if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
3958 len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
3961 for (i = 0; i < len; ++i) {
3962 tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
3963 smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
3967 /* Clean up. */
3968 smartlist_free(env_vars_in_unixoid_env_block_sorted);
3969 smartlist_free(env_vars_sorted);
3971 SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
3972 smartlist_free(env_vars);
3974 process_environment_free(env);
3977 /** Test set_environment_variable_in_smartlist */
3978 static void
3979 test_util_set_env_var_in_sl(void *ptr)
3981 /* The environment variables in these strings are in arbitrary
3982 * order; we sort the resulting lists before comparing them.
3984 * (They *will not* end up in the order shown in
3985 * expected_resulting_env_vars_string.) */
3987 const char *base_env_vars_string =
3988 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
3989 "HOME=/home/foozer\n"
3990 "TERM=xterm\n"
3991 "SHELL=/bin/ksh\n"
3992 "USER=foozer\n"
3993 "LOGNAME=foozer\n"
3994 "USERNAME=foozer\n"
3995 "LANG=en_US.utf8\n"
3998 const char *new_env_vars_string =
3999 "TERM=putty\n"
4000 "DISPLAY=:18.0\n"
4003 const char *expected_resulting_env_vars_string =
4004 "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
4005 "HOME=/home/foozer\n"
4006 "TERM=putty\n"
4007 "SHELL=/bin/ksh\n"
4008 "USER=foozer\n"
4009 "LOGNAME=foozer\n"
4010 "USERNAME=foozer\n"
4011 "LANG=en_US.utf8\n"
4012 "DISPLAY=:18.0\n"
4015 smartlist_t *merged_env_vars =
4016 smartlist_new_from_text_lines(base_env_vars_string);
4017 smartlist_t *new_env_vars =
4018 smartlist_new_from_text_lines(new_env_vars_string);
4019 smartlist_t *expected_resulting_env_vars =
4020 smartlist_new_from_text_lines(expected_resulting_env_vars_string);
4022 /* Elements of merged_env_vars are heap-allocated, and must be
4023 * freed. Some of them are (or should) be freed by
4024 * set_environment_variable_in_smartlist.
4026 * Elements of new_env_vars are heap-allocated, but are copied into
4027 * merged_env_vars, so they are not freed separately at the end of
4028 * the function.
4030 * Elements of expected_resulting_env_vars are heap-allocated, and
4031 * must be freed. */
4033 (void)ptr;
4035 SMARTLIST_FOREACH(new_env_vars, char *, env_var,
4036 set_environment_variable_in_smartlist(merged_env_vars,
4037 env_var,
4038 tor_free_,
4039 1));
4041 smartlist_sort_strings(merged_env_vars);
4042 smartlist_sort_strings(expected_resulting_env_vars);
4044 tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
4045 smartlist_len(expected_resulting_env_vars));
4047 int len = smartlist_len(merged_env_vars);
4048 int i;
4050 if (smartlist_len(expected_resulting_env_vars) < len) {
4051 len = smartlist_len(expected_resulting_env_vars);
4054 for (i = 0; i < len; ++i) {
4055 tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
4056 smartlist_get(expected_resulting_env_vars, i));
4060 /* Clean up. */
4061 SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
4062 smartlist_free(merged_env_vars);
4064 smartlist_free(new_env_vars);
4066 SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
4067 smartlist_free(expected_resulting_env_vars);
4070 static void
4071 test_util_weak_random(void *arg)
4073 int i, j, n[16];
4074 tor_weak_rng_t rng;
4075 (void) arg;
4077 tor_init_weak_random(&rng, (unsigned)time(NULL));
4079 for (i = 1; i <= 256; ++i) {
4080 for (j=0;j<100;++j) {
4081 int r = tor_weak_random_range(&rng, i);
4082 tt_int_op(0, OP_LE, r);
4083 tt_int_op(r, OP_LT, i);
4087 memset(n,0,sizeof(n));
4088 for (j=0;j<8192;++j) {
4089 n[tor_weak_random_range(&rng, 16)]++;
4092 for (i=0;i<16;++i)
4093 tt_int_op(n[i], OP_GT, 0);
4094 done:
4098 static void
4099 test_util_mathlog(void *arg)
4101 double d;
4102 (void) arg;
4104 d = tor_mathlog(2.718281828);
4105 tt_double_op(fabs(d - 1.0), OP_LT, .000001);
4106 d = tor_mathlog(10);
4107 tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
4108 done:
4112 static void
4113 test_util_round_to_next_multiple_of(void *arg)
4115 (void)arg;
4117 tt_u64_op(round_uint64_to_next_multiple_of(0,1), ==, 0);
4118 tt_u64_op(round_uint64_to_next_multiple_of(0,7), ==, 0);
4120 tt_u64_op(round_uint64_to_next_multiple_of(99,1), ==, 99);
4121 tt_u64_op(round_uint64_to_next_multiple_of(99,7), ==, 105);
4122 tt_u64_op(round_uint64_to_next_multiple_of(99,9), ==, 99);
4124 tt_i64_op(round_int64_to_next_multiple_of(0,1), ==, 0);
4125 tt_i64_op(round_int64_to_next_multiple_of(0,7), ==, 0);
4127 tt_i64_op(round_int64_to_next_multiple_of(99,1), ==, 99);
4128 tt_i64_op(round_int64_to_next_multiple_of(99,7), ==, 105);
4129 tt_i64_op(round_int64_to_next_multiple_of(99,9), ==, 99);
4131 tt_i64_op(round_int64_to_next_multiple_of(-99,1), ==, -99);
4132 tt_i64_op(round_int64_to_next_multiple_of(-99,7), ==, -98);
4133 tt_i64_op(round_int64_to_next_multiple_of(-99,9), ==, -99);
4135 tt_i64_op(round_int64_to_next_multiple_of(INT64_MIN,2), ==, INT64_MIN);
4136 tt_i64_op(round_int64_to_next_multiple_of(INT64_MAX,2), ==,
4137 INT64_MAX-INT64_MAX%2);
4138 done:
4142 static void
4143 test_util_laplace(void *arg)
4145 /* Sample values produced using Python's SciPy:
4147 * >>> from scipy.stats import laplace
4148 * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
4149 ... loc = 24, scale = 24)
4150 * array([ nan, -inf, -69.88855213, 24. ,
4151 * 24.48486498, 117.88855213, inf, nan])
4153 const double mu = 24.0, b = 24.0;
4154 const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
4155 (void)arg;
4157 tt_i64_op(INT64_MIN, ==, sample_laplace_distribution(mu, b, 0.0));
4158 tt_i64_op(-69, ==, sample_laplace_distribution(mu, b, 0.01));
4159 tt_i64_op(24, ==, sample_laplace_distribution(mu, b, 0.5));
4160 tt_i64_op(24, ==, sample_laplace_distribution(mu, b, 0.51));
4161 tt_i64_op(117, ==, sample_laplace_distribution(mu, b, 0.99));
4163 /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
4164 * ... loc = 0, scale = 50)
4165 * array([ -inf, -80.47189562, -34.65735903, 0. ,
4166 * 34.65735903, 80.47189562, 195.60115027])
4168 tt_i64_op(INT64_MIN + 20, ==,
4169 add_laplace_noise(20, 0.0, delta_f, epsilon));
4170 tt_i64_op(-60, ==, add_laplace_noise(20, 0.1, delta_f, epsilon));
4171 tt_i64_op(-14, ==, add_laplace_noise(20, 0.25, delta_f, epsilon));
4172 tt_i64_op(20, ==, add_laplace_noise(20, 0.5, delta_f, epsilon));
4173 tt_i64_op(54, ==, add_laplace_noise(20, 0.75, delta_f, epsilon));
4174 tt_i64_op(100, ==, add_laplace_noise(20, 0.9, delta_f, epsilon));
4175 tt_i64_op(215, ==, add_laplace_noise(20, 0.99, delta_f, epsilon));
4177 done:
4181 static void
4182 test_util_strclear(void *arg)
4184 static const char *vals[] = { "", "a", "abcdef", "abcdefgh", NULL };
4185 int i;
4186 char *v = NULL;
4187 (void)arg;
4189 for (i = 0; vals[i]; ++i) {
4190 size_t n;
4191 v = tor_strdup(vals[i]);
4192 n = strlen(v);
4193 tor_strclear(v);
4194 tt_assert(tor_mem_is_zero(v, n+1));
4195 tor_free(v);
4197 done:
4198 tor_free(v);
4201 #define UTIL_LEGACY(name) \
4202 { #name, test_util_ ## name , 0, NULL, NULL }
4204 #define UTIL_TEST(name, flags) \
4205 { #name, test_util_ ## name, flags, NULL, NULL }
4207 #ifdef FD_CLOEXEC
4208 #define CAN_CHECK_CLOEXEC
4209 static int
4210 fd_is_cloexec(tor_socket_t fd)
4212 int flags = fcntl(fd, F_GETFD, 0);
4213 return (flags & FD_CLOEXEC) == FD_CLOEXEC;
4215 #endif
4217 #ifndef _WIN32
4218 #define CAN_CHECK_NONBLOCK
4219 static int
4220 fd_is_nonblocking(tor_socket_t fd)
4222 int flags = fcntl(fd, F_GETFL, 0);
4223 return (flags & O_NONBLOCK) == O_NONBLOCK;
4225 #endif
4227 static void
4228 test_util_socket(void *arg)
4230 tor_socket_t fd1 = TOR_INVALID_SOCKET;
4231 tor_socket_t fd2 = TOR_INVALID_SOCKET;
4232 tor_socket_t fd3 = TOR_INVALID_SOCKET;
4233 tor_socket_t fd4 = TOR_INVALID_SOCKET;
4234 int n = get_n_open_sockets();
4236 TT_BLATHER(("Starting with %d open sockets.", n));
4238 (void)arg;
4240 fd1 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 0, 0);
4241 fd2 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 0, 1);
4242 tt_assert(SOCKET_OK(fd1));
4243 tt_assert(SOCKET_OK(fd2));
4244 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
4245 //fd3 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 1, 0);
4246 //fd4 = tor_open_socket_with_extensions(AF_INET, SOCK_STREAM, 0, 1, 1);
4247 fd3 = tor_open_socket(AF_INET, SOCK_STREAM, 0);
4248 fd4 = tor_open_socket_nonblocking(AF_INET, SOCK_STREAM, 0);
4249 tt_assert(SOCKET_OK(fd3));
4250 tt_assert(SOCKET_OK(fd4));
4251 tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
4253 #ifdef CAN_CHECK_CLOEXEC
4254 tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
4255 tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
4256 tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
4257 tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
4258 #endif
4259 #ifdef CAN_CHECK_NONBLOCK
4260 tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
4261 tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
4262 tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
4263 tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
4264 #endif
4266 tor_close_socket(fd1);
4267 tor_close_socket(fd2);
4268 fd1 = fd2 = TOR_INVALID_SOCKET;
4269 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
4270 tor_close_socket(fd3);
4271 tor_close_socket(fd4);
4272 fd3 = fd4 = TOR_INVALID_SOCKET;
4273 tt_int_op(get_n_open_sockets(), OP_EQ, n);
4275 done:
4276 if (SOCKET_OK(fd1))
4277 tor_close_socket(fd1);
4278 if (SOCKET_OK(fd2))
4279 tor_close_socket(fd2);
4280 if (SOCKET_OK(fd3))
4281 tor_close_socket(fd3);
4282 if (SOCKET_OK(fd4))
4283 tor_close_socket(fd4);
4286 /* Test for socketpair and ersatz_socketpair(). We test them both, since
4287 * the latter is a tolerably good way to exersize tor_accept_socket(). */
4288 static void
4289 test_util_socketpair(void *arg)
4291 const int ersatz = !strcmp(arg, "1");
4292 int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
4293 ersatz ? tor_ersatz_socketpair : tor_socketpair;
4294 int n = get_n_open_sockets();
4295 tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
4296 const int family = AF_UNIX;
4298 tt_int_op(0, OP_EQ, tor_socketpair_fn(family, SOCK_STREAM, 0, fds));
4299 tt_assert(SOCKET_OK(fds[0]));
4300 tt_assert(SOCKET_OK(fds[1]));
4301 tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
4302 #ifdef CAN_CHECK_CLOEXEC
4303 tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, 1);
4304 tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, 1);
4305 #endif
4306 #ifdef CAN_CHECK_NONBLOCK
4307 tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
4308 tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
4309 #endif
4311 done:
4312 if (SOCKET_OK(fds[0]))
4313 tor_close_socket(fds[0]);
4314 if (SOCKET_OK(fds[1]))
4315 tor_close_socket(fds[1]);
4318 static void
4319 test_util_max_mem(void *arg)
4321 size_t memory1, memory2;
4322 int r, r2;
4323 (void) arg;
4325 r = get_total_system_memory(&memory1);
4326 r2 = get_total_system_memory(&memory2);
4327 tt_int_op(r, OP_EQ, r2);
4328 tt_uint_op(memory2, OP_EQ, memory1);
4330 TT_BLATHER(("System memory: "U64_FORMAT, U64_PRINTF_ARG(memory1)));
4332 if (r==0) {
4333 /* You have at least a megabyte. */
4334 tt_uint_op(memory1, OP_GT, (1<<20));
4335 } else {
4336 /* You do not have a petabyte. */
4337 #if SIZEOF_SIZE_T == SIZEOF_UINT64_T
4338 tt_u64_op(memory1, OP_LT, (U64_LITERAL(1)<<50));
4339 #endif
4342 done:
4346 static void
4347 test_util_hostname_validation(void *arg)
4349 (void)arg;
4351 // Lets try valid hostnames first.
4352 tt_assert(string_is_valid_hostname("torproject.org"));
4353 tt_assert(string_is_valid_hostname("ocw.mit.edu"));
4354 tt_assert(string_is_valid_hostname("i.4cdn.org"));
4355 tt_assert(string_is_valid_hostname("stanford.edu"));
4356 tt_assert(string_is_valid_hostname("multiple-words-with-hypens.jp"));
4358 // Subdomain name cannot start with '-'.
4359 tt_assert(!string_is_valid_hostname("-torproject.org"));
4360 tt_assert(!string_is_valid_hostname("subdomain.-domain.org"));
4361 tt_assert(!string_is_valid_hostname("-subdomain.domain.org"));
4363 // Hostnames cannot contain non-alphanumeric characters.
4364 tt_assert(!string_is_valid_hostname("%%domain.\\org."));
4365 tt_assert(!string_is_valid_hostname("***x.net"));
4366 tt_assert(!string_is_valid_hostname("___abc.org"));
4367 tt_assert(!string_is_valid_hostname("\xff\xffxyz.org"));
4368 tt_assert(!string_is_valid_hostname("word1 word2.net"));
4370 // XXX: do we allow single-label DNS names?
4372 done:
4373 return;
4376 static void
4377 test_util_ipv4_validation(void *arg)
4379 (void)arg;
4381 tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
4382 tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
4384 tt_assert(!string_is_valid_ipv4_address("abcd"));
4385 tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
4386 tt_assert(!string_is_valid_ipv4_address("8.8."));
4388 done:
4389 return;
4392 struct testcase_t util_tests[] = {
4393 UTIL_LEGACY(time),
4394 UTIL_TEST(parse_http_time, 0),
4395 UTIL_LEGACY(config_line),
4396 UTIL_LEGACY(config_line_quotes),
4397 UTIL_LEGACY(config_line_comment_character),
4398 UTIL_LEGACY(config_line_escaped_content),
4399 #ifndef _WIN32
4400 UTIL_LEGACY(expand_filename),
4401 #endif
4402 UTIL_LEGACY(escape_string_socks),
4403 UTIL_LEGACY(string_is_key_value),
4404 UTIL_LEGACY(strmisc),
4405 UTIL_LEGACY(pow2),
4406 UTIL_LEGACY(gzip),
4407 UTIL_LEGACY(datadir),
4408 #ifdef ENABLE_MEMPOOLS
4409 UTIL_LEGACY(mempool),
4410 #endif
4411 UTIL_LEGACY(memarea),
4412 UTIL_LEGACY(control_formats),
4413 UTIL_LEGACY(mmap),
4414 UTIL_LEGACY(sscanf),
4415 UTIL_LEGACY(format_time_interval),
4416 UTIL_LEGACY(path_is_relative),
4417 UTIL_LEGACY(strtok),
4418 UTIL_LEGACY(di_ops),
4419 UTIL_TEST(round_to_next_multiple_of, 0),
4420 UTIL_TEST(laplace, 0),
4421 UTIL_TEST(strclear, 0),
4422 UTIL_TEST(find_str_at_start_of_line, 0),
4423 UTIL_TEST(string_is_C_identifier, 0),
4424 UTIL_TEST(asprintf, 0),
4425 UTIL_TEST(listdir, 0),
4426 UTIL_TEST(parent_dir, 0),
4427 UTIL_TEST(ftruncate, 0),
4428 #ifdef _WIN32
4429 UTIL_TEST(load_win_lib, 0),
4430 #endif
4431 #ifndef _WIN32
4432 UTIL_TEST(exit_status, 0),
4433 UTIL_TEST(fgets_eagain, 0),
4434 #endif
4435 UTIL_TEST(format_hex_number, 0),
4436 UTIL_TEST(format_dec_number, 0),
4437 UTIL_TEST(join_win_cmdline, 0),
4438 UTIL_TEST(split_lines, 0),
4439 UTIL_TEST(n_bits_set, 0),
4440 UTIL_TEST(eat_whitespace, 0),
4441 UTIL_TEST(sl_new_from_text_lines, 0),
4442 UTIL_TEST(envnames, 0),
4443 UTIL_TEST(make_environment, 0),
4444 UTIL_TEST(set_env_var_in_sl, 0),
4445 UTIL_TEST(read_file_eof_tiny_limit, 0),
4446 UTIL_TEST(read_file_eof_one_loop_a, 0),
4447 UTIL_TEST(read_file_eof_one_loop_b, 0),
4448 UTIL_TEST(read_file_eof_two_loops, 0),
4449 UTIL_TEST(read_file_eof_two_loops_b, 0),
4450 UTIL_TEST(read_file_eof_zero_bytes, 0),
4451 UTIL_TEST(write_chunks_to_file, 0),
4452 UTIL_TEST(mathlog, 0),
4453 UTIL_TEST(weak_random, 0),
4454 UTIL_TEST(socket, TT_FORK),
4455 { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
4456 (void*)"0" },
4457 { "socketpair_ersatz", test_util_socketpair, TT_FORK,
4458 &passthrough_setup, (void*)"1" },
4459 UTIL_TEST(max_mem, 0),
4460 UTIL_TEST(hostname_validation, 0),
4461 UTIL_TEST(ipv4_validation, 0),
4462 END_OF_TESTCASES