File Coverage

t/lib/MyTest.xs
Criterion Covered Total %
statement 4 181 2.2
branch 3 306 0.9
condition n/a
subroutine n/a
pod n/a
total 7 487 1.4


line stmt bran cond sub pod time code
1             #include
2             #include
3              
4             using namespace xs;
5             using namespace panda::time;
6             using panda::string;
7              
8             #ifdef _WIN32
9             # define SYSTIMEGM(x) _mkgmtime(x)
10             # define SYSTIMELOCAL(x) mktime(x)
11             #else
12             # define SYSTIMEGM(x) timegm(x)
13             # define SYSTIMELOCAL(x) timelocal(x)
14             #endif
15              
16             MODULE = MyTest PACKAGE = MyTest
17             PROTOTYPES: DISABLE
18              
19             time_t systimegm (int64_t sec, int64_t min, int64_t hour, int64_t mday, int64_t mon, int64_t year, int64_t isdst = -1) : ALIAS(systimelocal=1) {
20             struct tm date;
21 0           date.tm_sec = sec;
22 0           date.tm_min = min;
23 0           date.tm_hour = hour;
24 0           date.tm_mday = mday;
25 0           date.tm_mon = mon;
26 0           date.tm_year = year;
27 0           date.tm_isdst = isdst;
28 0 0         if (ix == 0) RETVAL = SYSTIMEGM(&date);
29 0           else RETVAL = SYSTIMELOCAL(&date);
30             }
31              
32             const char* strftime (const char* fmt, time_t epoch) {
33             char buf[100];
34             datetime date;
35 2 50         localtime(epoch, &date);
36 2 50         auto sz = strftime(buf, sizeof(buf), fmt, &date);
37 2 50         if (!sz) croak("should not happen");
38 2           RETVAL = buf;
39             }
40              
41             #ifndef _WIN32
42              
43             bool test_gmtime (ptime_t step, ptime_t from, ptime_t till) : ALIAS(test_localtime=1) {
44             datetime date1;
45             struct tm date2;
46            
47 0 0         string tzname = ix == 0 ? string("GMT") : tzlocal()->name;
    0          
    0          
    0          
    0          
48 0           char* hstr = getenv("HARNESS_ACTIVE");
49 0 0         bool test = (hstr != NULL && strlen(hstr) > 0);
    0          
50            
51             static bool sranded = false;
52 0 0         if (!sranded) { srand(time(NULL)); sranded = true; }
53              
54 0           bool isrand = false;
55             ptime_t disperse, epoch;
56 0 0         if (step == 0) {
57 0           isrand = true;
58 0           disperse = from;
59 0           step = 1;
60 0           from = 0;
61             }
62            
63 0           int cnt = 0;
64 0 0         for (ptime_t i = from; i < till; i += step) {
65 0           cnt++;
66 0           memset(&date1, 0, sizeof(date1));
67 0           memset(&date2, 0, sizeof(date2));
68            
69 0 0         if (isrand) epoch = rand() % (2*disperse) - disperse;
70 0           else epoch = i;
71 0           time_t sys_epoch = (time_t) epoch;
72            
73 0 0         if (ix == 0) {
74 0 0         gmtime(epoch, &date1);
75 0           gmtime_r(&sys_epoch, &date2);
76             } else {
77 0 0         localtime(epoch, &date1);
78 0           localtime_r(&sys_epoch, &date2);
79             }
80            
81 0 0         if (cnt % 100000 == 0 && !test) printf("TESTED #%d, last %04i-%02i-%02i %02i:%02i:%02i (off:%ld, dst=%d, zone=%s)\n", cnt, date2.tm_year+1900, date2.tm_mon+1, date2.tm_mday, date2.tm_hour, date2.tm_min, date2.tm_sec, date2.tm_gmtoff, date2.tm_isdst, date2.tm_zone);
    0          
    0          
82              
83 0 0         if (date1.year != (date2.tm_year + 1900) || date1.mon != date2.tm_mon || date1.mday != date2.tm_mday ||
    0          
    0          
    0          
84 0 0         date1.hour != date2.tm_hour || date1.min != date2.tm_min || date1.sec != date2.tm_sec ||
    0          
    0          
85 0 0         date1.isdst != date2.tm_isdst || date1.gmtoff != date2.tm_gmtoff || strcmp(date1.zone, date2.tm_zone) != 0) {
    0          
86 0           warn(
87             "zone=%.*s, epoch=%lli, got %d-%02lld-%02lld %02lld:%02lld:%02lld %d %d %d %d %s, should be %d-%02d-%02d %02d:%02d:%02d %d %d %d %ld %s",
88 0           (int)tzname.length(), tzname.data(), (long long)epoch,
89 0           date1.year, (long long)date1.mon+1, (long long)date1.mday, (long long)date1.hour, (long long)date1.min, (long long)date1.sec,
90             date1.wday, date1.yday, date1.isdst, date1.gmtoff, date1.zone,
91 0           date2.tm_year+1900, date2.tm_mon+1, date2.tm_mday, date2.tm_hour, date2.tm_min, date2.tm_sec,
92             date2.tm_wday, date2.tm_yday, date2.tm_isdst, date2.tm_gmtoff, date2.tm_zone
93 0 0         );
94 0           XSRETURN_UNDEF;
95             }
96             }
97            
98 0 0         if (!test) printf("TESTED %d TIMES\n", cnt);
    0          
99            
100 0           RETVAL = true;
101             }
102              
103             bool test_timegm (ptime_t step, ptime_t from, ptime_t till) : ALIAS(test_timelocal=1) {
104             datetime date1;
105             struct tm date2;
106            
107 0           char* hstr = getenv("HARNESS_ACTIVE");
108 0 0         bool test = (hstr != NULL && strlen(hstr) > 0);
    0          
109            
110             static bool sranded = false;
111 0 0         if (!sranded) { srand(time(NULL)); sranded = true; }
112              
113 0           bool isrand = false;
114             ptime_t disperce_years;
115 0 0         if (step == 0) {
116 0           isrand = true;
117 0           step = 1;
118 0           disperce_years = from;
119 0 0         if (disperce_years > 200) disperce_years = 200;
120 0           from = 0;
121             }
122            
123 0           int cnt = 0;
124 0 0         for (ptime_t i = from; step > 0 ? (i < till) : (i > till); i += step) {
    0          
125 0           cnt++;
126 0           bzero(&date1, sizeof(date1));
127 0           bzero(&date2, sizeof(date2));
128            
129 0 0         if (isrand) {
130 0 0         if (ix == 0) {
131 0           int rnum = rand();
132 0           date1.sec = rnum % 10000 - 5000;
133 0           rnum /= 1000;
134 0           date1.min = rnum % 10000 - 5000;
135 0           rnum /= 1000;
136 0           date1.hour = rnum % 100 - 50;
137 0           rnum = rand();
138 0           date1.mday = rnum % 100 - 50;
139 0           rnum /= 100;
140 0           date1.mon = rnum % 100 - 50;
141 0           rnum /= 100;
142 0           date1.year = rnum % 200 + 1910;
143             } else { // dont test denormalized values (LINUX has bugs with them + when using leap seconds zone, our normalization may differ with OS)
144 0           int rnum = rand();
145 0           date1.sec = rnum % 60;
146 0           rnum /= 1000;
147 0           date1.min = rnum % 60;
148 0           rnum /= 1000;
149 0           date1.hour = rnum % 24;
150 0           rnum = rand();
151 0           date1.mday = rnum % 31 + 1;
152 0           rnum /= 100;
153 0           date1.mon = rnum % 11;
154 0           rnum /= 100;
155 0           date1.year = rnum % disperce_years + 1910;
156             }
157             }
158             else {
159 0 0         if (ix == 0) gmtime(i, &date1);
    0          
160 0 0         else localtime(i, &date1);
161             }
162              
163 0 0         if (ix == 1) date1.isdst = -1;
164 0           dt2tm(date2, date1);
165            
166 0           datetime copy1 = date1;
167 0           struct tm copy2 = date2;
168            
169             ptime_t mytime;
170             time_t truetime;
171 0 0         if (ix == 0) {
172 0           truetime = timegm(&date2);
173 0 0         if (isrand) mytime = timegm(&date1); // need normalization
    0          
174 0 0         else mytime = timegml(&date1);
175             } else {
176 0 0         mytime = timelocal(&date1);
177 0           truetime = timelocal(&date2);
178             }
179            
180 0 0         if (cnt % 100000 == 0 && !test) printf("TESTED #%d, last %04d-%02d-%02d %02d:%02d:%02d\n", cnt, date2.tm_year+1900, date2.tm_mon+1, date2.tm_mday, date2.tm_hour, date2.tm_min, date2.tm_sec);
    0          
    0          
181            
182 0 0         bool same_ymdhms = (date1.year != (date2.tm_year + 1900) || date1.mon != date2.tm_mon || date1.mday != date2.tm_mday || date1.hour != date2.tm_hour || date1.min != date2.tm_min || date1.sec != date2.tm_sec) ? false : true;
    0          
    0          
    0          
    0          
    0          
183 0 0         bool same_zone = (date1.isdst != date2.tm_isdst || date1.gmtoff != date2.tm_gmtoff || strcmp(date1.zone, date2.tm_zone) != 0) ? false : true;
    0          
    0          
184 0 0         bool same_date = same_ymdhms && same_zone;
    0          
185              
186 0 0         if (mytime != truetime || !same_date) {
    0          
187 0 0         if (truetime == -1) continue; // OS cannot handle such dates
188            
189 0 0         if (same_ymdhms && ix == 1) { // if ambiguity, OS may return unpredicted results. Lets handle that.
    0          
190 0           datetime tmpdate = date1;
191 0           tmpdate.isdst = 1;
192 0 0         mytime = timelocal(&tmpdate);
193 0 0         if (mytime == truetime) continue;
194             }
195              
196 0           warn(
197             "MY: epoch=%lli (%04d/%02lld/%02lld %02lld:%02lld:%02lld %4s %d) from %04d/%02lld/%02lld %02lld:%02lld:%02lld DST=%d (%.*s)",
198             (long long)mytime,
199 0           date1.year, (long long)date1.mon+1, (long long)date1.mday, (long long)date1.hour, (long long)date1.min, (long long)date1.sec,
200             date1.zone, date1.gmtoff,
201 0           copy1.year, (long long)copy1.mon+1, (long long)copy1.mday, (long long)copy1.hour, (long long)copy1.min, (long long)copy1.sec,
202 0 0         copy1.isdst, (int)tzlocal()->name.length(), tzlocal()->name.data()
    0          
203 0 0         );
204 0           warn(
205             "OS: epoch=%li (%04d/%02d/%02d %02d:%02d:%02d %4s %ld) from %04d/%02d/%02d %02d:%02d:%02d DST=%d (%.*s)",
206 0           truetime, date2.tm_year+1900, date2.tm_mon+1, date2.tm_mday, date2.tm_hour, date2.tm_min, date2.tm_sec, date2.tm_zone, date2.tm_gmtoff,
207 0 0         copy2.tm_year+1900, copy2.tm_mon+1, copy2.tm_mday, copy2.tm_hour, copy2.tm_min, copy2.tm_sec, copy2.tm_isdst, (int)tzlocal()->name.length(), tzlocal()->name.data()
    0          
208 0 0         );
209 0 0         warn("diff is %lli", (long long)(mytime - truetime));
210 0           XSRETURN_UNDEF;
211             }
212             }
213            
214 0 0         if (!test) printf("TESTED %d TIMES\n", cnt);
    0          
215            
216 0           RETVAL = true;
217             }
218              
219             Array gmtime_bench (ptime_t epoch) : ALIAS(localtime_bench=1) {
220             datetime date;
221 0           ptime_t max_epoch = epoch + 10000;
222 0 0         if (ix == 0) while(epoch++ < max_epoch) gmtime(epoch, &date);
    0          
    0          
223 0 0         else if (ix == 1) while(epoch++ < max_epoch) localtime(epoch, &date);
    0          
    0          
224            
225 0 0         RETVAL = Array::create();
226 0 0         RETVAL.push(Simple(date.sec));
    0          
227 0 0         RETVAL.push(Simple(date.min));
    0          
228 0 0         RETVAL.push(Simple(date.hour));
    0          
229 0 0         RETVAL.push(Simple(date.mday));
    0          
230 0 0         RETVAL.push(Simple(date.mon));
    0          
231 0 0         RETVAL.push(Simple(date.year));
    0          
232 0 0         RETVAL.push(Simple(date.wday));
    0          
233 0 0         RETVAL.push(Simple(date.yday));
    0          
234 0 0         RETVAL.push(Simple(date.isdst));
    0          
235 0 0         RETVAL.push(Simple(date.gmtoff));
    0          
236 0 0         RETVAL.push(Simple(date.zone));
    0          
237             }
238              
239             Array posix_gmtime_bench (time_t epoch) : ALIAS(posix_localtime_bench=1) {
240             struct tm date;
241 0           time_t max_epoch = epoch + 10000;
242 0 0         if (ix == 0) while(epoch++ < max_epoch) gmtime_r(&epoch, &date);
    0          
243 0 0         else if (ix == 1) while(epoch++ < max_epoch) localtime_r(&epoch, &date);
    0          
244              
245 0 0         RETVAL = Array::create();
246 0 0         RETVAL.push(Simple(date.tm_sec));
    0          
247 0 0         RETVAL.push(Simple(date.tm_min));
    0          
248 0 0         RETVAL.push(Simple(date.tm_hour));
    0          
249 0 0         RETVAL.push(Simple(date.tm_mday));
    0          
250 0 0         RETVAL.push(Simple(date.tm_mon));
    0          
251 0 0         RETVAL.push(Simple(date.tm_year));
    0          
252 0 0         RETVAL.push(Simple(date.tm_wday));
    0          
253 0 0         RETVAL.push(Simple(date.tm_yday));
    0          
254 0 0         RETVAL.push(Simple(date.tm_isdst));
    0          
255 0 0         RETVAL.push(Simple(date.tm_gmtoff));
    0          
256 0 0         RETVAL.push(Simple(date.tm_zone));
    0          
257             }
258              
259             ptime_t timegm_bench (ptime_t sec, ptime_t min, ptime_t hour, ptime_t mday, ptime_t mon, ptime_t year) : ALIAS(timegml_bench=1, timelocal_bench=2, timelocall_bench=3) {
260             datetime date;
261 0           date.sec = sec;
262 0           date.min = min;
263 0           date.hour = hour;
264 0           date.mday = mday;
265 0           date.mon = mon;
266 0           date.year = year;
267 0           date.isdst = -1;
268            
269 0           int i = 0;
270 0           int cnt = 10000;
271 0           RETVAL = 0;
272            
273 0 0         if (ix == 0) while (i++ < cnt) RETVAL += timegm(&date);
    0          
    0          
274 0 0         else if (ix == 1) while (i++ < cnt) RETVAL += timegml(&date);
    0          
    0          
275 0 0         else if (ix == 2) while (i++ < cnt) RETVAL += timelocal(&date);
    0          
    0          
276 0 0         else if (ix == 3) while (i++ < cnt) RETVAL += timelocall(&date);
    0          
    0          
277             }
278              
279             time_t posix_timegm_bench (int64_t sec, int64_t min, int64_t hour, int64_t mday, int64_t mon, int64_t year) : ALIAS(posix_timelocal_bench=1) {
280             struct tm date;
281 0           date.tm_sec = sec;
282 0           date.tm_min = min;
283 0           date.tm_hour = hour;
284 0           date.tm_mday = mday;
285 0           date.tm_mon = mon;
286 0           date.tm_year = year-1900;
287 0           date.tm_isdst = -1;
288            
289 0           int i = 0;
290 0           int cnt = 10000;
291 0           RETVAL = 0;
292            
293 0 0         if (ix == 0) while (i++ < cnt) RETVAL += timegm(&date);
    0          
294 0 0         else if (ix == 1) while (i++ < cnt) RETVAL += timelocal(&date);
    0          
295             }
296              
297             #endif