Changeset View
Standalone View
contrib/netbsd-tests/lib/libc/time/t_mktime.c
/* $NetBSD: t_mktime.c,v 1.5 2012/03/18 07:33:58 jruoho Exp $ */ | /* $NetBSD: t_mktime.c,v 1.6 2017/10/27 00:55:27 kre Exp $ */ | ||||
/*- | /*- | ||||
* Copyright (c) 2011 The NetBSD Foundation, Inc. | * Copyright (c) 2011 The NetBSD Foundation, Inc. | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
ATF_TC(mktime_negyear); | ATF_TC(mktime_negyear); | ||||
ATF_TC_HEAD(mktime_negyear, tc) | ATF_TC_HEAD(mktime_negyear, tc) | ||||
{ | { | ||||
atf_tc_set_md_var(tc, "descr", "Test mktime(3) with negative year"); | atf_tc_set_md_var(tc, "descr", "Test mktime(3) with negative year"); | ||||
} | } | ||||
ATF_TC_BODY(mktime_negyear, tc) | ATF_TC_BODY(mktime_negyear, tc) | ||||
{ | { | ||||
#ifdef __FreeBSD__ | |||||
atf_tc_expect_fail("needs work"); | |||||
#endif | |||||
struct tm tms; | struct tm tms; | ||||
time_t t; | time_t t; | ||||
(void)memset(&tms, 0, sizeof(tms)); | (void)memset(&tms, 0, sizeof(tms)); | ||||
tms.tm_year = ~0; | tms.tm_year = -1; | ||||
tms.tm_mday = 1; | |||||
errno = 0; | errno = 0; | ||||
t = mktime(&tms); | t = mktime(&tms); | ||||
ATF_REQUIRE_ERRNO(0, t != (time_t)-1); | ATF_REQUIRE(t != (time_t)-1); | ||||
markj: Presumably we shouldn't rely on `errno` being clear if the call was successful? Where does it… | |||||
Done Inline Actions
Neither C nor POSIX say anything about mktime() setting errno. It just so happens that a previous version of tzcode left errno untouched when mktime() was successful, NetBSD incorrectly assumed that this was mandated and added a test for it, and we trusted them and imported that test. The current version of tzcode almost always sets errno to EOVERFLOW on 64-bit platforms, even when successful, so the test fails.
This is contrib code, I don't want to make gratuitous changes. des: > Presumably we shouldn't rely on `errno` being clear if the call was successful?
Neither C… | |||||
Done Inline ActionsWe should file a NetBSD PR, so our fix can be picked up in the next update. ngie: We should file a NetBSD PR, so our fix can be picked up in the next update. | |||||
Done Inline ActionsThere is no “our fix”. This commit reverts the test to the latest upstream revision. des: There is no “our fix”. This commit reverts the test to the [[ https://github. | |||||
} | } | ||||
ATF_TC(timegm_epoch); | ATF_TC(timegm_epoch); | ||||
ATF_TC_HEAD(timegm_epoch, tc) | ATF_TC_HEAD(timegm_epoch, tc) | ||||
{ | { | ||||
atf_tc_set_md_var(tc, "descr", "Test timegm(3) close to the epoch"); | atf_tc_set_md_var(tc, "descr", "Test timegm(3) close to the epoch"); | ||||
} | } | ||||
ATF_TC_BODY(timegm_epoch, tc) | ATF_TC_BODY(timegm_epoch, tc) | ||||
{ | { | ||||
struct tm tms; | struct tm tms; | ||||
time_t t; | time_t t; | ||||
/* midnight on 1 Jan 1970 */ | /* midnight on 1 Jan 1970 */ | ||||
(void)memset(&tms, 0, sizeof(tms)); | (void)memset(&tms, 0, sizeof(tms)); | ||||
errno = 0; | errno = 0; | ||||
tms.tm_year = 1970 - 1900; | tms.tm_year = 1970 - 1900; | ||||
tms.tm_mday = 1; | tms.tm_mday = 1; | ||||
t = timegm(&tms); | t = timegm(&tms); | ||||
ATF_REQUIRE_ERRNO(0, t == (time_t)0); | ATF_REQUIRE(t == (time_t)0); | ||||
/* one second after midnight on 1 Jan 1970 */ | /* one second after midnight on 1 Jan 1970 */ | ||||
(void)memset(&tms, 0, sizeof(tms)); | (void)memset(&tms, 0, sizeof(tms)); | ||||
errno = 0; | errno = 0; | ||||
tms.tm_year = 1970 - 1900; | tms.tm_year = 1970 - 1900; | ||||
tms.tm_mday = 1; | tms.tm_mday = 1; | ||||
tms.tm_sec = 1; | tms.tm_sec = 1; | ||||
t = timegm(&tms); | t = timegm(&tms); | ||||
ATF_REQUIRE_ERRNO(0, t == (time_t)1); | ATF_REQUIRE(t == (time_t)1); | ||||
/* | /* | ||||
* 1969-12-31 23:59:59 = one second before the epoch. | * 1969-12-31 23:59:59 = one second before the epoch. | ||||
* Result should be -1 with errno = 0. | * Result should be -1 with errno = 0. | ||||
*/ | */ | ||||
(void)memset(&tms, 0, sizeof(tms)); | (void)memset(&tms, 0, sizeof(tms)); | ||||
errno = 0; | errno = 0; | ||||
tms.tm_year = 1969 - 1900; | tms.tm_year = 1969 - 1900; | ||||
tms.tm_mon = 12 - 1; | tms.tm_mon = 12 - 1; | ||||
tms.tm_mday = 31; | tms.tm_mday = 31; | ||||
tms.tm_hour = 23; | tms.tm_hour = 23; | ||||
tms.tm_min = 59; | tms.tm_min = 59; | ||||
tms.tm_sec = 59; | tms.tm_sec = 59; | ||||
t = timegm(&tms); | t = timegm(&tms); | ||||
ATF_REQUIRE_ERRNO(0, t == (time_t)-1); | ATF_REQUIRE(t == (time_t)-1); | ||||
/* ATF_REQUIRE(errno == 0); does not work, errno is kept clear */ | |||||
/* | /* | ||||
* Another way of getting one second before the epoch: | * Another way of getting one second before the epoch: | ||||
* Set date to 1 Jan 1970, and time to -1 second. | * Set date to 1 Jan 1970, and time to -1 second. | ||||
*/ | */ | ||||
(void)memset(&tms, 0, sizeof(tms)); | (void)memset(&tms, 0, sizeof(tms)); | ||||
errno = 0; | errno = 0; | ||||
tms.tm_year = 1970 - 1900; | tms.tm_year = 1970 - 1900; | ||||
tms.tm_mday = 1; | tms.tm_mday = 1; | ||||
tms.tm_sec = -1; | tms.tm_sec = -1; | ||||
t = timegm(&tms); | t = timegm(&tms); | ||||
ATF_REQUIRE_ERRNO(0, t == (time_t)-1); | ATF_REQUIRE(t == (time_t)-1); | ||||
/* | /* | ||||
* Two seconds before the epoch. | * Two seconds before the epoch. | ||||
*/ | */ | ||||
(void)memset(&tms, 0, sizeof(tms)); | (void)memset(&tms, 0, sizeof(tms)); | ||||
errno = 0; | errno = 0; | ||||
tms.tm_year = 1970 - 1900; | tms.tm_year = 1970 - 1900; | ||||
tms.tm_mday = 1; | tms.tm_mday = 1; | ||||
tms.tm_sec = -2; | tms.tm_sec = -2; | ||||
t = timegm(&tms); | t = timegm(&tms); | ||||
ATF_REQUIRE_ERRNO(0, t == (time_t)-2); | ATF_REQUIRE(t == (time_t)-2); | ||||
} | } | ||||
ATF_TP_ADD_TCS(tp) | ATF_TP_ADD_TCS(tp) | ||||
{ | { | ||||
ATF_TP_ADD_TC(tp, localtime_r_gmt); | ATF_TP_ADD_TC(tp, localtime_r_gmt); | ||||
ATF_TP_ADD_TC(tp, mktime_negyear); | ATF_TP_ADD_TC(tp, mktime_negyear); | ||||
ATF_TP_ADD_TC(tp, timegm_epoch); | ATF_TP_ADD_TC(tp, timegm_epoch); | ||||
return atf_no_error(); | return atf_no_error(); | ||||
} | } |
Presumably we shouldn't rely on errno being clear if the call was successful? Where does it get set?
We should probably stop clearing errno above too then?