forked from OSchip/llvm-project
[libc] Introduce asctime, asctime_r to LLVM libc
[libc] Introduce asctime, asctime_r to LLVM libc asctime and asctime_r share the same common code. They call asctime_internal a static inline function. asctime uses snprintf to return the string representation in a buffer. It uses the following format (26 characters is the buffer size) as per 7.27.3.1 section in http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2478.pdf. The buf parameter for asctime_r shall point to a buffer of at least 26 bytes. snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",...) Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D99686
This commit is contained in:
parent
47ee47e1e8
commit
a72499e475
|
@ -249,6 +249,8 @@ def TimeAPI : PublicAPI<"time.h"> {
|
|||
];
|
||||
|
||||
let Functions = [
|
||||
"asctime",
|
||||
"asctime_r",
|
||||
"gmtime",
|
||||
"gmtime_r",
|
||||
"mktime",
|
||||
|
|
|
@ -181,6 +181,8 @@ if(LLVM_LIBC_FULL_BUILD)
|
|||
libc.src.threads.thrd_join
|
||||
|
||||
# time.h entrypoints
|
||||
libc.src.time.asctime
|
||||
libc.src.time.asctime_r
|
||||
libc.src.time.gmtime
|
||||
libc.src.time.gmtime_r
|
||||
libc.src.time.mktime
|
||||
|
|
|
@ -599,6 +599,19 @@ def StdC : StandardSpec<"stdc"> {
|
|||
],
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
"asctime",
|
||||
RetValSpec<CharPtr>,
|
||||
[ArgSpec<StructTmPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"asctime_r",
|
||||
RetValSpec<CharPtr>,
|
||||
[
|
||||
ArgSpec<StructTmPtr>,
|
||||
ArgSpec<CharPtr>,
|
||||
]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"gmtime",
|
||||
RetValSpec<StructTmPtr>,
|
||||
|
|
|
@ -10,6 +10,28 @@ add_object_library(
|
|||
libc.src.errno.__errno_location
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
asctime
|
||||
SRCS
|
||||
asctime.cpp
|
||||
HDRS
|
||||
asctime.h
|
||||
DEPENDS
|
||||
.time_utils
|
||||
libc.include.time
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
asctime_r
|
||||
SRCS
|
||||
asctime_r.cpp
|
||||
HDRS
|
||||
asctime_r.h
|
||||
DEPENDS
|
||||
.time_utils
|
||||
libc.include.time
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
gmtime
|
||||
SRCS
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
//===-- Implementation of asctime function --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/time/asctime.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/time/time_utils.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
using __llvm_libc::time_utils::TimeConstants;
|
||||
|
||||
LLVM_LIBC_FUNCTION(char *, asctime, (const struct tm *timeptr)) {
|
||||
static char buffer[TimeConstants::AsctimeBufferSize];
|
||||
return time_utils::asctime(timeptr, buffer, TimeConstants::AsctimeMaxBytes);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,22 @@
|
|||
//===-- Implementation header of asctime ------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_TIME_ASCTIME_H
|
||||
#define LLVM_LIBC_SRC_TIME_ASCTIME_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *asctime(const struct tm *timeptr);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_TIME_ASCTIME_H
|
||||
|
||||
#include "include/time.h"
|
|
@ -0,0 +1,22 @@
|
|||
//===-- Implementation of asctime_r function ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/time/asctime_r.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/time/time_utils.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
using __llvm_libc::time_utils::TimeConstants;
|
||||
|
||||
LLVM_LIBC_FUNCTION(char *, asctime_r,
|
||||
(const struct tm *timeptr, char *buffer)) {
|
||||
return time_utils::asctime(timeptr, buffer, TimeConstants::AsctimeMaxBytes);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,22 @@
|
|||
//===-- Implementation header of asctime_r ----------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_TIME_ASCTIME_R_H
|
||||
#define LLVM_LIBC_SRC_TIME_ASCTIME_R_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
char *asctime_r(const struct tm *timeptr, char *buffer);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_TIME_ASCTIME_R_H
|
||||
|
||||
#include "include/time.h"
|
|
@ -9,6 +9,8 @@
|
|||
#ifndef LLVM_LIBC_SRC_TIME_TIME_UTILS_H
|
||||
#define LLVM_LIBC_SRC_TIME_TIME_UTILS_H
|
||||
|
||||
#include <stddef.h> // For size_t.
|
||||
|
||||
#include "include/errno.h"
|
||||
|
||||
#include "src/errno/llvmlibc_errno.h"
|
||||
|
@ -33,6 +35,14 @@ struct TimeConstants {
|
|||
static constexpr int NumberOfSecondsInLeapYear =
|
||||
(DaysPerNonLeapYear + 1) * SecondsPerDay;
|
||||
|
||||
// For asctime the behavior is undefined if struct tm's tm_wday or tm_mon are
|
||||
// not within the normal ranges as defined in <time.h>, or if struct tm's
|
||||
// tm_year exceeds {INT_MAX}-1990, or if the below asctime_internal algorithm
|
||||
// would attempt to generate more than 26 bytes of output (including the
|
||||
// terminating null).
|
||||
static constexpr int AsctimeBufferSize = 256;
|
||||
static constexpr int AsctimeMaxBytes = 26;
|
||||
|
||||
/* 2000-03-01 (mod 400 year, immediately after feb29 */
|
||||
static constexpr int64_t SecondsUntil2000MarchFirst =
|
||||
(946684800LL + SecondsPerDay * (31 + 29));
|
||||
|
@ -63,6 +73,46 @@ static inline time_t OutOfRange() {
|
|||
return static_cast<time_t>(-1);
|
||||
}
|
||||
|
||||
static inline void InvalidValue() { llvmlibc_errno = EINVAL; }
|
||||
|
||||
static inline char *asctime(const struct tm *timeptr, char *buffer,
|
||||
size_t bufferLength) {
|
||||
if (timeptr == nullptr || buffer == nullptr) {
|
||||
InvalidValue();
|
||||
return nullptr;
|
||||
}
|
||||
if (timeptr->tm_wday < 0 ||
|
||||
timeptr->tm_wday > (TimeConstants::DaysPerWeek - 1)) {
|
||||
InvalidValue();
|
||||
return nullptr;
|
||||
}
|
||||
if (timeptr->tm_mon < 0 ||
|
||||
timeptr->tm_mon > (TimeConstants::MonthsPerYear - 1)) {
|
||||
InvalidValue();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO(rtenneti): i18n the following strings.
|
||||
static const char *WeekDaysName[TimeConstants::DaysPerWeek] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
|
||||
static const char *MonthsName[TimeConstants::MonthsPerYear] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
int written_size = __builtin_snprintf(
|
||||
buffer, bufferLength, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
|
||||
WeekDaysName[timeptr->tm_wday], MonthsName[timeptr->tm_mon],
|
||||
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
|
||||
TimeConstants::TimeYearBase + timeptr->tm_year);
|
||||
if (written_size < 0)
|
||||
return nullptr;
|
||||
if (static_cast<size_t>(written_size) >= bufferLength) {
|
||||
OutOfRange();
|
||||
return nullptr;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static inline struct tm *gmtime_internal(const time_t *timer,
|
||||
struct tm *result) {
|
||||
int64_t seconds = *timer;
|
||||
|
|
|
@ -1,5 +1,31 @@
|
|||
add_libc_testsuite(libc_time_unittests)
|
||||
|
||||
add_libc_unittest(
|
||||
asctime
|
||||
SUITE
|
||||
libc_time_unittests
|
||||
SRCS
|
||||
asctime_test.cpp
|
||||
HDRS
|
||||
TmHelper.h
|
||||
TmMatcher.h
|
||||
DEPENDS
|
||||
libc.src.time.asctime
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
asctime_r
|
||||
SUITE
|
||||
libc_time_unittests
|
||||
SRCS
|
||||
asctime_r_test.cpp
|
||||
HDRS
|
||||
TmHelper.h
|
||||
TmMatcher.h
|
||||
DEPENDS
|
||||
libc.src.time.asctime_r
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
gmtime
|
||||
SUITE
|
||||
|
@ -31,6 +57,7 @@ add_libc_unittest(
|
|||
SRCS
|
||||
mktime_test.cpp
|
||||
HDRS
|
||||
TmHelper.h
|
||||
TmMatcher.h
|
||||
DEPENDS
|
||||
libc.src.time.mktime
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
//===---- TmHelper.h ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_TEST_SRC_TIME_TM_HELPER_H
|
||||
#define LLVM_LIBC_TEST_SRC_TIME_TM_HELPER_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "src/time/time_utils.h"
|
||||
|
||||
using __llvm_libc::time_utils::TimeConstants;
|
||||
|
||||
namespace __llvm_libc {
|
||||
namespace tmhelper {
|
||||
namespace testing {
|
||||
|
||||
// A helper function to initialize tm data structure.
|
||||
static inline void InitializeTmData(struct tm *tm_data, int year, int month,
|
||||
int mday, int hour, int min, int sec,
|
||||
int wday, int yday) {
|
||||
struct tm temp = {.tm_sec = sec,
|
||||
.tm_min = min,
|
||||
.tm_hour = hour,
|
||||
.tm_mday = mday,
|
||||
.tm_mon = month - 1, // tm_mon starts with 0 for Jan
|
||||
// years since 1900
|
||||
.tm_year = year - TimeConstants::TimeYearBase,
|
||||
.tm_wday = wday,
|
||||
.tm_yday = yday};
|
||||
*tm_data = temp;
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace tmhelper
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_TEST_SRC_TIME_TM_HELPER_H
|
|
@ -0,0 +1,60 @@
|
|||
//===-- Unittests for asctime_r
|
||||
//--------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/time/asctime_r.h"
|
||||
#include "src/time/time_utils.h"
|
||||
#include "test/src/time/TmHelper.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
using __llvm_libc::time_utils::TimeConstants;
|
||||
|
||||
static inline char *call_asctime_r(struct tm *tm_data, int year, int month,
|
||||
int mday, int hour, int min, int sec,
|
||||
int wday, int yday, char *buffer) {
|
||||
__llvm_libc::tmhelper::testing::InitializeTmData(tm_data, year, month, mday,
|
||||
hour, min, sec, wday, yday);
|
||||
return __llvm_libc::asctime_r(tm_data, buffer);
|
||||
}
|
||||
|
||||
// asctime and asctime_r share the same code and thus didn't repeat all the
|
||||
// tests from asctime. Added couple of validation tests.
|
||||
TEST(LlvmLibcAsctimeR, Nullptr) {
|
||||
char *result;
|
||||
result = __llvm_libc::asctime_r(nullptr, nullptr);
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
ASSERT_STREQ(nullptr, result);
|
||||
|
||||
char buffer[TimeConstants::AsctimeBufferSize];
|
||||
result = __llvm_libc::asctime_r(nullptr, buffer);
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
ASSERT_STREQ(nullptr, result);
|
||||
|
||||
struct tm tm_data;
|
||||
result = __llvm_libc::asctime_r(&tm_data, nullptr);
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
ASSERT_STREQ(nullptr, result);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcAsctimeR, ValidDate) {
|
||||
char buffer[TimeConstants::AsctimeBufferSize];
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
// 1970-01-01 00:00:00. Test with a valid buffer size.
|
||||
result = call_asctime_r(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
4, // wday
|
||||
0, // yday
|
||||
buffer);
|
||||
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
//===-- Unittests for asctime ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/time/asctime.h"
|
||||
#include "test/src/time/TmHelper.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
static inline char *call_asctime(struct tm *tm_data, int year, int month,
|
||||
int mday, int hour, int min, int sec, int wday,
|
||||
int yday) {
|
||||
__llvm_libc::tmhelper::testing::InitializeTmData(tm_data, year, month, mday,
|
||||
hour, min, sec, wday, yday);
|
||||
return __llvm_libc::asctime(tm_data);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcAsctime, Nullptr) {
|
||||
char *result;
|
||||
result = __llvm_libc::asctime(nullptr);
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
ASSERT_STREQ(nullptr, result);
|
||||
}
|
||||
|
||||
// Weekdays are in the range 0 to 6. Test passing invalid value in wday.
|
||||
TEST(LlvmLibcAsctime, InvalidWday) {
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
|
||||
// Test with wday = -1.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
-1, // wday
|
||||
0); // yday
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
|
||||
// Test with wday = 7.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
7, // wday
|
||||
0); // yday
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
}
|
||||
|
||||
// Months are from January to December. Test passing invalid value in month.
|
||||
TEST(LlvmLibcAsctime, InvalidMonth) {
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
|
||||
// Test with month = 0.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
0, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
4, // wday
|
||||
0); // yday
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
|
||||
// Test with month = 13.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
13, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
4, // wday
|
||||
0); // yday
|
||||
ASSERT_EQ(EINVAL, llvmlibc_errno);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcAsctime, ValidWeekdays) {
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
// 1970-01-01 00:00:00.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
4, // wday
|
||||
0); // yday
|
||||
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
|
||||
|
||||
// 1970-01-03 00:00:00.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
3, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
6, // wday
|
||||
0); // yday
|
||||
ASSERT_STREQ("Sat Jan 3 00:00:00 1970\n", result);
|
||||
|
||||
// 1970-01-04 00:00:00.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
4, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
0, // wday
|
||||
0); // yday
|
||||
ASSERT_STREQ("Sun Jan 4 00:00:00 1970\n", result);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcAsctime, ValidMonths) {
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
// 1970-01-01 00:00:00.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
1, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
4, // wday
|
||||
0); // yday
|
||||
ASSERT_STREQ("Thu Jan 1 00:00:00 1970\n", result);
|
||||
|
||||
// 1970-02-01 00:00:00.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
2, // month
|
||||
1, // day
|
||||
0, // hr
|
||||
0, // min
|
||||
0, // sec
|
||||
0, // wday
|
||||
0); // yday
|
||||
ASSERT_STREQ("Sun Feb 1 00:00:00 1970\n", result);
|
||||
|
||||
// 1970-12-31 23:59:59.
|
||||
result = call_asctime(&tm_data,
|
||||
1970, // year
|
||||
12, // month
|
||||
31, // day
|
||||
23, // hr
|
||||
59, // min
|
||||
59, // sec
|
||||
4, // wday
|
||||
0); // yday
|
||||
ASSERT_STREQ("Thu Dec 31 23:59:59 1970\n", result);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcAsctime, EndOf32BitEpochYear) {
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
// Test for maximum value of a signed 32-bit integer.
|
||||
// Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
|
||||
result = call_asctime(&tm_data,
|
||||
2038, // year
|
||||
1, // month
|
||||
19, // day
|
||||
3, // hr
|
||||
14, // min
|
||||
7, // sec
|
||||
2, // wday
|
||||
7); // yday
|
||||
ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcAsctime, Max64BitYear) {
|
||||
if (sizeof(time_t) == 4)
|
||||
return;
|
||||
// Mon Jan 1 12:50:50 2170 (200 years from 1970),
|
||||
struct tm tm_data;
|
||||
char *result;
|
||||
result = call_asctime(&tm_data,
|
||||
2170, // year
|
||||
1, // month
|
||||
1, // day
|
||||
12, // hr
|
||||
50, // min
|
||||
50, // sec
|
||||
1, // wday
|
||||
50); // yday
|
||||
ASSERT_STREQ("Mon Jan 1 12:50:50 2170\n", result);
|
||||
|
||||
// Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
|
||||
// This test would cause buffer overflow and thus asctime returns nullptr.
|
||||
result = call_asctime(&tm_data,
|
||||
2147483647, // year
|
||||
1, // month
|
||||
1, // day
|
||||
12, // hr
|
||||
50, // min
|
||||
50, // sec
|
||||
2, // wday
|
||||
50); // yday
|
||||
ASSERT_EQ(EOVERFLOW, llvmlibc_errno);
|
||||
ASSERT_STREQ(nullptr, result);
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include "src/time/mktime.h"
|
||||
#include "src/time/time_utils.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "test/src/time/TmHelper.h"
|
||||
#include "test/src/time/TmMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
|
@ -20,33 +21,18 @@ using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
|||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
using __llvm_libc::time_utils::TimeConstants;
|
||||
|
||||
// A helper function to initialize tm data structure.
|
||||
static inline void initialize_tm_data(struct tm *tm_data, int year, int month,
|
||||
int mday, int hour, int min, int sec,
|
||||
int wday, int yday) {
|
||||
struct tm temp = {.tm_sec = sec,
|
||||
.tm_min = min,
|
||||
.tm_hour = hour,
|
||||
.tm_mday = mday,
|
||||
.tm_mon = month - 1, // tm_mon starts with 0 for Jan
|
||||
// years since 1900
|
||||
.tm_year = year - TimeConstants::TimeYearBase,
|
||||
.tm_wday = wday,
|
||||
.tm_yday = yday};
|
||||
*tm_data = temp;
|
||||
}
|
||||
|
||||
static inline time_t call_mktime(struct tm *tm_data, int year, int month,
|
||||
int mday, int hour, int min, int sec, int wday,
|
||||
int yday) {
|
||||
initialize_tm_data(tm_data, year, month, mday, hour, min, sec, wday, yday);
|
||||
__llvm_libc::tmhelper::testing::InitializeTmData(tm_data, year, month, mday,
|
||||
hour, min, sec, wday, yday);
|
||||
return __llvm_libc::mktime(tm_data);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcMkTime, FailureSetsErrno) {
|
||||
struct tm tm_data;
|
||||
initialize_tm_data(&tm_data, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, -1,
|
||||
0, 0);
|
||||
__llvm_libc::tmhelper::testing::InitializeTmData(
|
||||
&tm_data, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, -1, 0, 0);
|
||||
EXPECT_THAT(__llvm_libc::mktime(&tm_data), Fails(EOVERFLOW));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue