1 | #undef G_DISABLE_ASSERT |
2 | #undef G_LOG_DOMAIN |
3 | |
4 | #ifdef GLIB_COMPILATION |
5 | #undef GLIB_COMPILATION |
6 | #endif |
7 | |
8 | #include "glib.h" |
9 | |
10 | #include <stdio.h> |
11 | #include <stdlib.h> |
12 | #include <string.h> |
13 | #include <locale.h> |
14 | #include <time.h> |
15 | |
16 | gboolean failed = FALSE; |
17 | guint32 passed = 0; |
18 | guint32 notpassed = 0; |
19 | |
20 | #define TEST(m,cond) G_STMT_START { failed = !(cond); \ |
21 | if (failed) \ |
22 | { ++notpassed; \ |
23 | if (!m) \ |
24 | g_print ("\n(%s:%d) failed for: %s\n", __FILE__, __LINE__, ( # cond )); \ |
25 | else \ |
26 | g_print ("\n(%s:%d) failed for: %s: (%s)\n", __FILE__, __LINE__, ( # cond ), (gchar*)m); \ |
27 | } \ |
28 | else \ |
29 | ++passed; \ |
30 | if ((passed+notpassed) % 10000 == 0) g_print ("."); fflush (stdout); \ |
31 | } G_STMT_END |
32 | |
33 | static void |
34 | g_date_debug_print (GDate* d) |
35 | { |
36 | if (!d) g_print(format: "NULL!\n" ); |
37 | else |
38 | g_print(format: "julian: %u (%s) DMY: %u %u %u (%s)\n" , |
39 | d->julian_days, |
40 | d->julian ? "valid" : "invalid" , |
41 | d->day, |
42 | d->month, |
43 | d->year, |
44 | d->dmy ? "valid" : "invalid" ); |
45 | |
46 | fflush(stdout); |
47 | } |
48 | |
49 | int main(int argc, char** argv) |
50 | { |
51 | GDate* d; |
52 | guint32 j; |
53 | GDateMonth m; |
54 | GDateYear y, prev_y; |
55 | GDateDay day; |
56 | gchar buf[101]; |
57 | gchar* loc; |
58 | /* Try to get all the leap year cases. */ |
59 | GDateYear check_years[] = { |
60 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, |
61 | 11, 12, 13, 14, 98, 99, 100, 101, 102, 103, 397, |
62 | 398, 399, 400, 401, 402, 403, 404, 405, 406, |
63 | 1598, 1599, 1600, 1601, 1602, 1650, 1651, |
64 | 1897, 1898, 1899, 1900, 1901, 1902, 1903, |
65 | 1961, 1962, 1963, 1964, 1965, 1967, |
66 | 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, |
67 | 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, |
68 | 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, |
69 | 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
70 | 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, |
71 | 3000, 3001, 3002, 3998, 3999, 4000, 4001, 4002, 4003 |
72 | }; |
73 | guint n_check_years = sizeof(check_years)/sizeof(GDateYear); |
74 | guint i, k; |
75 | gboolean discontinuity; |
76 | |
77 | g_print(format: "checking GDate..." ); |
78 | |
79 | TEST("sizeof(GDate) is not more than 8 bytes on this platform" , sizeof(GDate) < 9); |
80 | |
81 | d = g_date_new(); |
82 | |
83 | TEST("Empty constructor produces invalid date" , !g_date_valid(d)); |
84 | |
85 | g_date_free(date: d); |
86 | |
87 | d = g_date_new_dmy(day: 1,month: 1,year: 1); |
88 | |
89 | TEST("January 1, Year 1 created and valid" , g_date_valid(d)); |
90 | |
91 | j = g_date_get_julian(date: d); |
92 | |
93 | TEST("January 1, Year 1 is Julian date 1" , j == 1); |
94 | |
95 | TEST("Returned month is January" , g_date_get_month(d) == G_DATE_JANUARY); |
96 | TEST("Returned day is 1" , g_date_get_day(d) == 1); |
97 | TEST("Returned year is 1" , g_date_get_year(d) == 1); |
98 | |
99 | TEST("Bad month is invalid" , !g_date_valid_month(G_DATE_BAD_MONTH)); |
100 | TEST("Month 13 is invalid" , !g_date_valid_month(13)); |
101 | TEST("Bad day is invalid" , !g_date_valid_day(G_DATE_BAD_DAY)); |
102 | TEST("Day 32 is invalid" , !g_date_valid_day(32)); |
103 | TEST("Bad year is invalid" , !g_date_valid_year(G_DATE_BAD_YEAR)); |
104 | TEST("Bad julian is invalid" , !g_date_valid_julian(G_DATE_BAD_JULIAN)); |
105 | TEST("Bad weekday is invalid" , !g_date_valid_weekday(G_DATE_BAD_WEEKDAY)); |
106 | TEST("Year 2000 is a leap year" , g_date_is_leap_year(2000)); |
107 | TEST("Year 1999 is not a leap year" , !g_date_is_leap_year(1999)); |
108 | TEST("Year 1996 is a leap year" , g_date_is_leap_year(1996)); |
109 | TEST("Year 1600 is a leap year" , g_date_is_leap_year(1600)); |
110 | TEST("Year 2100 is not a leap year" , !g_date_is_leap_year(2100)); |
111 | TEST("Year 1800 is not a leap year" , !g_date_is_leap_year(1800)); |
112 | |
113 | g_date_free(date: d); |
114 | |
115 | loc = setlocale(LC_ALL,locale: "" ); |
116 | if (loc) |
117 | g_print(format: "\nLocale set to %s\n" , loc); |
118 | else |
119 | g_print(format: "\nLocale unchanged\n" ); |
120 | |
121 | d = g_date_new(); |
122 | g_date_set_time(date: d, time_: time(NULL)); |
123 | TEST("Today is valid" , g_date_valid(d)); |
124 | |
125 | g_date_strftime(s: buf,slen: 100,format: "Today is a %A, %x\n" , date: d); |
126 | g_print(format: "%s" , buf); |
127 | |
128 | g_date_set_time(date: d, time_: 1); |
129 | TEST("Beginning of Unix epoch is valid" , g_date_valid(d)); |
130 | |
131 | g_date_strftime(s: buf,slen: 100,format: "1 second into the Unix epoch it was a %A, in the month of %B, %x\n" , date: d); |
132 | g_print(format: "%s" , buf); |
133 | |
134 | g_date_set_julian(date: d, julian_date: 1); |
135 | TEST("GDate's \"Julian\" epoch's first day is valid" , g_date_valid(d)); |
136 | |
137 | #ifndef G_OS_WIN32 |
138 | g_date_strftime(s: buf,slen: 100,format: "Our \"Julian\" epoch begins on a %A, in the month of %B, %x\n" , |
139 | date: d); |
140 | g_print(format: "%s" , buf); |
141 | #else |
142 | g_print ("But Windows FILETIME does not support dates before Jan 1 1601, so we can't strftime() the beginning of the \"Julian\" epoch.\n" ); |
143 | #endif |
144 | g_date_set_dmy(date: d, day: 10, month: 1, y: 2000); |
145 | |
146 | g_date_strftime(s: buf,slen: 100,format: "%x" , date: d); |
147 | |
148 | g_date_set_parse(date: d, str: buf); |
149 | /* Note: this test will hopefully work, but no promises. */ |
150 | TEST("Successfully parsed a %x-formatted string" , |
151 | g_date_valid(d) && |
152 | g_date_get_month(d) == 1 && |
153 | g_date_get_day(d) == 10 && |
154 | g_date_get_year(d) == 2000); |
155 | if (failed) |
156 | g_date_debug_print(d); |
157 | |
158 | g_date_free(date: d); |
159 | |
160 | j = G_DATE_BAD_JULIAN; |
161 | |
162 | i = 0; |
163 | discontinuity = TRUE; |
164 | y = check_years[0]; |
165 | prev_y = G_DATE_BAD_YEAR; |
166 | g_print (format: "testing %d years\n" , n_check_years); |
167 | while (i < n_check_years) |
168 | { |
169 | guint32 first_day_of_year = G_DATE_BAD_JULIAN; |
170 | guint16 days_in_year = g_date_is_leap_year(year: y) ? 366 : 365; |
171 | guint sunday_week_of_year = 0; |
172 | guint sunday_weeks_in_year = g_date_get_sunday_weeks_in_year(year: y); |
173 | guint monday_week_of_year = 0; |
174 | guint monday_weeks_in_year = g_date_get_monday_weeks_in_year(year: y); |
175 | guint iso8601_week_of_year = 0; |
176 | |
177 | if (discontinuity) |
178 | g_print(format: " (Break in sequence of requested years to check)\n" ); |
179 | |
180 | g_print(format: "Checking year %u" , y); |
181 | |
182 | TEST("Year is valid" , g_date_valid_year(y)); |
183 | |
184 | TEST("Number of Sunday weeks in year is 52 or 53" , |
185 | sunday_weeks_in_year == 52 || sunday_weeks_in_year == 53); |
186 | |
187 | TEST("Number of Monday weeks in year is 52 or 53" , |
188 | monday_weeks_in_year == 52 || monday_weeks_in_year == 53); |
189 | |
190 | m = 1; |
191 | while (m < 13) |
192 | { |
193 | guint8 dim = g_date_get_days_in_month(month: m,year: y); |
194 | GDate days[31]; /* This is the fast way, no allocation */ |
195 | |
196 | TEST("Sensible number of days in month" , (dim > 0 && dim < 32)); |
197 | |
198 | TEST("Month between 1 and 12 is valid" , g_date_valid_month(m)); |
199 | |
200 | day = 1; |
201 | |
202 | g_date_clear(date: days, n_dates: 31); |
203 | |
204 | while (day <= dim) |
205 | { |
206 | GDate tmp; |
207 | |
208 | TEST("DMY triplet is valid" , g_date_valid_dmy(day,m,y)); |
209 | |
210 | /* Create GDate with triplet */ |
211 | |
212 | d = &days[day-1]; |
213 | |
214 | TEST("Cleared day is invalid" , !g_date_valid(d)); |
215 | |
216 | g_date_set_dmy(date: d,day,month: m,y); |
217 | |
218 | TEST("Set day is valid" , g_date_valid(d)); |
219 | |
220 | if (m == G_DATE_JANUARY && day == 1) |
221 | { |
222 | first_day_of_year = g_date_get_julian(date: d); |
223 | } |
224 | |
225 | g_assert(first_day_of_year != G_DATE_BAD_JULIAN); |
226 | |
227 | TEST("Date with DMY triplet is valid" , g_date_valid(d)); |
228 | TEST("Month accessor works" , g_date_get_month(d) == m); |
229 | TEST("Year accessor works" , g_date_get_year(d) == y); |
230 | TEST("Day of month accessor works" , g_date_get_day(d) == day); |
231 | |
232 | TEST("Day of year is consistent with Julian dates" , |
233 | ((g_date_get_julian(d) + 1 - first_day_of_year) == |
234 | (g_date_get_day_of_year(d)))); |
235 | |
236 | if (failed) |
237 | { |
238 | g_print(format: "first day: %u this day: %u day of year: %u\n" , |
239 | first_day_of_year, |
240 | g_date_get_julian(date: d), |
241 | g_date_get_day_of_year(date: d)); |
242 | } |
243 | |
244 | if (m == G_DATE_DECEMBER && day == 31) |
245 | { |
246 | TEST("Last day of year equals number of days in year" , |
247 | g_date_get_day_of_year(d) == days_in_year); |
248 | if (failed) |
249 | { |
250 | g_print(format: "last day: %u days in year: %u\n" , |
251 | g_date_get_day_of_year(date: d), days_in_year); |
252 | } |
253 | } |
254 | |
255 | TEST("Day of year is not more than number of days in the year" , |
256 | g_date_get_day_of_year(d) <= days_in_year); |
257 | |
258 | TEST("Monday week of year is not more than number of weeks in the year" , |
259 | g_date_get_monday_week_of_year(d) <= monday_weeks_in_year); |
260 | if (failed) |
261 | { |
262 | g_print(format: "Weeks in year: %u\n" , monday_weeks_in_year); |
263 | g_date_debug_print(d); |
264 | } |
265 | TEST("Monday week of year is >= than last week of year" , |
266 | g_date_get_monday_week_of_year(d) >= monday_week_of_year); |
267 | |
268 | if (g_date_get_weekday(date: d) == G_DATE_MONDAY) |
269 | { |
270 | |
271 | TEST("Monday week of year on Monday 1 more than previous day's week of year" , |
272 | (g_date_get_monday_week_of_year(d) - monday_week_of_year) == 1); |
273 | if ((m == G_DATE_JANUARY && day <= 4) || |
274 | (m == G_DATE_DECEMBER && day >= 29)) { |
275 | TEST("ISO 8601 week of year on Monday Dec 29 - Jan 4 is 1" , |
276 | (g_date_get_iso8601_week_of_year(d) == 1)); |
277 | } else { |
278 | TEST("ISO 8601 week of year on Monday 1 more than previous day's week of year" , |
279 | (g_date_get_iso8601_week_of_year(d) - iso8601_week_of_year) == 1); |
280 | } |
281 | } |
282 | else |
283 | { |
284 | TEST("Monday week of year on non-Monday 0 more than previous day's week of year" , |
285 | (g_date_get_monday_week_of_year(d) - monday_week_of_year) == 0); |
286 | if (!(day == 1 && m == G_DATE_JANUARY)) { |
287 | TEST("ISO 8601 week of year on non-Monday 0 more than previous day's week of year (" , |
288 | (g_date_get_iso8601_week_of_year(d) - iso8601_week_of_year) == 0); |
289 | } |
290 | } |
291 | |
292 | |
293 | monday_week_of_year = g_date_get_monday_week_of_year(date: d); |
294 | iso8601_week_of_year = g_date_get_iso8601_week_of_year(date: d); |
295 | |
296 | |
297 | TEST("Sunday week of year is not more than number of weeks in the year" , |
298 | g_date_get_sunday_week_of_year(d) <= sunday_weeks_in_year); |
299 | if (failed) |
300 | { |
301 | g_date_debug_print(d); |
302 | } |
303 | TEST("Sunday week of year is >= than last week of year" , |
304 | g_date_get_sunday_week_of_year(d) >= sunday_week_of_year); |
305 | |
306 | if (g_date_get_weekday(date: d) == G_DATE_SUNDAY) |
307 | { |
308 | TEST("Sunday week of year on Sunday 1 more than previous day's week of year" , |
309 | (g_date_get_sunday_week_of_year(d) - sunday_week_of_year) == 1); |
310 | } |
311 | else |
312 | { |
313 | TEST("Sunday week of year on non-Sunday 0 more than previous day's week of year" , |
314 | (g_date_get_sunday_week_of_year(d) - sunday_week_of_year) == 0); |
315 | } |
316 | |
317 | sunday_week_of_year = g_date_get_sunday_week_of_year(date: d); |
318 | |
319 | TEST("Date is equal to itself" , |
320 | g_date_compare(d,d) == 0); |
321 | |
322 | |
323 | /*************** Increments ***********/ |
324 | |
325 | k = 1; |
326 | while (k < 402) /* Need to get 400 year increments in */ |
327 | { |
328 | |
329 | /***** Days ******/ |
330 | tmp = *d; |
331 | g_date_add_days(date: d, n_days: k); |
332 | |
333 | TEST("Adding days gives a value greater than previous" , |
334 | g_date_compare(d, &tmp) > 0); |
335 | |
336 | g_date_subtract_days(date: d, n_days: k); |
337 | TEST("Forward days then backward days returns us to current day" , |
338 | g_date_get_day(d) == day); |
339 | |
340 | if (failed) |
341 | { |
342 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
343 | g_date_debug_print(d); |
344 | } |
345 | |
346 | TEST("Forward days then backward days returns us to current month" , |
347 | g_date_get_month(d) == m); |
348 | |
349 | if (failed) |
350 | { |
351 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
352 | g_date_debug_print(d); |
353 | } |
354 | |
355 | TEST("Forward days then backward days returns us to current year" , |
356 | g_date_get_year(d) == y); |
357 | |
358 | if (failed) |
359 | { |
360 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
361 | g_date_debug_print(d); |
362 | } |
363 | |
364 | /******* Months ********/ |
365 | |
366 | tmp = *d; |
367 | g_date_add_months(date: d, n_months: k); |
368 | TEST("Adding months gives a larger value" , |
369 | g_date_compare(d, &tmp) > 0); |
370 | g_date_subtract_months(date: d, n_months: k); |
371 | |
372 | TEST("Forward months then backward months returns us to current month" , |
373 | g_date_get_month(d) == m); |
374 | |
375 | if (failed) |
376 | { |
377 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
378 | g_date_debug_print(d); |
379 | } |
380 | |
381 | TEST("Forward months then backward months returns us to current year" , |
382 | g_date_get_year(d) == y); |
383 | |
384 | if (failed) |
385 | { |
386 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
387 | g_date_debug_print(d); |
388 | } |
389 | |
390 | |
391 | if (day < 29) |
392 | { |
393 | /* Day should be unchanged */ |
394 | |
395 | TEST("Forward months then backward months returns us to current day" , |
396 | g_date_get_day(d) == day); |
397 | |
398 | if (failed) |
399 | { |
400 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
401 | g_date_debug_print(d); |
402 | } |
403 | } |
404 | else |
405 | { |
406 | /* reset the day for later tests */ |
407 | g_date_set_day(date: d, day); |
408 | } |
409 | |
410 | /******* Years ********/ |
411 | |
412 | tmp = *d; |
413 | g_date_add_years(date: d, n_years: k); |
414 | |
415 | TEST("Adding years gives a larger value" , |
416 | g_date_compare(d,&tmp) > 0); |
417 | |
418 | g_date_subtract_years(date: d, n_years: k); |
419 | |
420 | TEST("Forward years then backward years returns us to current month" , |
421 | g_date_get_month(d) == m); |
422 | |
423 | if (failed) |
424 | { |
425 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
426 | g_date_debug_print(d); |
427 | } |
428 | |
429 | TEST("Forward years then backward years returns us to current year" , |
430 | g_date_get_year(d) == y); |
431 | |
432 | if (failed) |
433 | { |
434 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
435 | g_date_debug_print(d); |
436 | } |
437 | |
438 | if (m != 2 && day != 29) |
439 | { |
440 | TEST("Forward years then backward years returns us to current day" , |
441 | g_date_get_day(d) == day); |
442 | |
443 | if (failed) |
444 | { |
445 | g_print(format: " (increment %u, dmy %u %u %u) " , k, day, m, y); |
446 | g_date_debug_print(d); |
447 | } |
448 | } |
449 | else |
450 | { |
451 | g_date_set_day(date: d, day); /* reset */ |
452 | } |
453 | |
454 | k += 10; |
455 | } |
456 | |
457 | /***** increment test relative to our local Julian count */ |
458 | |
459 | if (!discontinuity) { |
460 | |
461 | /* We can only run sequence tests between sequential years */ |
462 | |
463 | TEST("Julians are sequential with increment 1" , |
464 | j+1 == g_date_get_julian(d)); |
465 | if (failed) |
466 | { |
467 | g_print(format: "Out of sequence, prev: %u expected: %u got: %u\n" , |
468 | j, j+1, g_date_get_julian(date: d)); |
469 | } |
470 | |
471 | g_date_add_days(date: d,n_days: 1); |
472 | TEST("Next day has julian 1 higher" , |
473 | g_date_get_julian(d) == j + 2); |
474 | g_date_subtract_days(date: d, n_days: 1); |
475 | |
476 | if (j != G_DATE_BAD_JULIAN) |
477 | { |
478 | g_date_subtract_days(date: d, n_days: 1); |
479 | |
480 | TEST("Previous day has julian 1 lower" , |
481 | g_date_get_julian(d) == j); |
482 | |
483 | g_date_add_days(date: d, n_days: 1); /* back to original */ |
484 | } |
485 | } |
486 | discontinuity = FALSE; /* goes away now */ |
487 | |
488 | fflush(stdout); |
489 | fflush(stderr); |
490 | |
491 | j = g_date_get_julian(date: d); /* inc current julian */ |
492 | |
493 | ++day; |
494 | } |
495 | ++m; |
496 | } |
497 | g_print(format: " done\n" ); |
498 | ++i; |
499 | if (i == n_check_years) |
500 | break; |
501 | prev_y = y; |
502 | y = check_years[i]; |
503 | if (prev_y == G_DATE_BAD_YEAR || |
504 | (prev_y + 1) != y) discontinuity = TRUE; |
505 | } |
506 | |
507 | |
508 | g_print(format: "\n%u tests passed, %u failed\n" ,passed, notpassed); |
509 | |
510 | return (notpassed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; |
511 | } |
512 | |