Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #define _XOPEN_SOURCE 700
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <limits.h>
  8. #include "test.h"
  9.  
  10. /* We use this instead of memcmp because some broken C libraries
  11.  * add additional nonstandard fields to struct tm... */
  12.  
  13. int tm_cmp(struct tm tm1, struct tm tm2)
  14. {
  15.         return  tm1.tm_sec  != tm2.tm_sec  ||
  16.                 tm1.tm_min  != tm2.tm_min  ||
  17.                 tm1.tm_hour != tm2.tm_hour ||
  18.                 tm1.tm_mday != tm2.tm_mday ||
  19.                 tm1.tm_mon  != tm2.tm_mon  ||
  20.                 tm1.tm_year != tm2.tm_year ||
  21.                 tm1.tm_wday != tm2.tm_wday ||
  22.                 tm1.tm_yday != tm2.tm_yday ||
  23.                 tm1.tm_isdst!= tm2.tm_isdst;
  24. }
  25.  
  26. char *tm_str(struct tm tm)
  27. {
  28.         static int i;
  29.         static char b[4][64];
  30.         i = (i+1)%4;
  31.         snprintf(b[i], sizeof b[i],
  32.                 "s=%02d m=%02d h=%02d mday=%02d mon=%02d year=%04d wday=%d yday=%d isdst=%d",
  33.                 tm.tm_sec, tm.tm_min, tm.tm_hour,
  34.                 tm.tm_mday, tm.tm_mon, tm.tm_year,
  35.                 tm.tm_wday, tm.tm_yday, tm.tm_isdst);
  36.         return b[i];
  37. }
  38.  
  39. #define TM(ss,mm,hh,md,mo,yr,wd,yd,dst) (struct tm){ \
  40.         .tm_sec = ss, .tm_min = mm, .tm_hour = hh,    \
  41.         .tm_mday = md, .tm_mon = mo, .tm_year = yr,    \
  42.         .tm_wday = wd, .tm_yday = yd, .tm_isdst = dst }
  43.  
  44. #define TM_EPOCH    TM(0,0,0,1,0,70,4,0,0)
  45. #define TM_Y2038_1S TM(7,14,3,19,0,138,2,18,0)
  46. #define TM_Y2038    TM(8,14,3,19,0,138,2,18,0)
  47.  
  48. static void sec2tm(time_t t, char *m)
  49. {
  50.         struct tm *tm;
  51.         time_t r;
  52.  
  53.         errno = 0;
  54.         tm = gmtime(&t);
  55.         if (errno != 0)
  56.                 t_error("%s: gmtime((time_t)%lld) should not set errno, got %s\n",
  57.                         m, (long long)t, strerror(errno));
  58.         errno = 0;
  59.         r = mktime(tm);
  60.         if (errno != 0)
  61.                 t_error("%s: mktime(%s) should not set errno, got %s\n",
  62.                         m, tm_str(*tm), strerror(errno));
  63.         if (t != r)
  64.                 t_error("%s: mktime(gmtime(%lld)) roundtrip failed: got %lld (gmtime is %s)\n",
  65.                         m, (long long)t, (long long)r, tm_str(*tm));
  66. }
  67.  
  68. static void tm2sec(struct tm *tm, int big, char *m)
  69. {
  70.         struct tm *r;
  71.         time_t t;
  72.         int overflow = big && (time_t)LLONG_MAX!=LLONG_MAX;
  73.  
  74.         errno = 0;
  75.         t = mktime(tm);
  76.         if (overflow && t != -1)
  77.                 t_error("%s: mktime(%s) expected -1, got (time_t)%ld\n",
  78.                         m, tm_str(*tm), (long)t);
  79.         if (overflow && errno != 10000) //EOVERFLOW
  80.                 t_error("%s: mktime(%s) expected EOVERFLOW (%s), got (%s)\n",
  81.                         m, tm_str(*tm), strerror(10000), strerror(errno));
  82.         if (!overflow && t == -1)
  83.                 t_error("%s: mktime(%s) expected success, got (time_t)-1\n",
  84.                         m, tm_str(*tm));
  85.         if (!overflow && errno)
  86.                 t_error("%s: mktime(%s) expected no error, got (%s)\n",
  87.                         m, tm_str(*tm), strerror(errno));
  88.         r = gmtime(&t);
  89.         if (!overflow && tm_cmp(*r, *tm))
  90.                 t_error("%s: gmtime(mktime(%s)) roundtrip failed: got %s\n",
  91.                         m, tm_str(*tm), tm_str(*r));
  92. }
  93.  
  94. int main(void)
  95. {
  96.         time_t t;
  97.  
  98.         putenv("TZ=GMT");
  99.         tzset();
  100.         tm2sec(&TM_EPOCH, 0, "gmtime(0)");
  101.         tm2sec(&TM_Y2038_1S, 0, "2038-1s");
  102.         tm2sec(&TM_Y2038, 1, "2038");
  103.  
  104.         sec2tm(0, "EPOCH");
  105.         for (t = 1; t < 1000; t++)
  106.                 sec2tm(t*100003, "EPOCH+eps");
  107.  
  108.         /* FIXME: set a TZ var and check DST boundary conditions */
  109.         return t_status;
  110. }
  111.