1570af302Sopenharmony_ci#define _XOPEN_SOURCE 700 2570af302Sopenharmony_ci#include <stdlib.h> 3570af302Sopenharmony_ci#include <stdio.h> 4570af302Sopenharmony_ci#include <time.h> 5570af302Sopenharmony_ci#include <string.h> 6570af302Sopenharmony_ci#include <errno.h> 7570af302Sopenharmony_ci#include <limits.h> 8570af302Sopenharmony_ci#include "test.h" 9570af302Sopenharmony_ci 10570af302Sopenharmony_ci/* We use this instead of memcmp because some broken C libraries 11570af302Sopenharmony_ci * add additional nonstandard fields to struct tm... */ 12570af302Sopenharmony_ci 13570af302Sopenharmony_ciint tm_cmp(struct tm tm1, struct tm tm2) 14570af302Sopenharmony_ci{ 15570af302Sopenharmony_ci return tm1.tm_sec != tm2.tm_sec || 16570af302Sopenharmony_ci tm1.tm_min != tm2.tm_min || 17570af302Sopenharmony_ci tm1.tm_hour != tm2.tm_hour || 18570af302Sopenharmony_ci tm1.tm_mday != tm2.tm_mday || 19570af302Sopenharmony_ci tm1.tm_mon != tm2.tm_mon || 20570af302Sopenharmony_ci tm1.tm_year != tm2.tm_year || 21570af302Sopenharmony_ci tm1.tm_wday != tm2.tm_wday || 22570af302Sopenharmony_ci tm1.tm_yday != tm2.tm_yday || 23570af302Sopenharmony_ci tm1.tm_isdst!= tm2.tm_isdst; 24570af302Sopenharmony_ci} 25570af302Sopenharmony_ci 26570af302Sopenharmony_cichar *tm_str(struct tm tm) 27570af302Sopenharmony_ci{ 28570af302Sopenharmony_ci static int i; 29570af302Sopenharmony_ci static char b[4][64]; 30570af302Sopenharmony_ci i = (i+1)%4; 31570af302Sopenharmony_ci snprintf(b[i], sizeof b[i], 32570af302Sopenharmony_ci "s=%02d m=%02d h=%02d mday=%02d mon=%02d year=%04d wday=%d yday=%d isdst=%d", 33570af302Sopenharmony_ci tm.tm_sec, tm.tm_min, tm.tm_hour, 34570af302Sopenharmony_ci tm.tm_mday, tm.tm_mon, tm.tm_year, 35570af302Sopenharmony_ci tm.tm_wday, tm.tm_yday, tm.tm_isdst); 36570af302Sopenharmony_ci return b[i]; 37570af302Sopenharmony_ci} 38570af302Sopenharmony_ci 39570af302Sopenharmony_ci#define TM(ss,mm,hh,md,mo,yr,wd,yd,dst) (struct tm){ \ 40570af302Sopenharmony_ci .tm_sec = ss, .tm_min = mm, .tm_hour = hh, \ 41570af302Sopenharmony_ci .tm_mday = md, .tm_mon = mo, .tm_year = yr, \ 42570af302Sopenharmony_ci .tm_wday = wd, .tm_yday = yd, .tm_isdst = dst } 43570af302Sopenharmony_ci 44570af302Sopenharmony_ci#define TM_EPOCH TM(0,0,0,1,0,70,4,0,0) 45570af302Sopenharmony_ci#define TM_Y2038_1S TM(7,14,3,19,0,138,2,18,0) 46570af302Sopenharmony_ci#define TM_Y2038 TM(8,14,3,19,0,138,2,18,0) 47570af302Sopenharmony_ci 48570af302Sopenharmony_cistatic void sec2tm(time_t t, char *m) 49570af302Sopenharmony_ci{ 50570af302Sopenharmony_ci struct tm *tm; 51570af302Sopenharmony_ci time_t r; 52570af302Sopenharmony_ci 53570af302Sopenharmony_ci errno = 0; 54570af302Sopenharmony_ci tm = gmtime(&t); 55570af302Sopenharmony_ci if (errno != 0) 56570af302Sopenharmony_ci t_error("%s: gmtime((time_t)%lld) should not set errno, got %s\n", 57570af302Sopenharmony_ci m, (long long)t, strerror(errno)); 58570af302Sopenharmony_ci errno = 0; 59570af302Sopenharmony_ci r = mktime(tm); 60570af302Sopenharmony_ci if (errno != 0) 61570af302Sopenharmony_ci t_error("%s: mktime(%s) should not set errno, got %s\n", 62570af302Sopenharmony_ci m, tm_str(*tm), strerror(errno)); 63570af302Sopenharmony_ci if (t != r) 64570af302Sopenharmony_ci t_error("%s: mktime(gmtime(%lld)) roundtrip failed: got %lld (gmtime is %s)\n", 65570af302Sopenharmony_ci m, (long long)t, (long long)r, tm_str(*tm)); 66570af302Sopenharmony_ci} 67570af302Sopenharmony_ci 68570af302Sopenharmony_cistatic void tm2sec(struct tm *tm, int big, char *m) 69570af302Sopenharmony_ci{ 70570af302Sopenharmony_ci struct tm *r; 71570af302Sopenharmony_ci time_t t; 72570af302Sopenharmony_ci int overflow = big && (time_t)LLONG_MAX!=LLONG_MAX; 73570af302Sopenharmony_ci 74570af302Sopenharmony_ci errno = 0; 75570af302Sopenharmony_ci t = mktime(tm); 76570af302Sopenharmony_ci if (overflow && t != -1) 77570af302Sopenharmony_ci t_error("%s: mktime(%s) expected -1, got (time_t)%ld\n", 78570af302Sopenharmony_ci m, tm_str(*tm), (long)t); 79570af302Sopenharmony_ci if (overflow && errno != EOVERFLOW) 80570af302Sopenharmony_ci t_error("%s: mktime(%s) expected EOVERFLOW (%s), got (%s)\n", 81570af302Sopenharmony_ci m, tm_str(*tm), strerror(EOVERFLOW), strerror(errno)); 82570af302Sopenharmony_ci if (!overflow && t == -1) 83570af302Sopenharmony_ci t_error("%s: mktime(%s) expected success, got (time_t)-1\n", 84570af302Sopenharmony_ci m, tm_str(*tm)); 85570af302Sopenharmony_ci if (!overflow && errno) 86570af302Sopenharmony_ci t_error("%s: mktime(%s) expected no error, got (%s)\n", 87570af302Sopenharmony_ci m, tm_str(*tm), strerror(errno)); 88570af302Sopenharmony_ci r = gmtime(&t); 89570af302Sopenharmony_ci if (!overflow && tm_cmp(*r, *tm)) 90570af302Sopenharmony_ci t_error("%s: gmtime(mktime(%s)) roundtrip failed: got %s\n", 91570af302Sopenharmony_ci m, tm_str(*tm), tm_str(*r)); 92570af302Sopenharmony_ci} 93570af302Sopenharmony_ci 94570af302Sopenharmony_ciint main(void) 95570af302Sopenharmony_ci{ 96570af302Sopenharmony_ci time_t t; 97570af302Sopenharmony_ci 98570af302Sopenharmony_ci putenv("TZ=GMT"); 99570af302Sopenharmony_ci tzset(); 100570af302Sopenharmony_ci tm2sec(&TM_EPOCH, 0, "gmtime(0)"); 101570af302Sopenharmony_ci tm2sec(&TM_Y2038_1S, 0, "2038-1s"); 102570af302Sopenharmony_ci tm2sec(&TM_Y2038, 1, "2038"); 103570af302Sopenharmony_ci 104570af302Sopenharmony_ci sec2tm(0, "EPOCH"); 105570af302Sopenharmony_ci for (t = 1; t < 1000; t++) 106570af302Sopenharmony_ci sec2tm(t*100003, "EPOCH+eps"); 107570af302Sopenharmony_ci 108570af302Sopenharmony_ci /* FIXME: set a TZ var and check DST boundary conditions */ 109570af302Sopenharmony_ci return t_status; 110570af302Sopenharmony_ci} 111