test_util.c 216 KB
Newer Older
1
2
/* Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3
 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4
5
6
/* See LICENSE for licensing information */

#include "orconfig.h"
Nick Mathewson's avatar
Nick Mathewson committed
7
#define COMPAT_TIME_PRIVATE
8
#define UTIL_MALLOC_PRIVATE
9
#define PROCESS_WIN32_PRIVATE
10
#include "lib/testsupport/testsupport.h"
11
#include "core/or/or.h"
12
#include "lib/buf/buffers.h"
13
14
#include "app/config/config.h"
#include "feature/control/control.h"
15
#include "feature/control/control_proto.h"
16
#include "feature/client/transports.h"
17
#include "lib/crypt_ops/crypto_format.h"
18
#include "lib/crypt_ops/crypto_rand.h"
19
#include "lib/defs/time.h"
Nick Mathewson's avatar
Nick Mathewson committed
20
#include "test/test.h"
21
#include "test/test_helpers.h"
22
#include "lib/memarea/memarea.h"
23
#include "lib/process/waitpid.h"
24
#include "lib/process/process_win32.h"
Nick Mathewson's avatar
Nick Mathewson committed
25
#include "test/log_test_helpers.h"
26
#include "lib/compress/compress.h"
27
#include "lib/compress/compress_zstd.h"
28
#include "lib/encoding/keyval.h"
29
#include "lib/fdio/fdio.h"
30
#include "lib/fs/winlib.h"
31
32
#include "lib/process/env.h"
#include "lib/process/pidfile.h"
Nick Mathewson's avatar
Nick Mathewson committed
33
#include "lib/intmath/weakrng.h"
34
#include "lib/intmath/muldiv.h"
35
#include "lib/thread/numcpus.h"
36
37
#include "lib/math/fp.h"
#include "lib/math/laplace.h"
38
#include "lib/meminfo/meminfo.h"
39
#include "lib/time/tvdiff.h"
40
#include "lib/encoding/confline.h"
41
#include "lib/net/socketpair.h"
42
#include "lib/malloc/map_anon.h"
43

44
45
46
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
Nick Mathewson's avatar
Nick Mathewson committed
47
48
49
50
51
52
#ifdef HAVE_SYS_UTIME_H
#include <sys/utime.h>
#endif
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
53
54
55
56
57
58
59
60
61
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
62
63
64
65
66
67
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
68

69
70
71
#ifdef _WIN32
#include <tchar.h>
#endif
72
#include <math.h>
73
#include <ctype.h>
74
#include <float.h>
75

76
77
78
79
80
/* These platforms don't have meaningful pwdb or homedirs. */
#if defined(_WIN32) || defined(__ANDROID__)
#define DISABLE_PWDB_TESTS
#endif

81
82
static void set_file_mtime(const char *fname, time_t when);

83
84
85
#define INFINITY_DBL ((double)INFINITY)
#define NAN_DBL ((double)NAN)

George Kadianakis's avatar
George Kadianakis committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/** Test the tor_isinf() wrapper */
static void
test_tor_isinf(void *arg)
{
  (void) arg;

  tt_assert(tor_isinf(INFINITY_DBL));

  tt_assert(!tor_isinf(NAN_DBL));
  tt_assert(!tor_isinf(DBL_EPSILON));
  tt_assert(!tor_isinf(DBL_MAX));
  tt_assert(!tor_isinf(DBL_MIN));

  tt_assert(!tor_isinf(0.0));
  tt_assert(!tor_isinf(0.1));
  tt_assert(!tor_isinf(3));
  tt_assert(!tor_isinf(3.14));

 done:
  ;
}

108
109
110
111
112
113
114
115
116
117
118
119
120
/* XXXX this is a minimal wrapper to make the unit tests compile with the
 * changed tor_timegm interface. */
static time_t
tor_timegm_wrapper(const struct tm *tm)
{
  time_t t;
  if (tor_timegm(tm, &t) < 0)
    return -1;
  return t;
}

#define tor_timegm tor_timegm_wrapper

meejah's avatar
meejah committed
121
static void
122
123
test_util_read_until_eof_impl(const char *fname, size_t file_len,
                              size_t read_limit)
meejah's avatar
meejah committed
124
125
{
  char *fifo_name = NULL;
126
  char *test_str = NULL;
meejah's avatar
meejah committed
127
  char *str = NULL;
128
  size_t sz = 9999999;
meejah's avatar
meejah committed
129
  int fd = -1;
130
  int r;
meejah's avatar
meejah committed
131

132
133
134
  fifo_name = tor_strdup(get_fname(fname));
  test_str = tor_malloc(file_len);
  crypto_rand(test_str, file_len);
meejah's avatar
meejah committed
135

136
  r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
137
  tt_int_op(r, OP_EQ, 0);
138
139

  fd = open(fifo_name, O_RDONLY|O_BINARY);
140
  tt_int_op(fd, OP_GE, 0);
141
  str = read_file_to_str_until_eof(fd, read_limit, &sz);
142
  tt_ptr_op(str, OP_NE, NULL);
meejah's avatar
meejah committed
143

144
  if (read_limit < file_len)
145
    tt_int_op(sz, OP_EQ, read_limit);
146
  else
147
    tt_int_op(sz, OP_EQ, file_len);
meejah's avatar
meejah committed
148

149
150
  tt_mem_op(test_str, OP_EQ, str, sz);
  tt_int_op(str[sz], OP_EQ, '\0');
meejah's avatar
meejah committed
151
152
153
154

 done:
  unlink(fifo_name);
  tor_free(fifo_name);
155
  tor_free(test_str);
meejah's avatar
meejah committed
156
  tor_free(str);
157
158
  if (fd >= 0)
    close(fd);
meejah's avatar
meejah committed
159
160
161
}

static void
162
test_util_read_file_eof_tiny_limit(void *arg)
meejah's avatar
meejah committed
163
164
{
  (void)arg;
165
166
  // purposely set limit shorter than what we wrote to the FIFO to
  // test the maximum, and that it puts the NUL in the right spot
meejah's avatar
meejah committed
167

168
169
  test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
}
meejah's avatar
meejah committed
170

171
172
173
174
175
176
177
178
179
180
181
182
183
184
static void
test_util_read_file_eof_one_loop_a(void *arg)
{
  (void)arg;
  test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
}

static void
test_util_read_file_eof_one_loop_b(void *arg)
{
  (void)arg;
  test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
}

185
186
187
188
static void
test_util_read_file_eof_two_loops(void *arg)
{
  (void)arg;
meejah's avatar
meejah committed
189
190
191
192
  // write more than 1024 bytes to the FIFO to test two passes through
  // the loop in the method; if the re-alloc size is changed this
  // should be updated as well.

193
  test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
meejah's avatar
meejah committed
194
195
}

196
197
198
199
200
201
202
203
static void
test_util_read_file_eof_two_loops_b(void *arg)
{
  (void)arg;

  test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
}

meejah's avatar
meejah committed
204
static void
205
test_util_read_file_eof_zero_bytes(void *arg)
meejah's avatar
meejah committed
206
207
208
{
  (void)arg;
  // zero-byte fifo
209
  test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
meejah's avatar
meejah committed
210
211
}

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
static void
test_util_read_file_endlines(void *arg)
{
  (void)arg;

  char *fname = NULL;
  char *read_content = NULL;
  int r = -1;

  /* Write a file that contains both \n and \r\n as line ending. */
  const char *file_content = "foo bar\n"
                             "foo bar baz\r\n"
                             "foo bar\r\n";

  const char *expected_file_content = "foo bar\n"
                                      "foo bar baz\n"
                                      "foo bar\n";

  fname = tor_strdup(get_fname("file_with_crlf_ending"));

  r = write_bytes_to_file(fname, file_content, strlen(file_content), 1);
  tt_int_op(r, OP_EQ, 0);

  /* Read the file in text mode: we strip \r's from the files on both Windows
   * and UNIX. */
  read_content = read_file_to_str(fname, 0, NULL);

  tt_ptr_op(read_content, OP_NE, NULL);
  tt_int_op(strlen(read_content), OP_EQ, strlen(expected_file_content));
  tt_str_op(read_content, OP_EQ, expected_file_content);

  tor_free(read_content);

  /* Read the file in binary mode: we should preserve the \r here. */
  read_content = read_file_to_str(fname, RFTS_BIN, NULL);

  tt_ptr_op(read_content, OP_NE, NULL);
  tt_int_op(strlen(read_content), OP_EQ, strlen(file_content));
  tt_str_op(read_content, OP_EQ, file_content);

  tor_free(read_content);

 done:
  unlink(fname);
  tor_free(fname);
  tor_free(read_content);
}

260
/* Test the basic expected behaviour for write_chunks_to_file.
261
262
 * NOTE: This will need to be updated if we ever change the tempfile location
 * or extension */
263
264
265
static void
test_util_write_chunks_to_file(void *arg)
{
266
267
268
  char *fname = NULL;
  char *tempname = NULL;
  char *str = NULL;
269
  int r;
270
  struct stat st;
271
272

  /* These should be two different sizes to ensure the data is different
273
   * between the data file and the temp file's 'known string' */
274
275
  int temp_str_len = 1024;
  int data_str_len = 512;
276
277
  char *data_str = tor_malloc(data_str_len);
  char *temp_str = tor_malloc(temp_str_len);
278
279
280
281

  smartlist_t *chunks = smartlist_new();
  sized_chunk_t c = {data_str, data_str_len/2};
  sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
282
283
284
285
286
287
288
  (void)arg;

  crypto_rand(temp_str, temp_str_len);
  crypto_rand(data_str, data_str_len);

  // Ensure it can write multiple chunks

289
290
291
292
293
294
  smartlist_add(chunks, &c);
  smartlist_add(chunks, &c2);

  /*
  * Check if it writes using a tempfile
  */
295
  fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
296
297
298
299
  tor_asprintf(&tempname, "%s.tmp", fname);

  // write a known string to a file where the tempfile will be
  r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
300
  tt_int_op(r, OP_EQ, 0);
301
302
303

  // call write_chunks_to_file
  r = write_chunks_to_file(fname, chunks, 1, 0);
304
  tt_int_op(r, OP_EQ, 0);
305
306

  // assert the file has been written (expected size)
307
  str = read_file_to_str(fname, RFTS_BIN, &st);
308
  tt_assert(str != NULL);
309
310
  tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
  tt_mem_op(data_str, OP_EQ, str, data_str_len);
311
312
313
  tor_free(str);

  // assert that the tempfile is removed (should not leave artifacts)
314
  str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
315
316
317
318
  tt_assert(str == NULL);

  // Remove old testfile for second test
  r = unlink(fname);
319
  tt_int_op(r, OP_EQ, 0);
320
321
322
323
324
325
  tor_free(fname);
  tor_free(tempname);

  /*
  *  Check if it skips using a tempfile with flags
  */
326
  fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
327
328
329
330
  tor_asprintf(&tempname, "%s.tmp", fname);

  // write a known string to a file where the tempfile will be
  r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
331
  tt_int_op(r, OP_EQ, 0);
332
333
334

  // call write_chunks_to_file with no_tempfile = true
  r = write_chunks_to_file(fname, chunks, 1, 1);
335
  tt_int_op(r, OP_EQ, 0);
336
337

  // assert the file has been written (expected size)
338
  str = read_file_to_str(fname, RFTS_BIN, &st);
339
  tt_assert(str != NULL);
340
341
  tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
  tt_mem_op(data_str, OP_EQ, str, data_str_len);
342
343
344
  tor_free(str);

  // assert the tempfile still contains the known string
345
  str = read_file_to_str(tempname, RFTS_BIN, &st);
346
  tt_assert(str != NULL);
347
348
  tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
  tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
349
350
351
352
353
354
355
356
357
358

 done:
  unlink(fname);
  unlink(tempname);
  smartlist_free(chunks);
  tor_free(fname);
  tor_free(tempname);
  tor_free(str);
  tor_free(data_str);
  tor_free(temp_str);
359
360
}

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
/* Test write_str_to_file_if_not_equal(). */
static void
test_util_write_str_if_changed(void *arg)
{
  (void)arg;
  char *fname = tor_strdup(get_fname("write_if_changed"));
  char *s = NULL;
  int rv;
  const char str1[] = "The wombat lives across the seas";
  const char str2[] = "Among the far Antipodes"; /* -- Ogden Nash */

  /* We can create files. */
  rv = write_str_to_file_if_not_equal(fname, str1);
  tt_int_op(rv, OP_EQ, 0);
  s = read_file_to_str(fname, 0, NULL);
  tt_str_op(s, OP_EQ, str1);
  tor_free(s);

  /* We can replace files. */
  rv = write_str_to_file_if_not_equal(fname, str2);
  tt_int_op(rv, OP_EQ, 0);
  s = read_file_to_str(fname, 0, NULL);
  tt_str_op(s, OP_EQ, str2);
  tor_free(s);

  /* Make sure we don't replace files when they're equal. (That's the whole
   * point of the function we're testing. */
  /* First, change the mtime of the file so that we can tell whether we
   * replaced it. */
  const time_t now = time(NULL);
  const time_t five_sec_ago = now - 5;
  set_file_mtime(fname, five_sec_ago);
  rv = write_str_to_file_if_not_equal(fname, str2);
  tt_int_op(rv, OP_EQ, 0);
  /* Make sure that the file's mtime is unchanged... */
  struct stat st;
  rv = stat(fname, &st);
  tt_int_op(rv, OP_EQ, 0);
  tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
  /* And make sure its contents are unchanged. */
  s = read_file_to_str(fname, 0, NULL);
  tt_str_op(s, OP_EQ, str2);
  tor_free(s);

 done:
  tor_free(fname);
  tor_free(s);
}

410
#ifndef COCCI
411
#define _TFE(a, b, f)  tt_int_op((a).f, OP_EQ, (b).f)
412
413
414
415
416
417
418
419
420
421
422
/** test the minimum set of struct tm fields needed for a unique epoch value
 * this is also the set we use to test tor_timegm */
#define TM_EQUAL(a, b)           \
          TT_STMT_BEGIN          \
            _TFE(a, b, tm_year); \
            _TFE(a, b, tm_mon ); \
            _TFE(a, b, tm_mday); \
            _TFE(a, b, tm_hour); \
            _TFE(a, b, tm_min ); \
            _TFE(a, b, tm_sec ); \
          TT_STMT_END
Nick Mathewson's avatar
Nick Mathewson committed
423
#endif /* !defined(COCCI) */
424

425
static void
426
test_util_time(void *arg)
427
428
{
  struct timeval start, end;
429
  struct tm a_time, b_time;
430
  char timestr[128];
431
432
  time_t t_res;
  int i;
433
  struct timeval tv;
434

435
  /* Test tv_udiff and tv_mdiff */
436

437
  (void)arg;
438
439
440
441
442
443
  start.tv_sec = 5;
  start.tv_usec = 5000;

  end.tv_sec = 5;
  end.tv_usec = 5000;

444
  tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
445
  tt_int_op(0L,OP_EQ, tv_mdiff(&start, &end));
446
447
  tt_int_op(0L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(0L,OP_EQ, tv_mdiff(&end, &start));
448
449
450

  end.tv_usec = 7000;

451
  tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
452
  tt_int_op(2L,OP_EQ, tv_mdiff(&start, &end));
453
454
  tt_int_op(-2000L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-2L,OP_EQ, tv_mdiff(&end, &start));
455
456
457

  end.tv_sec = 6;

458
  tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
459
  tt_int_op(1002L,OP_EQ, tv_mdiff(&start, &end));
460
461
  tt_int_op(-1002000L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-1002L,OP_EQ, tv_mdiff(&end, &start));
462
463
464

  end.tv_usec = 0;

465
  tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
466
  tt_int_op(995L,OP_EQ, tv_mdiff(&start, &end));
467
468
  tt_int_op(-995000L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-995L,OP_EQ, tv_mdiff(&end, &start));
469
470
471

  end.tv_sec = 4;

472
  tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
473
  tt_int_op(-1005L,OP_EQ, tv_mdiff(&start, &end));
474
475
476
  tt_int_op(1005000L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(1005L,OP_EQ, tv_mdiff(&end, &start));

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
  /* Negative tv_sec values, these will break on platforms where tv_sec is
   * unsigned */

  end.tv_sec = -10;

  tt_int_op(-15005000L,OP_EQ, tv_udiff(&start, &end));
  tt_int_op(-15005L,OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(15005000L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(15005L,OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = -100;

  tt_int_op(89995000L,OP_EQ, tv_udiff(&start, &end));
  tt_int_op(89995L,OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(-89995000L,OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-89995L,OP_EQ, tv_mdiff(&end, &start));

494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  /* Test that tv_usec values round away from zero when converted to msec */
  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = 10;
  end.tv_usec = 499;

  tt_int_op(10000499L, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(10000L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(-10000499L, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = 10;
  end.tv_usec = 500;

  tt_int_op(10000500L, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(-10000500L, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = 10;
  end.tv_usec = 501;

  tt_int_op(10000501L, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(-10000501L, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-10001L, OP_EQ, tv_mdiff(&end, &start));

  /* Overflow conditions */
526

527
528
#ifdef _WIN32
  /* Would you believe that tv_sec is a long on windows? Of course you would.*/
529
530
#define TV_SEC_MAX LONG_MAX
#define TV_SEC_MIN LONG_MIN
531
#else
532
533
534
535
536
537
  /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
   * Which means TIME_MAX is not actually the maximum value of tv_sec.
   * But that's ok for the moment, because the code correctly performs 64-bit
   * calculations internally, then catches the overflow. */
#define TV_SEC_MAX TIME_MAX
#define TV_SEC_MIN TIME_MIN
538
#endif /* defined(_WIN32) */
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745

/* Assume tv_usec is an unsigned integer until proven otherwise */
#define TV_USEC_MAX UINT_MAX

  /* Overflows in the result type */

  /* All comparisons work */
  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = LONG_MAX/1000 - 2;
  end.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = LONG_MAX/1000000 - 1;
  end.tv_usec = 0;

  tt_int_op(end.tv_sec*1000000L, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(-end.tv_sec*1000000L, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));

  /* No comparisons work */
  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = LONG_MAX/1000 + 1;
  end.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = LONG_MAX/1000000 + 1;
  end.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = LONG_MAX/1000;
  end.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = 0;
  start.tv_usec = 0;
  end.tv_sec = LONG_MAX/1000000;
  end.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op((end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(-(end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&end, &start));

  /* Overflows on comparison to zero */

  start.tv_sec = 0;
  start.tv_usec = 0;

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = 0;
  end.tv_usec = TV_USEC_MAX;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = TV_USEC_MAX;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = 0;
  end.tv_usec = 0;

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = TV_USEC_MAX;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  /* overflows on comparison to maxima / minima */

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = 0;

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = 0;

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  /* overflows on comparison to maxima / minima with extra usec */

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = TOR_USEC_PER_SEC;

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = TOR_USEC_PER_SEC;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  end.tv_sec = TV_SEC_MAX;
  end.tv_usec = TOR_USEC_PER_SEC;

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = 0;

  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));

  start.tv_sec = TV_SEC_MIN;
  start.tv_usec = TOR_USEC_PER_SEC;

746
747
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
748
749
  tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
  tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
750

751
  /* Test tor_timegm & tor_gmtime_r */
752
753

  /* The test values here are confirmed to be correct on a platform
754
755
756
757
758
759
760
761
762
763
   * with a working timegm & gmtime_r. */

  /* Start with known-zero a_time and b_time.
   * This avoids passing uninitialised values to TM_EQUAL in a_time.
   * Zeroing may not be needed for b_time, as long as tor_gmtime_r
   * never reads the existing values in the structure.
   * But we really don't want intermittently failing tests. */
  memset(&a_time, 0, sizeof(struct tm));
  memset(&b_time, 0, sizeof(struct tm));

764
765
766
767
768
769
  a_time.tm_year = 2003-1900;
  a_time.tm_mon = 7;
  a_time.tm_mday = 30;
  a_time.tm_hour = 6;
  a_time.tm_min = 14;
  a_time.tm_sec = 55;
770
  t_res = 1062224095UL;
771
  tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
772
773
774
  tor_gmtime_r(&t_res, &b_time);
  TM_EQUAL(a_time, b_time);

775
  a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
776
  t_res = 1093846495UL;
777
  tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
778
779
780
  tor_gmtime_r(&t_res, &b_time);
  TM_EQUAL(a_time, b_time);

781
782
  a_time.tm_mon = 1;          /* Try a leap year, in feb. */
  a_time.tm_mday = 10;
783
  t_res = 1076393695UL;
784
  tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
785
786
787
  tor_gmtime_r(&t_res, &b_time);
  TM_EQUAL(a_time, b_time);

788
  a_time.tm_mon = 0;
789
  t_res = 1073715295UL;
790
  tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
791
792
793
  tor_gmtime_r(&t_res, &b_time);
  TM_EQUAL(a_time, b_time);

794
795
796
797
798
799
800
801
802
803
804
  /* This value is in range with 32 bit and 64 bit time_t */
  a_time.tm_year = 2037-1900;
  t_res = 2115180895UL;
  tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
  tor_gmtime_r(&t_res, &b_time);
  TM_EQUAL(a_time, b_time);

  /* This value is out of range with 32 bit time_t, but in range for 64 bit
   * time_t */
  a_time.tm_year = 2039-1900;
#if SIZEOF_TIME_T == 4
805
  setup_full_capture_of_logs(LOG_WARN);
806
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
807
808
  expect_single_log_msg_containing("Result does not fit in tor_timegm");
  teardown_capture_of_logs();
809
810
811
812
813
#elif SIZEOF_TIME_T == 8
  t_res = 2178252895UL;
  tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
  tor_gmtime_r(&t_res, &b_time);
  TM_EQUAL(a_time, b_time);
814
#endif /* SIZEOF_TIME_T == 4 || ... */
815

816
817
  /* Test tor_timegm out of range */

818
819
820
  /* The below tests will all cause a BUG message, so we capture, suppress,
   * and detect. */
#define CAPTURE() do {                                          \
821
    setup_full_capture_of_logs(LOG_WARN);                       \
822
823
  } while (0)
#define CHECK_TIMEGM_WARNING(msg) do { \
824
    expect_single_log_msg_containing(msg);                              \
825
    teardown_capture_of_logs();                                         \
826
  } while (0)
827
828
829
830
831
832
#define CHECK_POSSIBLE_EINVAL() do {                            \
    if (mock_saved_log_n_entries()) {                           \
      expect_single_log_msg_containing("Invalid argument");     \
    }                                                           \
    teardown_capture_of_logs();                                 \
  } while (0)
833
834
835
836

#define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
    CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")

837
838
839
840
  /* year */

  /* Wrong year < 1970 */
  a_time.tm_year = 1969-1900;
841
  CAPTURE();
842
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
843
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
844
845

  a_time.tm_year = -1-1900;
846
  CAPTURE();
847
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
848
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
849

850
#if SIZEOF_INT == 4 || SIZEOF_INT == 8
851
    a_time.tm_year = -1*(1 << 16);
852
    CAPTURE();
853
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
854
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
855
856
857
858

    /* one of the smallest tm_year values my 64 bit system supports:
     * t_res = -9223372036854775LL without clamping */
    a_time.tm_year = -292275055-1900;
859
    CAPTURE();
860
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
861
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
862
863

    a_time.tm_year = INT32_MIN;
864
    CAPTURE();
865
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
866
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
867
#endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
868

869
870
#if SIZEOF_INT == 8
    a_time.tm_year = -1*(1 << 48);
871
    CAPTURE();
872
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
873
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
874
875
876
877
878

    /* while unlikely, the system's gmtime(_r) could return
     * a "correct" retrospective gregorian negative year value,
     * which I'm pretty sure is:
     * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
879
     * 730485 is the number of days in two millennia, including leap days */
880
    a_time.tm_year = -292277022657-1900;
881
    CAPTURE();
882
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
883
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
884
885

    a_time.tm_year = INT64_MIN;
886
    CAPTURE();
887
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
888
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
889
#endif /* SIZEOF_INT == 8 */
890
891

  /* Wrong year >= INT32_MAX - 1900 */
892
#if SIZEOF_INT == 4 || SIZEOF_INT == 8
893
    a_time.tm_year = INT32_MAX-1900;
894
    CAPTURE();
895
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
896
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
897
898

    a_time.tm_year = INT32_MAX;
899
    CAPTURE();
900
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
901
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
902
#endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
903

904
#if SIZEOF_INT == 8
905
    /* one of the largest tm_year values my 64 bit system supports */
906
    a_time.tm_year = 292278994-1900;
907
    CAPTURE();
908
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
909
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
910
911
912
913
914

    /* while unlikely, the system's gmtime(_r) could return
     * a "correct" proleptic gregorian year value,
     * which I'm pretty sure is:
     * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
915
     * 730485 is the number of days in two millennia, including leap days */
916
    a_time.tm_year = 292277026596-1900;
917
    CAPTURE();
918
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
919
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
920
921

    a_time.tm_year = INT64_MAX-1900;
922
    CAPTURE();
923
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
924
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
925
926

    a_time.tm_year = INT64_MAX;
927
    CAPTURE();
928
    tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
929
    CHECK_TIMEGM_ARG_OUT_OF_RANGE();
930
#endif /* SIZEOF_INT == 8 */
931
932
933
934

  /* month */
  a_time.tm_year = 2007-1900;  /* restore valid year */

935
  a_time.tm_mon = 12;          /* Wrong month, it's 0-based */
936
  CAPTURE();
937
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
938
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
939

940
  a_time.tm_mon = -1;          /* Wrong month */
941
  CAPTURE();
942
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
943
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
944

945
946
947
  /* day */
  a_time.tm_mon = 6;            /* Try July */
  a_time.tm_mday = 32;          /* Wrong day */
948
  CAPTURE();
949
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
950
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
951
952
953

  a_time.tm_mon = 5;            /* Try June */
  a_time.tm_mday = 31;          /* Wrong day */
954
  CAPTURE();
955
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
956
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
957
958
959
960

  a_time.tm_year = 2008-1900;   /* Try a leap year */
  a_time.tm_mon = 1;            /* in feb. */
  a_time.tm_mday = 30;          /* Wrong day */
961
  CAPTURE();
962
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
963
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
964
965
966
967

  a_time.tm_year = 2011-1900;   /* Try a non-leap year */
  a_time.tm_mon = 1;            /* in feb. */
  a_time.tm_mday = 29;          /* Wrong day */
968
  CAPTURE();
969
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
970
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
971
972

  a_time.tm_mday = 0;           /* Wrong day, it's 1-based (to be different) */
973
  CAPTURE();
974
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
975
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
976
977
978
979
980

  /* hour */
  a_time.tm_mday = 3;           /* restore valid month day */

  a_time.tm_hour = 24;          /* Wrong hour, it's 0-based */
981
  CAPTURE();
982
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
983
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
984
985

  a_time.tm_hour = -1;          /* Wrong hour */
986
  CAPTURE();
987
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
988
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
989
990
991
992
993

  /* minute */
  a_time.tm_hour = 22;          /* restore valid hour */

  a_time.tm_min = 60;           /* Wrong minute, it's 0-based */
994
  CAPTURE();
995
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
996
  CHECK_TIMEGM_ARG_OUT_OF_RANGE();
997
998

  a_time.tm_min = -1;           /* Wrong minute */
999
  CAPTURE();
1000
  tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
For faster browsing, not all history is shown. View entire blame