1 /* $NetBSD: t_parsedate.c,v 1.24 2016/05/05 02:12:21 kre Exp $ */ 2 /*- 3 * Copyright (c) 2010, 2015 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: t_parsedate.c,v 1.24 2016/05/05 02:12:21 kre Exp $"); 33 34 #include <atf-c.h> 35 #include <errno.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <time.h> 39 #include <util.h> 40 41 /* 42 * ANY is used as a placeholder for values that do not need to be 43 * checked. The actual value is arbitrary. We don't use -1 44 * because some tests might want to use -1 as a literal value. 45 */ 46 #define ANY -30215 47 48 /* parsecheck -- 49 * call parsedate(), then call time_to_tm() on the result, 50 * and check that year/month/day/hour/minute/second are as expected. 51 * 52 * time_to_tm should usually be localtime_r or gmtime_r. 53 * 54 * Don't check values specified as ANY. 55 */ 56 static void 57 parsecheck(const char *datestr, const time_t *reftime, const int *zoff, 58 struct tm * time_to_tm(const time_t *, struct tm *), 59 int year, int month, int day, int hour, int minute, int second) 60 { 61 time_t t; 62 struct tm tm; 63 char argstr[128]; 64 65 /* 66 * printable version of the args. 67 * 68 * Note that printf("%.*d", 0, 0)) prints nothing at all, 69 * while printf("%.*d", 1, val) prints the value as usual. 70 */ 71 snprintf(argstr, sizeof(argstr), "%s%s%s, %s%.*jd, %s%.*d", 72 /* NULL or \"<datestr>\" */ 73 (datestr ? "\"" : ""), 74 (datestr ? datestr : "NULL"), 75 (datestr ? "\"" : ""), 76 /* NULL or *reftime */ 77 (reftime ? "" : "NULL"), 78 (reftime ? 1 : 0), 79 (reftime ? (intmax_t)*reftime : (intmax_t)0), 80 /* NULL or *zoff */ 81 (zoff ? "" : "NULL"), 82 (zoff ? 1 : 0), 83 (zoff ? *zoff : 0)); 84 85 ATF_CHECK_MSG((t = parsedate(datestr, reftime, zoff)) != -1, 86 "parsedate(%s) returned -1\n", argstr); 87 ATF_CHECK(time_to_tm(&t, &tm) != NULL); 88 if (year != ANY) 89 ATF_CHECK_MSG(tm.tm_year + 1900 == year, 90 "parsedate(%s) expected year %d got %d (+1900)\n", 91 argstr, year, (int)tm.tm_year); 92 if (month != ANY) 93 ATF_CHECK_MSG(tm.tm_mon + 1 == month, 94 "parsedate(%s) expected month %d got %d (+1)\n", 95 argstr, month, (int)tm.tm_mon); 96 if (day != ANY) 97 ATF_CHECK_MSG(tm.tm_mday == day, 98 "parsedate(%s) expected day %d got %d\n", 99 argstr, day, (int)tm.tm_mday); 100 if (hour != ANY) 101 ATF_CHECK_MSG(tm.tm_hour == hour, 102 "parsedate(%s) expected hour %d got %d\n", 103 argstr, hour, (int)tm.tm_hour); 104 if (minute != ANY) 105 ATF_CHECK_MSG(tm.tm_min == minute, 106 "parsedate(%s) expected minute %d got %d\n", 107 argstr, minute, (int)tm.tm_min); 108 if (second != ANY) 109 ATF_CHECK_MSG(tm.tm_sec == second, 110 "parsedate(%s) expected second %d got %d\n", 111 argstr, second, (int)tm.tm_sec); 112 } 113 114 ATF_TC(dates); 115 116 ATF_TC_HEAD(dates, tc) 117 { 118 atf_tc_set_md_var(tc, "descr", "Test unambiguous dates" 119 " (PR lib/44255)"); 120 } 121 122 ATF_TC_BODY(dates, tc) 123 { 124 125 parsecheck("9/10/69", NULL, NULL, localtime_r, 126 2069, 9, 10, 0, 0, 0); /* year < 70: add 2000 */ 127 parsecheck("9/10/70", NULL, NULL, localtime_r, 128 1970, 9, 10, 0, 0, 0); /* 70 <= year < 100: add 1900 */ 129 parsecheck("69-09-10", NULL, NULL, localtime_r, 130 69, 9, 10, 0, 0, 0); /* ISO8601 year remains unchanged */ 131 parsecheck("70-09-10", NULL, NULL, localtime_r, 132 70, 9, 10, 0, 0, 0); /* ISO8601 year remains unchanged */ 133 parsecheck("2006-11-17", NULL, NULL, localtime_r, 134 2006, 11, 17, 0, 0, 0); 135 parsecheck("10/1/2000", NULL, NULL, localtime_r, 136 2000, 10, 1, 0, 0, 0); /* month/day/year */ 137 parsecheck("20 Jun 1994", NULL, NULL, localtime_r, 138 1994, 6, 20, 0, 0, 0); 139 parsecheck("97 September 2", NULL, NULL, localtime_r, 140 1997, 9, 2, 0, 0, 0); 141 parsecheck("23jun2001", NULL, NULL, localtime_r, 142 2001, 6, 23, 0, 0, 0); 143 parsecheck("1-sep-06", NULL, NULL, localtime_r, 144 2006, 9, 1, 0, 0, 0); 145 parsecheck("1/11", NULL, NULL, localtime_r, 146 ANY, 1, 11, 0, 0, 0); /* month/day */ 147 parsecheck("1500-01-02", NULL, NULL, localtime_r, 148 1500, 1, 2, 0, 0, 0); 149 parsecheck("9999-12-21", NULL, NULL, localtime_r, 150 9999, 12, 21, 0, 0, 0); 151 parsecheck("2015.12.07.08.07.35", NULL, NULL, localtime_r, 152 2015, 12, 7, 8, 7, 35); 153 } 154 155 ATF_TC(times); 156 157 ATF_TC_HEAD(times, tc) 158 { 159 atf_tc_set_md_var(tc, "descr", "Test times" 160 " (PR lib/44255)"); 161 } 162 163 ATF_TC_BODY(times, tc) 164 { 165 166 parsecheck("10:01", NULL, NULL, localtime_r, 167 ANY, ANY, ANY, 10, 1, 0); 168 parsecheck("10:12pm", NULL, NULL, localtime_r, 169 ANY, ANY, ANY, 22, 12, 0); 170 parsecheck("12:11:01.000012", NULL, NULL, localtime_r, 171 ANY, ANY, ANY, 12, 11, 1); 172 parsecheck("12:21-0500", NULL, NULL, gmtime_r, 173 ANY, ANY, ANY, 12+5, 21, 0); 174 /* numeric zones not permitted with am/pm ... */ 175 parsecheck("7 a.m. ICT", NULL, NULL, gmtime_r, 176 ANY, ANY, ANY, 7-7, 0, 0); 177 parsecheck("midnight", NULL, NULL, localtime_r, 178 ANY, ANY, ANY, 0, 0, 0); 179 parsecheck("mn", NULL, NULL, localtime_r, 180 ANY, ANY, ANY, 0, 0, 0); 181 parsecheck("noon", NULL, NULL, localtime_r, 182 ANY, ANY, ANY, 12, 0, 0); 183 parsecheck("dawn", NULL, NULL, localtime_r, 184 ANY, ANY, ANY, 6, 0, 0); 185 parsecheck("sunset", NULL, NULL, localtime_r, 186 ANY, ANY, ANY, 18, 0, 0); 187 } 188 189 ATF_TC(dsttimes); 190 191 ATF_TC_HEAD(dsttimes, tc) 192 { 193 atf_tc_set_md_var(tc, "descr", "Test DST transition times" 194 " (PR lib/47916)"); 195 } 196 197 ATF_TC_BODY(dsttimes, tc) 198 { 199 struct tm tm; 200 time_t t; 201 int tzoff; 202 203 putenv(__UNCONST("TZ=EST")); 204 tzset(); 205 parsecheck("12:0", NULL, NULL, localtime_r, 206 ANY, ANY, ANY, 12, 0, 0); 207 208 putenv(__UNCONST("TZ=Asia/Tokyo")); 209 tzset(); 210 parsecheck("12:0", NULL, NULL, localtime_r, 211 ANY, ANY, ANY, 12, 0, 0); 212 213 /* 214 * When the effective local time is Tue Jul 9 13:21:53 BST 2013, 215 * check mktime("14:00") 216 */ 217 putenv(__UNCONST("TZ=Europe/London")); 218 tzset(); 219 tm = (struct tm){ 220 .tm_year = 2013-1900, .tm_mon = 7-1, .tm_mday = 9, 221 .tm_hour = 13, .tm_min = 21, .tm_sec = 53, 222 .tm_isdst = 0 }; 223 t = mktime(&tm); 224 ATF_CHECK(t != (time_t)-1); 225 parsecheck("14:00", &t, NULL, localtime_r, 226 2013, 7, 9, 14, 0, 0); 227 tzoff = -60; /* British Summer Time */ 228 parsecheck("14:00", &t, &tzoff, localtime_r, 229 2013, 7, 9, 14, 0, 0); 230 } 231 232 ATF_TC(relative); 233 234 ATF_TC_HEAD(relative, tc) 235 { 236 atf_tc_set_md_var(tc, "descr", "Test relative items" 237 " (PR lib/44255)"); 238 } 239 240 ATF_TC_BODY(relative, tc) 241 { 242 struct tm tm; 243 time_t now; 244 245 #define REL_CHECK(s, now, tm) do { \ 246 time_t p, q; \ 247 char nb[30], pb[30], qb[30]; \ 248 p = parsedate(s, &now, NULL); \ 249 q = mktime(&tm); \ 250 ATF_CHECK_EQ_MSG(p, q, \ 251 "From %jd (%24.24s) using \"%s\", obtained %jd (%24.24s); expected %jd (%24.24s)", \ 252 (uintmax_t)now, ctime_r(&now, nb), \ 253 s, (uintmax_t)p, ctime_r(&p, pb), (uintmax_t)q, \ 254 ctime_r(&q, qb)); \ 255 } while (/*CONSTCOND*/0) 256 257 #define isleap(yr) (((yr) & 3) == 0 && (((yr) % 100) != 0 || \ 258 ((1900+(yr)) % 400) == 0)) 259 260 ATF_CHECK(parsedate("-1 month", NULL, NULL) != -1); 261 ATF_CHECK(parsedate("last friday", NULL, NULL) != -1); 262 ATF_CHECK(parsedate("one week ago", NULL, NULL) != -1); 263 ATF_CHECK(parsedate("this thursday", NULL, NULL) != -1); 264 ATF_CHECK(parsedate("next sunday", NULL, NULL) != -1); 265 ATF_CHECK(parsedate("+2 years", NULL, NULL) != -1); 266 267 /* 268 * Test relative to a number of fixed dates. Avoid the 269 * edges of the time_t range to avert under- or overflow 270 * of the relative date, and use a prime step for maximum 271 * coverage of different times of day/week/month/year. 272 */ 273 for (now = 0x00FFFFFF; now < 0xFF000000; now += 3777779) { 274 ATF_CHECK(localtime_r(&now, &tm) != NULL); 275 tm.tm_mday--; 276 /* "yesterday" leaves time untouched */ 277 tm.tm_isdst = -1; 278 REL_CHECK("yesterday", now, tm); 279 280 ATF_CHECK(localtime_r(&now, &tm) != NULL); 281 tm.tm_mday++; 282 /* as does "tomorrow" */ 283 tm.tm_isdst = -1; 284 REL_CHECK("tomorrow", now, tm); 285 286 ATF_CHECK(localtime_r(&now, &tm) != NULL); 287 if (tm.tm_wday > 4) 288 tm.tm_mday += 7; 289 tm.tm_mday += 4 - tm.tm_wday; 290 /* if a day name is mentioned, it means midnight (by default) */ 291 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 292 tm.tm_isdst = -1; 293 REL_CHECK("this thursday", now, tm); 294 295 ATF_CHECK(localtime_r(&now, &tm) != NULL); 296 tm.tm_mday += 14 - (tm.tm_wday ? tm.tm_wday : 7); 297 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 298 tm.tm_isdst = -1; 299 REL_CHECK("next sunday", now, tm); 300 301 ATF_CHECK(localtime_r(&now, &tm) != NULL); 302 if (tm.tm_wday <= 5) 303 tm.tm_mday -= 7; 304 tm.tm_mday += 5 - tm.tm_wday; 305 tm.tm_sec = tm.tm_min = 0; 306 tm.tm_hour = 16; 307 tm.tm_isdst = -1; 308 REL_CHECK("last friday 4 p.m.", now, tm); 309 310 ATF_CHECK(localtime_r(&now, &tm) != NULL); 311 tm.tm_mday += 14; 312 if (tm.tm_wday > 3) 313 tm.tm_mday += 7; 314 tm.tm_mday += 3 - tm.tm_wday; 315 tm.tm_sec = tm.tm_min = 0; 316 tm.tm_hour = 3; 317 tm.tm_isdst = -1; 318 REL_CHECK("we fortnight 3 a.m.", now, tm); 319 320 ATF_CHECK(localtime_r(&now, &tm) != NULL); 321 tm.tm_min -= 5; 322 tm.tm_isdst = -1; 323 REL_CHECK("5 minutes ago", now, tm); 324 325 ATF_CHECK(localtime_r(&now, &tm) != NULL); 326 tm.tm_hour++; 327 tm.tm_min += 37; 328 tm.tm_isdst = -1; 329 REL_CHECK("97 minutes", now, tm); 330 331 ATF_CHECK(localtime_r(&now, &tm) != NULL); 332 tm.tm_mon++; 333 if (tm.tm_mon == 1 && 334 tm.tm_mday > 28 + isleap(tm.tm_year)) 335 tm.tm_mday = 28 + isleap(tm.tm_year); 336 else if ((tm.tm_mon == 3 || tm.tm_mon == 5 || 337 tm.tm_mon == 8 || tm.tm_mon == 10) && tm.tm_mday == 31) 338 tm.tm_mday = 30; 339 tm.tm_isdst = -1; 340 REL_CHECK("month", now, tm); 341 342 ATF_CHECK(localtime_r(&now, &tm) != NULL); 343 tm.tm_mon += 2; /* "next" means add 2 ... */ 344 if (tm.tm_mon == 13 && 345 tm.tm_mday > 28 + isleap(tm.tm_year + 1)) 346 tm.tm_mday = 28 + isleap(tm.tm_year + 1); 347 else if (tm.tm_mon == 8 && tm.tm_mday == 31) 348 tm.tm_mday = 30; 349 tm.tm_isdst = -1; 350 REL_CHECK("next month", now, tm); 351 352 ATF_CHECK(localtime_r(&now, &tm) != NULL); 353 tm.tm_mon--; 354 if (tm.tm_mon == 1 && 355 tm.tm_mday > 28 + isleap(tm.tm_year)) 356 tm.tm_mday = 28 + isleap(tm.tm_year); 357 else if ((tm.tm_mon == 3 || tm.tm_mon == 5 || 358 tm.tm_mon == 8 || tm.tm_mon == 10) && tm.tm_mday == 31) 359 tm.tm_mday = 30; 360 tm.tm_isdst = -1; 361 REL_CHECK("last month", now, tm); 362 363 ATF_CHECK(localtime_r(&now, &tm) != NULL); 364 tm.tm_mon += 6; 365 if (tm.tm_mon == 13 && 366 tm.tm_mday > 28 + isleap(tm.tm_year + 1)) 367 tm.tm_mday = 28 + isleap(tm.tm_year + 1); 368 else if ((tm.tm_mon == 15 || tm.tm_mon == 17 || 369 tm.tm_mon == 8 || tm.tm_mon == 10) && tm.tm_mday == 31) 370 tm.tm_mday = 30; 371 tm.tm_mday += 2; 372 tm.tm_isdst = -1; 373 REL_CHECK("+6 months 2 days", now, tm); 374 375 ATF_CHECK(localtime_r(&now, &tm) != NULL); 376 tm.tm_mon -= 9; 377 if (tm.tm_mon == 1 && tm.tm_mday > 28 + isleap(tm.tm_year)) 378 tm.tm_mday = 28 + isleap(tm.tm_year); 379 else if ((tm.tm_mon == -9 || tm.tm_mon == -7 || 380 tm.tm_mon == -2) && tm.tm_mday == 31) 381 tm.tm_mday = 30; 382 tm.tm_isdst = -1; 383 REL_CHECK("9 months ago", now, tm); 384 385 ATF_CHECK(localtime_r(&now, &tm) != NULL); 386 if (tm.tm_wday <= 2) 387 tm.tm_mday -= 7; 388 tm.tm_mday += 2 - tm.tm_wday; 389 tm.tm_isdst = -1; 390 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 391 REL_CHECK("1 week ago Tu", now, tm); 392 393 ATF_CHECK(localtime_r(&now, &tm) != NULL); 394 tm.tm_isdst = -1; 395 tm.tm_mday++; 396 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 397 REL_CHECK("midnight tomorrow", now, tm); 398 399 ATF_CHECK(localtime_r(&now, &tm) != NULL); 400 tm.tm_isdst = -1; 401 tm.tm_mday++; 402 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 403 REL_CHECK("tomorrow midnight", now, tm); 404 405 ATF_CHECK(localtime_r(&now, &tm) != NULL); 406 tm.tm_isdst = -1; 407 tm.tm_mday++; 408 tm.tm_hour = 12; 409 tm.tm_min = tm.tm_sec = 0; 410 REL_CHECK("noon tomorrow", now, tm); 411 412 ATF_CHECK(localtime_r(&now, &tm) != NULL); 413 if (tm.tm_wday > 2) 414 tm.tm_mday += 7; 415 tm.tm_mday += 2 - tm.tm_wday; 416 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 417 tm.tm_isdst = -1; 418 REL_CHECK("midnight Tuesday", now, tm); 419 420 ATF_CHECK(localtime_r(&now, &tm) != NULL); 421 if (tm.tm_wday > 2 + 1) 422 tm.tm_mday += 7; 423 tm.tm_mday += 2 - tm.tm_wday; 424 tm.tm_mday++; /* xxx midnight --> the next day */ 425 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 426 tm.tm_isdst = -1; 427 REL_CHECK("Tuesday midnight", now, tm); 428 } 429 } 430 431 ATF_TC(atsecs); 432 433 ATF_TC_HEAD(atsecs, tc) 434 { 435 atf_tc_set_md_var(tc, "descr", "Test seconds past the epoch"); 436 } 437 438 ATF_TC_BODY(atsecs, tc) 439 { 440 int tzoff; 441 442 /* "@0" -> (time_t)0, regardless of timezone */ 443 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 444 putenv(__UNCONST("TZ=Europe/Berlin")); 445 tzset(); 446 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 447 putenv(__UNCONST("TZ=America/New_York")); 448 tzset(); 449 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 450 tzoff = 0; 451 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 452 tzoff = 3600; 453 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 454 tzoff = -3600; 455 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 456 457 /* -1 or other negative numbers are not errors */ 458 errno = 0; 459 ATF_CHECK(parsedate("@-1", NULL, &tzoff) == (time_t)-1 && errno == 0); 460 ATF_CHECK(parsedate("@-2", NULL, &tzoff) == (time_t)-2 && errno == 0); 461 462 /* junk is an error */ 463 errno = 0; 464 ATF_CHECK(parsedate("@junk", NULL, NULL) == (time_t)-1 && errno != 0); 465 } 466 467 ATF_TC(zones); 468 469 ATF_TC_HEAD(zones, tc) 470 { 471 atf_tc_set_md_var(tc, "descr", "Test parsing dates with zones"); 472 } 473 474 ATF_TC_BODY(zones, tc) 475 { 476 parsecheck("2015-12-06 16:11:48 UTC", NULL, NULL, gmtime_r, 477 2015, 12, 6, 16, 11, 48); 478 parsecheck("2015-12-06 16:11:48 UT", NULL, NULL, gmtime_r, 479 2015, 12, 6, 16, 11, 48); 480 parsecheck("2015-12-06 16:11:48 GMT", NULL, NULL, gmtime_r, 481 2015, 12, 6, 16, 11, 48); 482 parsecheck("2015-12-06 16:11:48 +0000", NULL, NULL, gmtime_r, 483 2015, 12, 6, 16, 11, 48); 484 485 parsecheck("2015-12-06 16:11:48 -0500", NULL, NULL, gmtime_r, 486 2015, 12, 6, 21, 11, 48); 487 parsecheck("2015-12-06 16:11:48 EST", NULL, NULL, gmtime_r, 488 2015, 12, 6, 21, 11, 48); 489 parsecheck("2015-12-06 16:11:48 EDT", NULL, NULL, gmtime_r, 490 2015, 12, 6, 20, 11, 48); 491 parsecheck("2015-12-06 16:11:48 +0500", NULL, NULL, gmtime_r, 492 2015, 12, 6, 11, 11, 48); 493 494 parsecheck("2015-12-06 16:11:48 +1000", NULL, NULL, gmtime_r, 495 2015, 12, 6, 6, 11, 48); 496 parsecheck("2015-12-06 16:11:48 AEST", NULL, NULL, gmtime_r, 497 2015, 12, 6, 6, 11, 48); 498 parsecheck("2015-12-06 16:11:48 -1000", NULL, NULL, gmtime_r, 499 2015, 12, 7, 2, 11, 48); 500 parsecheck("2015-12-06 16:11:48 HST", NULL, NULL, gmtime_r, 501 2015, 12, 7, 2, 11, 48); 502 503 parsecheck("2015-12-06 16:11:48 AWST", NULL, NULL, gmtime_r, 504 2015, 12, 6, 8, 11, 48); 505 parsecheck("2015-12-06 16:11:48 NZDT", NULL, NULL, gmtime_r, 506 2015, 12, 6, 3, 11, 48); 507 508 parsecheck("Sun, 6 Dec 2015 09:43:16 -0500", NULL, NULL, gmtime_r, 509 2015, 12, 6, 14, 43, 16); 510 parsecheck("Mon Dec 7 03:13:31 ICT 2015", NULL, NULL, gmtime_r, 511 2015, 12, 6, 20, 13, 31); 512 /* the day name is ignored when a day of month (etc) is given... */ 513 parsecheck("Sat Dec 7 03:13:31 ICT 2015", NULL, NULL, gmtime_r, 514 2015, 12, 6, 20, 13, 31); 515 516 517 parsecheck("2015-12-06 12:00:00 IDLW", NULL, NULL, gmtime_r, 518 2015, 12, 7, 0, 0, 0); 519 parsecheck("2015-12-06 12:00:00 IDLE", NULL, NULL, gmtime_r, 520 2015, 12, 6, 0, 0, 0); 521 522 parsecheck("2015-12-06 21:17:33 NFT", NULL, NULL, gmtime_r, 523 2015, 12, 7, 0, 47, 33); 524 parsecheck("2015-12-06 21:17:33 ACST", NULL, NULL, gmtime_r, 525 2015, 12, 6, 11, 47, 33); 526 parsecheck("2015-12-06 21:17:33 +0717", NULL, NULL, gmtime_r, 527 2015, 12, 6, 14, 0, 33); 528 529 parsecheck("2015-12-06 21:21:21 Z", NULL, NULL, gmtime_r, 530 2015, 12, 6, 21, 21, 21); 531 parsecheck("2015-12-06 21:21:21 A", NULL, NULL, gmtime_r, 532 2015, 12, 6, 22, 21, 21); 533 parsecheck("2015-12-06 21:21:21 G", NULL, NULL, gmtime_r, 534 2015, 12, 7, 4, 21, 21); 535 parsecheck("2015-12-06 21:21:21 M", NULL, NULL, gmtime_r, 536 2015, 12, 7, 9, 21, 21); 537 parsecheck("2015-12-06 21:21:21 N", NULL, NULL, gmtime_r, 538 2015, 12, 6, 20, 21, 21); 539 parsecheck("2015-12-06 21:21:21 T", NULL, NULL, gmtime_r, 540 2015, 12, 6, 14, 21, 21); 541 parsecheck("2015-12-06 21:21:21 Y", NULL, NULL, gmtime_r, 542 2015, 12, 6, 9, 21, 21); 543 544 } 545 546 ATF_TC(gibberish); 547 548 ATF_TC_HEAD(gibberish, tc) 549 { 550 atf_tc_set_md_var(tc, "descr", "Test (not) parsing nonsense"); 551 } 552 553 ATF_TC_BODY(gibberish, tc) 554 { 555 errno = 0; 556 ATF_CHECK(parsedate("invalid nonsense", NULL, NULL) == (time_t)-1 557 && errno != 0); 558 errno = 0; 559 ATF_CHECK(parsedate("12th day of Christmas", NULL, NULL) == (time_t)-1 560 && errno != 0); 561 errno = 0; 562 ATF_CHECK(parsedate("2015-31-07 15:00", NULL, NULL) == (time_t)-1 563 && errno != 0); 564 errno = 0; 565 ATF_CHECK(parsedate("2015-02-29 10:01", NULL, NULL) == (time_t)-1 566 && errno != 0); 567 errno = 0; 568 ATF_CHECK(parsedate("2015-12-06 24:01", NULL, NULL) == (time_t)-1 569 && errno != 0); 570 errno = 0; 571 ATF_CHECK(parsedate("2015-12-06 14:61", NULL, NULL) == (time_t)-1 572 && errno != 0); 573 } 574 575 ATF_TP_ADD_TCS(tp) 576 { 577 ATF_TP_ADD_TC(tp, dates); 578 ATF_TP_ADD_TC(tp, times); 579 ATF_TP_ADD_TC(tp, dsttimes); 580 ATF_TP_ADD_TC(tp, relative); 581 ATF_TP_ADD_TC(tp, atsecs); 582 ATF_TP_ADD_TC(tp, zones); 583 ATF_TP_ADD_TC(tp, gibberish); 584 585 return atf_no_error(); 586 } 587 588