1 /* $NetBSD: t_parsedate.c,v 1.19 2015/12/31 10:56:13 dholland 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.19 2015/12/31 10:56:13 dholland 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 pb[30], qb[30]; \ 248 p = parsedate(s, &now, NULL); \ 249 q = mktime(&tm); \ 250 ATF_CHECK_EQ_MSG(p, q, \ 251 "From \"%s\", obtained %jd (%24.24s); expected %jd (%24.24s)", \ 252 s, (uintmax_t)p, ctime_r(&p, pb), (uintmax_t)q, \ 253 ctime_r(&q, qb)); \ 254 } while (/*CONSTCOND*/0) 255 256 ATF_CHECK(parsedate("-1 month", NULL, NULL) != -1); 257 ATF_CHECK(parsedate("last friday", NULL, NULL) != -1); 258 ATF_CHECK(parsedate("one week ago", NULL, NULL) != -1); 259 ATF_CHECK(parsedate("this thursday", NULL, NULL) != -1); 260 ATF_CHECK(parsedate("next sunday", NULL, NULL) != -1); 261 ATF_CHECK(parsedate("+2 years", NULL, NULL) != -1); 262 263 (void)time(&now); 264 265 ATF_CHECK(localtime_r(&now, &tm) != NULL); 266 tm.tm_mday--; 267 /* "yesterday" leaves time untouched */ 268 tm.tm_isdst = -1; 269 REL_CHECK("yesterday", now, tm); 270 271 ATF_CHECK(localtime_r(&now, &tm) != NULL); 272 tm.tm_mday++; 273 /* as does "tomorrow" */ 274 tm.tm_isdst = -1; 275 REL_CHECK("tomorrow", now, tm); 276 277 ATF_CHECK(localtime_r(&now, &tm) != NULL); 278 if (tm.tm_wday > 4) 279 tm.tm_mday += 7; 280 tm.tm_mday += 4 - tm.tm_wday; 281 /* if a day name is mentioned, it means midnight (by default) */ 282 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 283 tm.tm_isdst = -1; 284 REL_CHECK("this thursday", now, tm); 285 286 ATF_CHECK(localtime_r(&now, &tm) != NULL); 287 tm.tm_mday += 14 - (tm.tm_wday ? tm.tm_wday : 7); 288 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 289 tm.tm_isdst = -1; 290 REL_CHECK("next sunday", now, tm); 291 292 ATF_CHECK(localtime_r(&now, &tm) != NULL); 293 if (tm.tm_wday <= 5) 294 tm.tm_mday -= 7; 295 tm.tm_mday += 5 - tm.tm_wday; 296 tm.tm_sec = tm.tm_min = 0; 297 tm.tm_hour = 16; 298 tm.tm_isdst = -1; 299 REL_CHECK("last friday 4 p.m.", now, tm); 300 301 ATF_CHECK(localtime_r(&now, &tm) != NULL); 302 tm.tm_mday += 14; 303 if (tm.tm_wday > 3) 304 tm.tm_mday += 7; 305 tm.tm_mday += 3 - tm.tm_wday; 306 tm.tm_sec = tm.tm_min = 0; 307 tm.tm_hour = 3; 308 tm.tm_isdst = -1; 309 REL_CHECK("we fortnight 3 a.m.", now, tm); 310 311 ATF_CHECK(localtime_r(&now, &tm) != NULL); 312 tm.tm_min -= 5; 313 tm.tm_isdst = -1; 314 REL_CHECK("5 minutes ago", now, tm); 315 316 ATF_CHECK(localtime_r(&now, &tm) != NULL); 317 tm.tm_hour++; 318 tm.tm_min += 37; 319 tm.tm_isdst = -1; 320 REL_CHECK("97 minutes", now, tm); 321 322 ATF_CHECK(localtime_r(&now, &tm) != NULL); 323 tm.tm_mon++; 324 tm.tm_isdst = -1; 325 REL_CHECK("month", now, tm); 326 327 ATF_CHECK(localtime_r(&now, &tm) != NULL); 328 tm.tm_mon += 2; /* "next" means add 2 ... */ 329 tm.tm_isdst = -1; 330 REL_CHECK("next month", now, tm); 331 332 ATF_CHECK(localtime_r(&now, &tm) != NULL); 333 tm.tm_mon--; 334 tm.tm_isdst = -1; 335 REL_CHECK("last month", now, tm); 336 337 ATF_CHECK(localtime_r(&now, &tm) != NULL); 338 tm.tm_mon += 6; 339 tm.tm_mday += 2; 340 tm.tm_isdst = -1; 341 REL_CHECK("+6 months 2 days", now, tm); 342 343 ATF_CHECK(localtime_r(&now, &tm) != NULL); 344 tm.tm_mon -= 9; 345 tm.tm_isdst = -1; 346 REL_CHECK("9 months ago", now, tm); 347 348 ATF_CHECK(localtime_r(&now, &tm) != NULL); 349 if (tm.tm_wday <= 2) 350 tm.tm_mday -= 7; 351 tm.tm_mday += 2 - tm.tm_wday; 352 tm.tm_isdst = -1; 353 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 354 REL_CHECK("1 week ago Tu", now, tm); 355 356 ATF_CHECK(localtime_r(&now, &tm) != NULL); 357 tm.tm_isdst = -1; 358 tm.tm_mday++; 359 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 360 REL_CHECK("midnight tomorrow", now, tm); 361 362 ATF_CHECK(localtime_r(&now, &tm) != NULL); 363 tm.tm_isdst = -1; 364 tm.tm_mday++; 365 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 366 REL_CHECK("tomorrow midnight", now, tm); 367 368 ATF_CHECK(localtime_r(&now, &tm) != NULL); 369 tm.tm_isdst = -1; 370 tm.tm_mday++; 371 tm.tm_hour = 12; 372 tm.tm_min = tm.tm_sec = 0; 373 REL_CHECK("noon tomorrow", now, tm); 374 375 ATF_CHECK(localtime_r(&now, &tm) != NULL); 376 if (tm.tm_wday > 2) 377 tm.tm_mday += 7; 378 tm.tm_mday += 2 - tm.tm_wday; 379 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 380 tm.tm_isdst = -1; 381 REL_CHECK("midnight Tuesday", now, tm); 382 383 ATF_CHECK(localtime_r(&now, &tm) != NULL); 384 if (tm.tm_wday > 2 + 1) 385 tm.tm_mday += 7; 386 tm.tm_mday += 2 - tm.tm_wday; 387 tm.tm_mday++; /* xxx midnight --> the next day */ 388 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 389 tm.tm_isdst = -1; 390 REL_CHECK("Tuesday midnight", now, tm); 391 } 392 393 ATF_TC(atsecs); 394 395 ATF_TC_HEAD(atsecs, tc) 396 { 397 atf_tc_set_md_var(tc, "descr", "Test seconds past the epoch"); 398 } 399 400 ATF_TC_BODY(atsecs, tc) 401 { 402 int tzoff; 403 404 /* "@0" -> (time_t)0, regardless of timezone */ 405 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 406 putenv(__UNCONST("TZ=Europe/Berlin")); 407 tzset(); 408 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 409 putenv(__UNCONST("TZ=America/New_York")); 410 tzset(); 411 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 412 tzoff = 0; 413 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 414 tzoff = 3600; 415 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 416 tzoff = -3600; 417 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 418 419 /* -1 or other negative numbers are not errors */ 420 errno = 0; 421 ATF_CHECK(parsedate("@-1", NULL, &tzoff) == (time_t)-1 && errno == 0); 422 ATF_CHECK(parsedate("@-2", NULL, &tzoff) == (time_t)-2 && errno == 0); 423 424 /* junk is an error */ 425 errno = 0; 426 ATF_CHECK(parsedate("@junk", NULL, NULL) == (time_t)-1 && errno != 0); 427 } 428 429 ATF_TC(zones); 430 431 ATF_TC_HEAD(zones, tc) 432 { 433 atf_tc_set_md_var(tc, "descr", "Test parsing dates with zones"); 434 } 435 436 ATF_TC_BODY(zones, tc) 437 { 438 parsecheck("2015-12-06 16:11:48 UTC", NULL, NULL, gmtime_r, 439 2015, 12, 6, 16, 11, 48); 440 parsecheck("2015-12-06 16:11:48 UT", NULL, NULL, gmtime_r, 441 2015, 12, 6, 16, 11, 48); 442 parsecheck("2015-12-06 16:11:48 GMT", NULL, NULL, gmtime_r, 443 2015, 12, 6, 16, 11, 48); 444 parsecheck("2015-12-06 16:11:48 +0000", NULL, NULL, gmtime_r, 445 2015, 12, 6, 16, 11, 48); 446 447 parsecheck("2015-12-06 16:11:48 -0500", NULL, NULL, gmtime_r, 448 2015, 12, 6, 21, 11, 48); 449 parsecheck("2015-12-06 16:11:48 EST", NULL, NULL, gmtime_r, 450 2015, 12, 6, 21, 11, 48); 451 parsecheck("2015-12-06 16:11:48 EDT", NULL, NULL, gmtime_r, 452 2015, 12, 6, 20, 11, 48); 453 parsecheck("2015-12-06 16:11:48 +0500", NULL, NULL, gmtime_r, 454 2015, 12, 6, 11, 11, 48); 455 456 parsecheck("2015-12-06 16:11:48 +1000", NULL, NULL, gmtime_r, 457 2015, 12, 6, 6, 11, 48); 458 parsecheck("2015-12-06 16:11:48 AEST", NULL, NULL, gmtime_r, 459 2015, 12, 6, 6, 11, 48); 460 parsecheck("2015-12-06 16:11:48 -1000", NULL, NULL, gmtime_r, 461 2015, 12, 7, 2, 11, 48); 462 parsecheck("2015-12-06 16:11:48 HST", NULL, NULL, gmtime_r, 463 2015, 12, 7, 2, 11, 48); 464 465 parsecheck("2015-12-06 16:11:48 AWST", NULL, NULL, gmtime_r, 466 2015, 12, 6, 8, 11, 48); 467 parsecheck("2015-12-06 16:11:48 NZDT", NULL, NULL, gmtime_r, 468 2015, 12, 6, 3, 11, 48); 469 470 parsecheck("Sun, 6 Dec 2015 09:43:16 -0500", NULL, NULL, gmtime_r, 471 2015, 12, 6, 14, 43, 16); 472 parsecheck("Mon Dec 7 03:13:31 ICT 2015", NULL, NULL, gmtime_r, 473 2015, 12, 6, 20, 13, 31); 474 /* the day name is ignored when a day of month (etc) is given... */ 475 parsecheck("Sat Dec 7 03:13:31 ICT 2015", NULL, NULL, gmtime_r, 476 2015, 12, 6, 20, 13, 31); 477 478 479 parsecheck("2015-12-06 12:00:00 IDLW", NULL, NULL, gmtime_r, 480 2015, 12, 7, 0, 0, 0); 481 parsecheck("2015-12-06 12:00:00 IDLE", NULL, NULL, gmtime_r, 482 2015, 12, 6, 0, 0, 0); 483 484 parsecheck("2015-12-06 21:17:33 NFT", NULL, NULL, gmtime_r, 485 2015, 12, 7, 0, 47, 33); 486 parsecheck("2015-12-06 21:17:33 ACST", NULL, NULL, gmtime_r, 487 2015, 12, 6, 11, 47, 33); 488 parsecheck("2015-12-06 21:17:33 +0717", NULL, NULL, gmtime_r, 489 2015, 12, 6, 14, 0, 33); 490 491 parsecheck("2015-12-06 21:21:21 Z", NULL, NULL, gmtime_r, 492 2015, 12, 6, 21, 21, 21); 493 parsecheck("2015-12-06 21:21:21 A", NULL, NULL, gmtime_r, 494 2015, 12, 6, 22, 21, 21); 495 parsecheck("2015-12-06 21:21:21 G", NULL, NULL, gmtime_r, 496 2015, 12, 7, 4, 21, 21); 497 parsecheck("2015-12-06 21:21:21 M", NULL, NULL, gmtime_r, 498 2015, 12, 7, 9, 21, 21); 499 parsecheck("2015-12-06 21:21:21 N", NULL, NULL, gmtime_r, 500 2015, 12, 6, 20, 21, 21); 501 parsecheck("2015-12-06 21:21:21 T", NULL, NULL, gmtime_r, 502 2015, 12, 6, 14, 21, 21); 503 parsecheck("2015-12-06 21:21:21 Y", NULL, NULL, gmtime_r, 504 2015, 12, 6, 9, 21, 21); 505 506 } 507 508 ATF_TC(gibberish); 509 510 ATF_TC_HEAD(gibberish, tc) 511 { 512 atf_tc_set_md_var(tc, "descr", "Test (not) parsing nonsense"); 513 } 514 515 ATF_TC_BODY(gibberish, tc) 516 { 517 errno = 0; 518 ATF_CHECK(parsedate("invalid nonsense", NULL, NULL) == (time_t)-1 519 && errno != 0); 520 errno = 0; 521 ATF_CHECK(parsedate("12th day of Christmas", NULL, NULL) == (time_t)-1 522 && errno != 0); 523 errno = 0; 524 ATF_CHECK(parsedate("2015-31-07 15:00", NULL, NULL) == (time_t)-1 525 && errno != 0); 526 errno = 0; 527 ATF_CHECK(parsedate("2015-02-29 10:01", NULL, NULL) == (time_t)-1 528 && errno != 0); 529 errno = 0; 530 ATF_CHECK(parsedate("2015-12-06 24:01", NULL, NULL) == (time_t)-1 531 && errno != 0); 532 errno = 0; 533 ATF_CHECK(parsedate("2015-12-06 14:61", NULL, NULL) == (time_t)-1 534 && errno != 0); 535 } 536 537 ATF_TP_ADD_TCS(tp) 538 { 539 ATF_TP_ADD_TC(tp, dates); 540 ATF_TP_ADD_TC(tp, times); 541 ATF_TP_ADD_TC(tp, dsttimes); 542 ATF_TP_ADD_TC(tp, relative); 543 ATF_TP_ADD_TC(tp, atsecs); 544 ATF_TP_ADD_TC(tp, zones); 545 ATF_TP_ADD_TC(tp, gibberish); 546 547 return atf_no_error(); 548 } 549 550