1 /* $NetBSD: t_parsedate.c,v 1.25 2016/06/22 15:01:38 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.25 2016/06/22 15:01:38 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 } 184 185 ATF_TC(dsttimes); 186 187 ATF_TC_HEAD(dsttimes, tc) 188 { 189 atf_tc_set_md_var(tc, "descr", "Test DST transition times" 190 " (PR lib/47916)"); 191 } 192 193 ATF_TC_BODY(dsttimes, tc) 194 { 195 struct tm tm; 196 time_t t; 197 int tzoff; 198 199 putenv(__UNCONST("TZ=EST")); 200 tzset(); 201 parsecheck("12:0", NULL, NULL, localtime_r, 202 ANY, ANY, ANY, 12, 0, 0); 203 204 putenv(__UNCONST("TZ=Asia/Tokyo")); 205 tzset(); 206 parsecheck("12:0", NULL, NULL, localtime_r, 207 ANY, ANY, ANY, 12, 0, 0); 208 209 /* 210 * When the effective local time is Tue Jul 9 13:21:53 BST 2013, 211 * check mktime("14:00") 212 */ 213 putenv(__UNCONST("TZ=Europe/London")); 214 tzset(); 215 tm = (struct tm){ 216 .tm_year = 2013-1900, .tm_mon = 7-1, .tm_mday = 9, 217 .tm_hour = 13, .tm_min = 21, .tm_sec = 53, 218 .tm_isdst = 0 }; 219 t = mktime(&tm); 220 ATF_CHECK(t != (time_t)-1); 221 parsecheck("14:00", &t, NULL, localtime_r, 222 2013, 7, 9, 14, 0, 0); 223 tzoff = -60; /* British Summer Time */ 224 parsecheck("14:00", &t, &tzoff, localtime_r, 225 2013, 7, 9, 14, 0, 0); 226 } 227 228 ATF_TC(relative); 229 230 ATF_TC_HEAD(relative, tc) 231 { 232 atf_tc_set_md_var(tc, "descr", "Test relative items" 233 " (PR lib/44255)"); 234 } 235 236 ATF_TC_BODY(relative, tc) 237 { 238 struct tm tm; 239 time_t now; 240 241 #define REL_CHECK(s, now, tm) do { \ 242 time_t p, q; \ 243 char nb[30], pb[30], qb[30]; \ 244 p = parsedate(s, &now, NULL); \ 245 q = mktime(&tm); \ 246 ATF_CHECK_EQ_MSG(p, q, \ 247 "From %jd (%24.24s) using \"%s\", obtained %jd (%24.24s); expected %jd (%24.24s)", \ 248 (uintmax_t)now, ctime_r(&now, nb), \ 249 s, (uintmax_t)p, ctime_r(&p, pb), (uintmax_t)q, \ 250 ctime_r(&q, qb)); \ 251 } while (/*CONSTCOND*/0) 252 253 #define isleap(yr) (((yr) & 3) == 0 && (((yr) % 100) != 0 || \ 254 ((1900+(yr)) % 400) == 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 /* 264 * Test relative to a number of fixed dates. Avoid the 265 * edges of the time_t range to avert under- or overflow 266 * of the relative date, and use a prime step for maximum 267 * coverage of different times of day/week/month/year. 268 */ 269 for (now = 0x00FFFFFF; now < 0xFF000000; now += 3777779) { 270 ATF_CHECK(localtime_r(&now, &tm) != NULL); 271 tm.tm_mday--; 272 /* "yesterday" leaves time untouched */ 273 tm.tm_isdst = -1; 274 REL_CHECK("yesterday", now, tm); 275 276 ATF_CHECK(localtime_r(&now, &tm) != NULL); 277 tm.tm_mday++; 278 /* as does "tomorrow" */ 279 tm.tm_isdst = -1; 280 REL_CHECK("tomorrow", now, tm); 281 282 ATF_CHECK(localtime_r(&now, &tm) != NULL); 283 if (tm.tm_wday > 4) 284 tm.tm_mday += 7; 285 tm.tm_mday += 4 - tm.tm_wday; 286 /* if a day name is mentioned, it means midnight (by default) */ 287 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 288 tm.tm_isdst = -1; 289 REL_CHECK("this thursday", now, tm); 290 291 ATF_CHECK(localtime_r(&now, &tm) != NULL); 292 tm.tm_mday += 14 - (tm.tm_wday ? tm.tm_wday : 7); 293 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 294 tm.tm_isdst = -1; 295 REL_CHECK("next sunday", now, tm); 296 297 ATF_CHECK(localtime_r(&now, &tm) != NULL); 298 if (tm.tm_wday <= 5) 299 tm.tm_mday -= 7; 300 tm.tm_mday += 5 - tm.tm_wday; 301 tm.tm_sec = tm.tm_min = 0; 302 tm.tm_hour = 16; 303 tm.tm_isdst = -1; 304 REL_CHECK("last friday 4 p.m.", now, tm); 305 306 ATF_CHECK(localtime_r(&now, &tm) != NULL); 307 tm.tm_mday += 14; 308 if (tm.tm_wday > 3) 309 tm.tm_mday += 7; 310 tm.tm_mday += 3 - tm.tm_wday; 311 tm.tm_sec = tm.tm_min = 0; 312 tm.tm_hour = 3; 313 tm.tm_isdst = -1; 314 REL_CHECK("we fortnight 3 a.m.", now, tm); 315 316 ATF_CHECK(localtime_r(&now, &tm) != NULL); 317 tm.tm_min -= 5; 318 tm.tm_isdst = -1; 319 REL_CHECK("5 minutes ago", now, tm); 320 321 ATF_CHECK(localtime_r(&now, &tm) != NULL); 322 tm.tm_hour++; 323 tm.tm_min += 37; 324 tm.tm_isdst = -1; 325 REL_CHECK("97 minutes", now, tm); 326 327 ATF_CHECK(localtime_r(&now, &tm) != NULL); 328 tm.tm_mon++; 329 if (tm.tm_mon == 1 && 330 tm.tm_mday > 28 + isleap(tm.tm_year)) 331 tm.tm_mday = 28 + isleap(tm.tm_year); 332 else if ((tm.tm_mon == 3 || tm.tm_mon == 5 || 333 tm.tm_mon == 8 || tm.tm_mon == 10) && tm.tm_mday == 31) 334 tm.tm_mday = 30; 335 tm.tm_isdst = -1; 336 REL_CHECK("month", now, tm); 337 338 ATF_CHECK(localtime_r(&now, &tm) != NULL); 339 tm.tm_mon += 2; /* "next" means add 2 ... */ 340 if (tm.tm_mon == 13 && 341 tm.tm_mday > 28 + isleap(tm.tm_year + 1)) 342 tm.tm_mday = 28 + isleap(tm.tm_year + 1); 343 else if (tm.tm_mon == 8 && tm.tm_mday == 31) 344 tm.tm_mday = 30; 345 tm.tm_isdst = -1; 346 REL_CHECK("next month", now, tm); 347 348 ATF_CHECK(localtime_r(&now, &tm) != NULL); 349 tm.tm_mon--; 350 if (tm.tm_mon == 1 && 351 tm.tm_mday > 28 + isleap(tm.tm_year)) 352 tm.tm_mday = 28 + isleap(tm.tm_year); 353 else if ((tm.tm_mon == 3 || tm.tm_mon == 5 || 354 tm.tm_mon == 8 || tm.tm_mon == 10) && tm.tm_mday == 31) 355 tm.tm_mday = 30; 356 tm.tm_isdst = -1; 357 REL_CHECK("last month", now, tm); 358 359 ATF_CHECK(localtime_r(&now, &tm) != NULL); 360 tm.tm_mon += 6; 361 if (tm.tm_mon == 13 && 362 tm.tm_mday > 28 + isleap(tm.tm_year + 1)) 363 tm.tm_mday = 28 + isleap(tm.tm_year + 1); 364 else if ((tm.tm_mon == 15 || tm.tm_mon == 17 || 365 tm.tm_mon == 8 || tm.tm_mon == 10) && tm.tm_mday == 31) 366 tm.tm_mday = 30; 367 tm.tm_mday += 2; 368 tm.tm_isdst = -1; 369 REL_CHECK("+6 months 2 days", now, tm); 370 371 ATF_CHECK(localtime_r(&now, &tm) != NULL); 372 tm.tm_mon -= 9; 373 if (tm.tm_mon == 1 && tm.tm_mday > 28 + isleap(tm.tm_year)) 374 tm.tm_mday = 28 + isleap(tm.tm_year); 375 else if ((tm.tm_mon == -9 || tm.tm_mon == -7 || 376 tm.tm_mon == -2) && tm.tm_mday == 31) 377 tm.tm_mday = 30; 378 tm.tm_isdst = -1; 379 REL_CHECK("9 months ago", now, tm); 380 381 ATF_CHECK(localtime_r(&now, &tm) != NULL); 382 if (tm.tm_wday <= 2) 383 tm.tm_mday -= 7; 384 tm.tm_mday += 2 - tm.tm_wday; 385 tm.tm_isdst = -1; 386 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 387 REL_CHECK("1 week ago Tu", now, tm); 388 389 ATF_CHECK(localtime_r(&now, &tm) != NULL); 390 tm.tm_isdst = -1; 391 tm.tm_mday++; 392 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 393 REL_CHECK("midnight tomorrow", now, tm); 394 395 ATF_CHECK(localtime_r(&now, &tm) != NULL); 396 tm.tm_isdst = -1; 397 tm.tm_mday++; 398 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 399 REL_CHECK("tomorrow midnight", now, tm); 400 401 ATF_CHECK(localtime_r(&now, &tm) != NULL); 402 tm.tm_isdst = -1; 403 tm.tm_mday++; 404 tm.tm_hour = 12; 405 tm.tm_min = tm.tm_sec = 0; 406 REL_CHECK("noon tomorrow", now, tm); 407 408 ATF_CHECK(localtime_r(&now, &tm) != NULL); 409 if (tm.tm_wday > 2) 410 tm.tm_mday += 7; 411 tm.tm_mday += 2 - tm.tm_wday; 412 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 413 tm.tm_isdst = -1; 414 REL_CHECK("midnight Tuesday", now, tm); 415 416 ATF_CHECK(localtime_r(&now, &tm) != NULL); 417 if (tm.tm_wday > 2 + 1) 418 tm.tm_mday += 7; 419 tm.tm_mday += 2 - tm.tm_wday; 420 tm.tm_mday++; /* xxx midnight --> the next day */ 421 tm.tm_sec = tm.tm_min = tm.tm_hour = 0; 422 tm.tm_isdst = -1; 423 REL_CHECK("Tuesday midnight", now, tm); 424 } 425 } 426 427 ATF_TC(atsecs); 428 429 ATF_TC_HEAD(atsecs, tc) 430 { 431 atf_tc_set_md_var(tc, "descr", "Test seconds past the epoch"); 432 } 433 434 ATF_TC_BODY(atsecs, tc) 435 { 436 int tzoff; 437 438 /* "@0" -> (time_t)0, regardless of timezone */ 439 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 440 putenv(__UNCONST("TZ=Europe/Berlin")); 441 tzset(); 442 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 443 putenv(__UNCONST("TZ=America/New_York")); 444 tzset(); 445 ATF_CHECK(parsedate("@0", NULL, NULL) == (time_t)0); 446 tzoff = 0; 447 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 448 tzoff = 3600; 449 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 450 tzoff = -3600; 451 ATF_CHECK(parsedate("@0", NULL, &tzoff) == (time_t)0); 452 453 /* -1 or other negative numbers are not errors */ 454 errno = 0; 455 ATF_CHECK(parsedate("@-1", NULL, &tzoff) == (time_t)-1 && errno == 0); 456 ATF_CHECK(parsedate("@-2", NULL, &tzoff) == (time_t)-2 && errno == 0); 457 458 /* junk is an error */ 459 errno = 0; 460 ATF_CHECK(parsedate("@junk", NULL, NULL) == (time_t)-1 && errno != 0); 461 } 462 463 ATF_TC(zones); 464 465 ATF_TC_HEAD(zones, tc) 466 { 467 atf_tc_set_md_var(tc, "descr", "Test parsing dates with zones"); 468 } 469 470 ATF_TC_BODY(zones, tc) 471 { 472 parsecheck("2015-12-06 16:11:48 UTC", NULL, NULL, gmtime_r, 473 2015, 12, 6, 16, 11, 48); 474 parsecheck("2015-12-06 16:11:48 UT", NULL, NULL, gmtime_r, 475 2015, 12, 6, 16, 11, 48); 476 parsecheck("2015-12-06 16:11:48 GMT", NULL, NULL, gmtime_r, 477 2015, 12, 6, 16, 11, 48); 478 parsecheck("2015-12-06 16:11:48 +0000", NULL, NULL, gmtime_r, 479 2015, 12, 6, 16, 11, 48); 480 481 parsecheck("2015-12-06 16:11:48 -0500", NULL, NULL, gmtime_r, 482 2015, 12, 6, 21, 11, 48); 483 parsecheck("2015-12-06 16:11:48 EST", NULL, NULL, gmtime_r, 484 2015, 12, 6, 21, 11, 48); 485 parsecheck("2015-12-06 16:11:48 EDT", NULL, NULL, gmtime_r, 486 2015, 12, 6, 20, 11, 48); 487 parsecheck("2015-12-06 16:11:48 +0500", NULL, NULL, gmtime_r, 488 2015, 12, 6, 11, 11, 48); 489 490 parsecheck("2015-12-06 16:11:48 +1000", NULL, NULL, gmtime_r, 491 2015, 12, 6, 6, 11, 48); 492 parsecheck("2015-12-06 16:11:48 AEST", NULL, NULL, gmtime_r, 493 2015, 12, 6, 6, 11, 48); 494 parsecheck("2015-12-06 16:11:48 -1000", NULL, NULL, gmtime_r, 495 2015, 12, 7, 2, 11, 48); 496 parsecheck("2015-12-06 16:11:48 HST", NULL, NULL, gmtime_r, 497 2015, 12, 7, 2, 11, 48); 498 499 parsecheck("2015-12-06 16:11:48 AWST", NULL, NULL, gmtime_r, 500 2015, 12, 6, 8, 11, 48); 501 parsecheck("2015-12-06 16:11:48 NZDT", NULL, NULL, gmtime_r, 502 2015, 12, 6, 3, 11, 48); 503 504 parsecheck("Sun, 6 Dec 2015 09:43:16 -0500", NULL, NULL, gmtime_r, 505 2015, 12, 6, 14, 43, 16); 506 parsecheck("Mon Dec 7 03:13:31 ICT 2015", NULL, NULL, gmtime_r, 507 2015, 12, 6, 20, 13, 31); 508 /* the day name is ignored when a day of month (etc) is given... */ 509 parsecheck("Sat Dec 7 03:13:31 ICT 2015", NULL, NULL, gmtime_r, 510 2015, 12, 6, 20, 13, 31); 511 512 513 parsecheck("2015-12-06 12:00:00 IDLW", NULL, NULL, gmtime_r, 514 2015, 12, 7, 0, 0, 0); 515 parsecheck("2015-12-06 12:00:00 IDLE", NULL, NULL, gmtime_r, 516 2015, 12, 6, 0, 0, 0); 517 518 parsecheck("2015-12-06 21:17:33 NFT", NULL, NULL, gmtime_r, 519 2015, 12, 7, 0, 47, 33); 520 parsecheck("2015-12-06 21:17:33 ACST", NULL, NULL, gmtime_r, 521 2015, 12, 6, 11, 47, 33); 522 parsecheck("2015-12-06 21:17:33 +0717", NULL, NULL, gmtime_r, 523 2015, 12, 6, 14, 0, 33); 524 525 parsecheck("2015-12-06 21:21:21 Z", NULL, NULL, gmtime_r, 526 2015, 12, 6, 21, 21, 21); 527 parsecheck("2015-12-06 21:21:21 A", NULL, NULL, gmtime_r, 528 2015, 12, 6, 22, 21, 21); 529 parsecheck("2015-12-06 21:21:21 G", NULL, NULL, gmtime_r, 530 2015, 12, 7, 4, 21, 21); 531 parsecheck("2015-12-06 21:21:21 M", NULL, NULL, gmtime_r, 532 2015, 12, 7, 9, 21, 21); 533 parsecheck("2015-12-06 21:21:21 N", NULL, NULL, gmtime_r, 534 2015, 12, 6, 20, 21, 21); 535 parsecheck("2015-12-06 21:21:21 T", NULL, NULL, gmtime_r, 536 2015, 12, 6, 14, 21, 21); 537 parsecheck("2015-12-06 21:21:21 Y", NULL, NULL, gmtime_r, 538 2015, 12, 6, 9, 21, 21); 539 540 } 541 542 ATF_TC(gibberish); 543 544 ATF_TC_HEAD(gibberish, tc) 545 { 546 atf_tc_set_md_var(tc, "descr", "Test (not) parsing nonsense"); 547 } 548 549 ATF_TC_BODY(gibberish, tc) 550 { 551 errno = 0; 552 ATF_CHECK(parsedate("invalid nonsense", NULL, NULL) == (time_t)-1 553 && errno != 0); 554 errno = 0; 555 ATF_CHECK(parsedate("12th day of Christmas", NULL, NULL) == (time_t)-1 556 && errno != 0); 557 errno = 0; 558 ATF_CHECK(parsedate("2015-31-07 15:00", NULL, NULL) == (time_t)-1 559 && errno != 0); 560 errno = 0; 561 ATF_CHECK(parsedate("2015-02-29 10:01", NULL, NULL) == (time_t)-1 562 && errno != 0); 563 errno = 0; 564 ATF_CHECK(parsedate("2015-12-06 24:01", NULL, NULL) == (time_t)-1 565 && errno != 0); 566 errno = 0; 567 ATF_CHECK(parsedate("2015-12-06 14:61", NULL, NULL) == (time_t)-1 568 && errno != 0); 569 } 570 571 ATF_TP_ADD_TCS(tp) 572 { 573 ATF_TP_ADD_TC(tp, dates); 574 ATF_TP_ADD_TC(tp, times); 575 ATF_TP_ADD_TC(tp, dsttimes); 576 ATF_TP_ADD_TC(tp, relative); 577 ATF_TP_ADD_TC(tp, atsecs); 578 ATF_TP_ADD_TC(tp, zones); 579 ATF_TP_ADD_TC(tp, gibberish); 580 581 return atf_no_error(); 582 } 583 584