tst-mktime2.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* Test program from Paul Eggert and Tony Leneis. */
  2. #include <array_length.h>
  3. #include <errno.h>
  4. #include <limits.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <support/check.h>
  8. #include <time.h>
  9. #include <unistd.h>
  10. /* True if the arithmetic type T is signed. */
  11. #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
  12. /* The maximum and minimum values for the integer type T. These
  13. macros have undefined behavior if T is signed and has padding bits.
  14. If this is a problem for you, please let us know how to fix it for
  15. your host. */
  16. #define TYPE_MINIMUM(t) \
  17. ((t) (! TYPE_SIGNED (t) \
  18. ? (t) 0 \
  19. : ~ TYPE_MAXIMUM (t)))
  20. #define TYPE_MAXIMUM(t) \
  21. ((t) (! TYPE_SIGNED (t) \
  22. ? (t) -1 \
  23. : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
  24. #ifndef TIME_T_MIN
  25. # define TIME_T_MIN TYPE_MINIMUM (time_t)
  26. #endif
  27. #ifndef TIME_T_MAX
  28. # define TIME_T_MAX TYPE_MAXIMUM (time_t)
  29. #endif
  30. /* Values we'll use to set the TZ environment variable. */
  31. static const char *tz_strings[] =
  32. {
  33. (const char *) 0, "GMT0", "JST-9",
  34. "EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00"
  35. };
  36. static void
  37. set_timezone (const char *tz)
  38. {
  39. printf ("info: setting TZ=%s\n", tz);
  40. if (setenv ("TZ", tz, 1) != 0)
  41. FAIL_EXIT1 ("setenv: %m");
  42. }
  43. /* Fail if mktime fails to convert a date in the spring-forward gap.
  44. Based on a problem report from Andreas Jaeger. */
  45. static void
  46. spring_forward_gap (void)
  47. {
  48. /* glibc (up to about 1998-10-07) failed this test. */
  49. struct tm tm;
  50. /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0"
  51. instead of "TZ=America/Vancouver" in order to detect the bug even
  52. on systems that don't support the Olson extension, or don't have the
  53. full zoneinfo tables installed. */
  54. set_timezone ("PST8PDT,M4.1.0,M10.5.0");
  55. tm.tm_year = 98;
  56. tm.tm_mon = 3;
  57. tm.tm_mday = 5;
  58. tm.tm_hour = 2;
  59. tm.tm_min = 0;
  60. tm.tm_sec = 0;
  61. tm.tm_isdst = -1;
  62. if (mktime (&tm) == (time_t)-1)
  63. FAIL_EXIT1 ("mktime: %m");
  64. }
  65. static void
  66. mktime_test1 (time_t now)
  67. {
  68. struct tm *lt = localtime (&now);
  69. if (lt == NULL)
  70. {
  71. /* For extreme input values, it is expected that localtime fails
  72. with EOVERFLOW. */
  73. printf ("info: localtime (%lld) failed: %m\n", (long long int) now);
  74. TEST_COMPARE (errno, EOVERFLOW);
  75. return;
  76. }
  77. TEST_COMPARE (mktime (lt), now);
  78. }
  79. static void
  80. mktime_test (time_t now)
  81. {
  82. mktime_test1 (now);
  83. mktime_test1 ((time_t) (TIME_T_MAX - now));
  84. mktime_test1 ((time_t) (TIME_T_MIN + now));
  85. }
  86. static void
  87. irix_6_4_bug (void)
  88. {
  89. /* Based on code from Ariel Faigon. */
  90. struct tm tm;
  91. tm.tm_year = 96;
  92. tm.tm_mon = 3;
  93. tm.tm_mday = 0;
  94. tm.tm_hour = 0;
  95. tm.tm_min = 0;
  96. tm.tm_sec = 0;
  97. tm.tm_isdst = -1;
  98. mktime (&tm);
  99. TEST_COMPARE (tm.tm_mon, 2);
  100. TEST_COMPARE (tm.tm_mday, 31);
  101. }
  102. static void
  103. bigtime_test (int j)
  104. {
  105. struct tm tm;
  106. time_t now;
  107. tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j;
  108. tm.tm_isdst = -1;
  109. now = mktime (&tm);
  110. if (now != (time_t) -1)
  111. {
  112. struct tm *lt = localtime (&now);
  113. TEST_COMPARE (lt->tm_year, tm.tm_year);
  114. TEST_COMPARE (lt->tm_mon, tm.tm_mon);
  115. TEST_COMPARE (lt->tm_mday, tm.tm_mday);
  116. TEST_COMPARE (lt->tm_hour, tm.tm_hour);
  117. TEST_COMPARE (lt->tm_min, tm.tm_min);
  118. TEST_COMPARE (lt->tm_sec, tm.tm_sec);
  119. TEST_COMPARE (lt->tm_yday, tm.tm_yday);
  120. TEST_COMPARE (lt->tm_wday, tm.tm_wday);
  121. TEST_COMPARE (lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst,
  122. tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst);
  123. }
  124. }
  125. static int
  126. do_test (void)
  127. {
  128. time_t t, delta;
  129. int i;
  130. unsigned int j;
  131. set_timezone ("America/Sao_Paulo");
  132. delta = TIME_T_MAX / 997; /* a suitable prime number */
  133. for (i = 0; i < array_length (tz_strings); i++)
  134. {
  135. if (tz_strings[i] != NULL)
  136. set_timezone (tz_strings[i]);
  137. for (t = 0; t <= TIME_T_MAX - delta; t += delta)
  138. mktime_test (t);
  139. mktime_test ((time_t) 1);
  140. mktime_test ((time_t) (60 * 60));
  141. mktime_test ((time_t) (60 * 60 * 24));
  142. for (j = 1; j <= INT_MAX; j *= 2)
  143. bigtime_test (j);
  144. bigtime_test (j - 1);
  145. }
  146. irix_6_4_bug ();
  147. spring_forward_gap ();
  148. return 0;
  149. }
  150. #include <support/test-driver.c>