fmt/test/chrono-test.cc

1026 lines
40 KiB
C++
Raw Normal View History

// Formatting library for C++ - time formatting tests
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.
#include "fmt/chrono.h"
#include <algorithm>
#include <ctime>
#include <vector>
2021-04-30 21:21:49 +00:00
#include "gtest-extra.h" // EXPECT_THROW_MSG
#include "util.h" // get_locale
2020-05-07 22:59:46 +00:00
2021-05-19 02:38:52 +00:00
using fmt::runtime;
using testing::Contains;
#if defined(__MINGW32__) && !defined(_UCRT)
// Only C89 conversion specifiers when using MSVCRT instead of UCRT
# define FMT_HAS_C99_STRFTIME 0
#else
# define FMT_HAS_C99_STRFTIME 1
#endif
#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907L
using days = std::chrono::days;
#else
using days = std::chrono::duration<std::chrono::hours::rep, std::ratio<86400>>;
#endif
auto make_tm() -> std::tm {
auto time = std::tm();
time.tm_mday = 1;
return time;
}
auto make_hour(int h) -> std::tm {
auto time = make_tm();
time.tm_hour = h;
return time;
}
auto make_minute(int m) -> std::tm {
auto time = make_tm();
time.tm_min = m;
return time;
}
auto make_second(int s) -> std::tm {
auto time = make_tm();
time.tm_sec = s;
return time;
}
std::string system_strftime(const std::string& format, const std::tm* timeptr,
std::locale* locptr = nullptr) {
auto loc = locptr ? *locptr : std::locale::classic();
auto& facet = std::use_facet<std::time_put<char>>(loc);
std::ostringstream os;
os.imbue(loc);
facet.put(os, os, ' ', timeptr, format.c_str(),
format.c_str() + format.size());
2021-11-13 09:31:57 +00:00
#ifdef _WIN32
// Workaround a bug in older versions of Universal CRT.
auto str = os.str();
if (str == "-0000") str = "+0000";
return str;
#else
return os.str();
2021-11-13 09:31:57 +00:00
#endif
}
FMT_CONSTEXPR std::tm make_tm(int year, int mon, int mday, int hour, int min,
int sec) {
auto tm = std::tm();
tm.tm_sec = sec;
tm.tm_min = min;
tm.tm_hour = hour;
tm.tm_mday = mday;
tm.tm_mon = mon - 1;
tm.tm_year = year - 1900;
return tm;
}
TEST(chrono_test, format_tm) {
auto tm = std::tm();
2019-03-15 01:10:56 +00:00
tm.tm_year = 116;
tm.tm_mon = 3;
tm.tm_mday = 25;
tm.tm_hour = 11;
tm.tm_min = 22;
tm.tm_sec = 33;
EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm),
"The date is 2016-04-25 11:22:33.");
EXPECT_EQ(fmt::format("{:%Y}", tm), "2016");
2021-10-09 18:17:51 +00:00
EXPECT_EQ(fmt::format("{:%C}", tm), "20");
2021-10-10 08:50:43 +00:00
EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm));
EXPECT_EQ(fmt::format("{:%e}", tm), "25");
EXPECT_EQ(fmt::format("{:%D}", tm), "04/25/16");
2021-09-10 14:33:45 +00:00
EXPECT_EQ(fmt::format("{:%F}", tm), "2016-04-25");
2021-09-13 06:42:26 +00:00
EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33");
2021-10-10 14:52:02 +00:00
2021-10-10 16:08:04 +00:00
// Short year
tm.tm_year = 999 - 1900;
2021-10-14 12:07:33 +00:00
tm.tm_mon = 0; // for %G
tm.tm_mday = 2; // for %G
tm.tm_wday = 3; // for %G
tm.tm_yday = 1; // for %G
2021-10-10 16:08:04 +00:00
EXPECT_EQ(fmt::format("{:%Y}", tm), "0999");
2021-10-13 15:26:11 +00:00
EXPECT_EQ(fmt::format("{:%C%y}", tm), "0999");
2021-10-14 12:07:33 +00:00
EXPECT_EQ(fmt::format("{:%G}", tm), "0999");
2021-10-10 16:08:04 +00:00
2021-10-13 15:26:11 +00:00
tm.tm_year = 27 - 1900;
EXPECT_EQ(fmt::format("{:%Y}", tm), "0027");
EXPECT_EQ(fmt::format("{:%C%y}", tm), "0027");
// Overflow year
tm.tm_year = 2147483647;
EXPECT_EQ(fmt::format("{:%Y}", tm), "2147485547");
tm.tm_year = -2147483648;
EXPECT_EQ(fmt::format("{:%Y}", tm), "-2147481748");
2021-10-10 14:52:02 +00:00
// for week on the year
// https://www.cl.cam.ac.uk/~mgk25/iso-time.html
std::vector<std::tm> tm_list = {
make_tm(1975, 12, 29, 12, 14, 16), // W01
make_tm(1977, 1, 2, 12, 14, 16), // W53
make_tm(1999, 12, 27, 12, 14, 16), // W52
make_tm(1999, 12, 31, 12, 14, 16), // W52
make_tm(2000, 1, 1, 12, 14, 16), // W52
make_tm(2000, 1, 2, 12, 14, 16), // W52
make_tm(2000, 1, 3, 12, 14, 16) // W1
2021-10-10 14:52:02 +00:00
};
#if !FMT_HAS_C99_STRFTIME
GTEST_SKIP() << "Skip the rest of this test because it relies on strftime() "
"conforming to C99, but on this platform, MINGW + MSVCRT, "
"the function conforms only to C89.";
#endif
const std::string iso_week_spec = "%Y-%m-%d: %G %g %V";
for (auto ctm : tm_list) {
// Calculate tm_yday, tm_wday, etc.
std::time_t t = std::mktime(&ctm);
2021-10-10 14:52:02 +00:00
tm = *std::localtime(&t);
auto fmt_spec = fmt::format("{{:{}}}", iso_week_spec);
EXPECT_EQ(system_strftime(iso_week_spec, &tm),
fmt::format(fmt::runtime(fmt_spec), tm));
}
// Every day from 1970-01-01
std::time_t time_now = std::time(nullptr);
for (std::time_t t = 6 * 3600; t < time_now; t += 86400) {
tm = *std::localtime(&t);
auto fmt_spec = fmt::format("{{:{}}}", iso_week_spec);
EXPECT_EQ(system_strftime(iso_week_spec, &tm),
fmt::format(fmt::runtime(fmt_spec), tm));
2021-10-10 14:52:02 +00:00
}
2019-03-15 01:10:56 +00:00
}
// MSVC:
// minkernel\crts\ucrt\src\appcrt\time\wcsftime.cpp(971) : Assertion failed:
// timeptr->tm_year >= -1900 && timeptr->tm_year <= 8099
#ifndef _WIN32
TEST(chrono_test, format_tm_future) {
auto tm = std::tm();
tm.tm_year = 10445; // 10000+ years
tm.tm_mon = 3;
tm.tm_mday = 25;
tm.tm_hour = 11;
tm.tm_min = 22;
tm.tm_sec = 33;
EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm),
"The date is 12345-04-25 11:22:33.");
EXPECT_EQ(fmt::format("{:%Y}", tm), "12345");
2021-10-09 18:17:51 +00:00
EXPECT_EQ(fmt::format("{:%C}", tm), "123");
2021-10-10 08:50:43 +00:00
EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm));
EXPECT_EQ(fmt::format("{:%D}", tm), "04/25/45");
EXPECT_EQ(fmt::format("{:%F}", tm), "12345-04-25");
EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33");
}
TEST(chrono_test, format_tm_past) {
auto tm = std::tm();
tm.tm_year = -2001;
tm.tm_mon = 3;
tm.tm_mday = 25;
tm.tm_hour = 11;
tm.tm_min = 22;
tm.tm_sec = 33;
EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm),
"The date is -101-04-25 11:22:33.");
EXPECT_EQ(fmt::format("{:%Y}", tm), "-101");
2021-10-10 08:50:43 +00:00
// macOS %C - "-1"
// Linux %C - "-2"
// fmt %C - "-1"
EXPECT_EQ(fmt::format("{:%C}", tm), "-1");
2021-10-10 08:50:43 +00:00
EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm));
2021-10-10 08:50:43 +00:00
// macOS %D - "04/25/01" (%y)
// Linux %D - "04/25/99" (%y)
// fmt %D - "04/25/01" (%y)
EXPECT_EQ(fmt::format("{:%D}", tm), "04/25/01");
EXPECT_EQ(fmt::format("{:%F}", tm), "-101-04-25");
EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33");
tm.tm_year = -1901; // -1
EXPECT_EQ(fmt::format("{:%Y}", tm), "-001");
EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm));
tm.tm_year = -1911; // -11
EXPECT_EQ(fmt::format("{:%Y}", tm), "-011");
EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm));
}
#endif
TEST(chrono_test, grow_buffer) {
auto s = std::string("{:");
2019-03-15 01:10:56 +00:00
for (int i = 0; i < 30; ++i) s += "%c";
s += "}\n";
auto t = std::time(nullptr);
(void)fmt::format(fmt::runtime(s), *std::localtime(&t));
2019-03-15 01:10:56 +00:00
}
TEST(chrono_test, format_to_empty_container) {
2019-03-15 01:10:56 +00:00
auto time = std::tm();
time.tm_sec = 42;
auto s = std::string();
2019-03-15 01:10:56 +00:00
fmt::format_to(std::back_inserter(s), "{:%S}", time);
EXPECT_EQ(s, "42");
}
TEST(chrono_test, empty_result) { EXPECT_EQ(fmt::format("{}", std::tm()), ""); }
2019-03-15 01:10:56 +00:00
auto equal(const std::tm& lhs, const std::tm& rhs) -> bool {
2019-03-15 01:10:56 +00:00
return lhs.tm_sec == rhs.tm_sec && lhs.tm_min == rhs.tm_min &&
lhs.tm_hour == rhs.tm_hour && lhs.tm_mday == rhs.tm_mday &&
lhs.tm_mon == rhs.tm_mon && lhs.tm_year == rhs.tm_year &&
lhs.tm_wday == rhs.tm_wday && lhs.tm_yday == rhs.tm_yday &&
lhs.tm_isdst == rhs.tm_isdst;
}
TEST(chrono_test, gmtime) {
auto t = std::time(nullptr);
auto tm = *std::gmtime(&t);
EXPECT_TRUE(equal(tm, fmt::gmtime(t)));
2019-03-15 01:10:56 +00:00
}
template <typename TimePoint>
auto strftime_full_utc(TimePoint tp) -> std::string {
auto t = std::chrono::system_clock::to_time_t(tp);
auto tm = *std::gmtime(&t);
return system_strftime("%Y-%m-%d %H:%M:%S", &tm);
}
TEST(chrono_test, system_clock_time_point) {
auto t1 = std::chrono::time_point_cast<std::chrono::seconds>(
std::chrono::system_clock::now());
EXPECT_EQ(strftime_full_utc(t1), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1));
EXPECT_EQ(strftime_full_utc(t1), fmt::format("{}", t1));
2023-01-16 19:48:00 +00:00
EXPECT_EQ(strftime_full_utc(t1), fmt::format("{:}", t1));
using time_point =
std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
auto t2 = time_point(std::chrono::seconds(42));
EXPECT_EQ(strftime_full_utc(t2), fmt::format("{:%Y-%m-%d %H:%M:%S}", t2));
std::vector<std::string> spec_list = {
"%%", "%n", "%t", "%Y", "%EY", "%y", "%Oy", "%Ey", "%C",
"%EC", "%G", "%g", "%b", "%h", "%B", "%m", "%Om", "%U",
"%OU", "%W", "%OW", "%V", "%OV", "%j", "%d", "%Od", "%e",
"%Oe", "%a", "%A", "%w", "%Ow", "%u", "%Ou", "%H", "%OH",
"%I", "%OI", "%M", "%OM", "%S", "%OS", "%x", "%Ex", "%X",
"%EX", "%D", "%F", "%R", "%T", "%p"};
#ifndef _WIN32
2021-10-30 16:14:13 +00:00
// Disabled on Windows because these formats are not consistent among
// platforms.
spec_list.insert(spec_list.end(), {"%c", "%Ec", "%r"});
#elif !FMT_HAS_C99_STRFTIME
// Only C89 conversion specifiers when using MSVCRT instead of UCRT
spec_list = {"%%", "%Y", "%y", "%b", "%B", "%m", "%U", "%W", "%j", "%d",
"%a", "%A", "%w", "%H", "%I", "%M", "%S", "%x", "%X", "%p"};
#endif
spec_list.push_back("%Y-%m-%d %H:%M:%S");
for (const auto& spec : spec_list) {
auto t = std::chrono::system_clock::to_time_t(t1);
auto tm = *std::gmtime(&t);
auto sys_output = system_strftime(spec, &tm);
auto fmt_spec = fmt::format("{{:{}}}", spec);
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1));
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
}
// Timezone formatters tests makes sense for localtime.
#if FMT_HAS_C99_STRFTIME
spec_list = {"%z", "%Z"};
#else
spec_list = {"%Z"};
#endif
for (const auto& spec : spec_list) {
auto t = std::chrono::system_clock::to_time_t(t1);
auto tm = *std::localtime(&t);
auto sys_output = system_strftime(spec, &tm);
auto fmt_spec = fmt::format("{{:{}}}", spec);
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
if (spec == "%z") {
sys_output.insert(sys_output.end() - 2, 1, ':');
EXPECT_EQ(sys_output, fmt::format("{:%Ez}", tm));
EXPECT_EQ(sys_output, fmt::format("{:%Oz}", tm));
}
}
// Separate tests for UTC, since std::time_put can use local time and ignoring
// the timezone in std::tm (if it presents on platform).
if (fmt::detail::has_member_data_tm_zone<std::tm>::value) {
auto t = std::chrono::system_clock::to_time_t(t1);
auto tm = *std::gmtime(&t);
std::vector<std::string> tz_names = {"GMT", "UTC"};
EXPECT_THAT(tz_names, Contains(fmt::format("{:%Z}", t1)));
EXPECT_THAT(tz_names, Contains(fmt::format("{:%Z}", tm)));
}
if (fmt::detail::has_member_data_tm_gmtoff<std::tm>::value) {
auto t = std::chrono::system_clock::to_time_t(t1);
auto tm = *std::gmtime(&t);
EXPECT_EQ("+0000", fmt::format("{:%z}", t1));
EXPECT_EQ("+0000", fmt::format("{:%z}", tm));
EXPECT_EQ("+00:00", fmt::format("{:%Ez}", t1));
EXPECT_EQ("+00:00", fmt::format("{:%Ez}", tm));
EXPECT_EQ("+00:00", fmt::format("{:%Oz}", t1));
EXPECT_EQ("+00:00", fmt::format("{:%Oz}", tm));
}
}
#if FMT_USE_LOCAL_TIME
TEST(chrono_test, localtime) {
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
EXPECT_TRUE(equal(tm, fmt::localtime(t)));
}
template <typename Duration>
auto strftime_full_local(std::chrono::local_time<Duration> tp) -> std::string {
auto t = std::chrono::system_clock::to_time_t(
std::chrono::current_zone()->to_sys(tp));
auto tm = *std::localtime(&t);
return system_strftime("%Y-%m-%d %H:%M:%S", &tm);
}
TEST(chrono_test, local_system_clock_time_point) {
# ifdef _WIN32
return; // Not supported on Windows.
# endif
auto t1 = std::chrono::time_point_cast<std::chrono::seconds>(
std::chrono::current_zone()->to_local(std::chrono::system_clock::now()));
EXPECT_EQ(strftime_full_local(t1), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1));
EXPECT_EQ(strftime_full_local(t1), fmt::format("{}", t1));
2023-01-16 19:48:00 +00:00
EXPECT_EQ(strftime_full_local(t1), fmt::format("{:}", t1));
using time_point = std::chrono::local_time<std::chrono::seconds>;
auto t2 = time_point(std::chrono::seconds(86400 + 42));
EXPECT_EQ(strftime_full_local(t2), fmt::format("{:%Y-%m-%d %H:%M:%S}", t2));
std::vector<std::string> spec_list = {
"%%", "%n", "%t", "%Y", "%EY", "%y", "%Oy", "%Ey", "%C",
"%EC", "%G", "%g", "%b", "%h", "%B", "%m", "%Om", "%U",
"%OU", "%W", "%OW", "%V", "%OV", "%j", "%d", "%Od", "%e",
"%Oe", "%a", "%A", "%w", "%Ow", "%u", "%Ou", "%H", "%OH",
"%I", "%OI", "%M", "%OM", "%S", "%OS", "%x", "%Ex", "%X",
"%EX", "%D", "%F", "%R", "%T", "%p", "%z", "%Z"};
# ifndef _WIN32
// Disabled on Windows because these formats are not consistent among
// platforms.
spec_list.insert(spec_list.end(), {"%c", "%Ec", "%r"});
# elif !FMT_HAS_C99_STRFTIME
// Only C89 conversion specifiers when using MSVCRT instead of UCRT
spec_list = {"%%", "%Y", "%y", "%b", "%B", "%m", "%U", "%W", "%j", "%d", "%a",
"%A", "%w", "%H", "%I", "%M", "%S", "%x", "%X", "%p", "%Z"};
# endif
spec_list.push_back("%Y-%m-%d %H:%M:%S");
for (const auto& spec : spec_list) {
auto t = std::chrono::system_clock::to_time_t(
std::chrono::current_zone()->to_sys(t1));
auto tm = *std::localtime(&t);
auto sys_output = system_strftime(spec, &tm);
auto fmt_spec = fmt::format("{{:{}}}", spec);
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1));
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
}
if (std::find(spec_list.cbegin(), spec_list.cend(), "%z") !=
spec_list.cend()) {
auto t = std::chrono::system_clock::to_time_t(
std::chrono::current_zone()->to_sys(t1));
auto tm = *std::localtime(&t);
auto sys_output = system_strftime("%z", &tm);
sys_output.insert(sys_output.end() - 2, 1, ':');
EXPECT_EQ(sys_output, fmt::format("{:%Ez}", t1));
EXPECT_EQ(sys_output, fmt::format("{:%Ez}", tm));
EXPECT_EQ(sys_output, fmt::format("{:%Oz}", t1));
EXPECT_EQ(sys_output, fmt::format("{:%Oz}", tm));
}
}
#endif // FMT_USE_LOCAL_TIME
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
TEST(chrono_test, format_default) {
2018-12-09 17:11:52 +00:00
EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
EXPECT_EQ("42as",
fmt::format("{}", std::chrono::duration<int, std::atto>(42)));
EXPECT_EQ("42fs",
fmt::format("{}", std::chrono::duration<int, std::femto>(42)));
EXPECT_EQ("42ps",
fmt::format("{}", std::chrono::duration<int, std::pico>(42)));
EXPECT_EQ("42ns", fmt::format("{}", std::chrono::nanoseconds(42)));
EXPECT_EQ("42µs", fmt::format("{}", std::chrono::microseconds(42)));
EXPECT_EQ("42ms", fmt::format("{}", std::chrono::milliseconds(42)));
EXPECT_EQ("42cs",
fmt::format("{}", std::chrono::duration<int, std::centi>(42)));
EXPECT_EQ("42ds",
fmt::format("{}", std::chrono::duration<int, std::deci>(42)));
EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
EXPECT_EQ("42das",
fmt::format("{}", std::chrono::duration<int, std::deca>(42)));
EXPECT_EQ("42hs",
fmt::format("{}", std::chrono::duration<int, std::hecto>(42)));
EXPECT_EQ("42ks",
fmt::format("{}", std::chrono::duration<int, std::kilo>(42)));
EXPECT_EQ("42Ms",
fmt::format("{}", std::chrono::duration<int, std::mega>(42)));
EXPECT_EQ("42Gs",
fmt::format("{}", std::chrono::duration<int, std::giga>(42)));
EXPECT_EQ("42Ts",
fmt::format("{}", std::chrono::duration<int, std::tera>(42)));
EXPECT_EQ("42Ps",
fmt::format("{}", std::chrono::duration<int, std::peta>(42)));
EXPECT_EQ("42Es",
fmt::format("{}", std::chrono::duration<int, std::exa>(42)));
EXPECT_EQ("42min", fmt::format("{}", std::chrono::minutes(42)));
2018-12-09 17:11:52 +00:00
EXPECT_EQ("42h", fmt::format("{}", std::chrono::hours(42)));
EXPECT_EQ("42d", fmt::format("{}", days(42)));
2019-01-13 02:27:38 +00:00
EXPECT_EQ(
"42[15]s",
fmt::format("{}", std::chrono::duration<int, std::ratio<15, 1>>(42)));
EXPECT_EQ(
"42[15/4]s",
fmt::format("{}", std::chrono::duration<int, std::ratio<15, 4>>(42)));
2018-12-09 17:11:52 +00:00
}
TEST(chrono_test, duration_align) {
auto s = std::chrono::seconds(42);
EXPECT_EQ("42s ", fmt::format("{:5}", s));
EXPECT_EQ("42s ", fmt::format("{:{}}", s, 5));
EXPECT_EQ(" 42s", fmt::format("{:>5}", s));
EXPECT_EQ("**42s**", fmt::format("{:*^7}", s));
EXPECT_EQ("03:25:45 ",
fmt::format("{:12%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ(" 03:25:45",
fmt::format("{:>12%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ("~~03:25:45~~",
fmt::format("{:~^12%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ("03:25:45 ",
fmt::format("{:{}%H:%M:%S}", std::chrono::seconds(12345), 12));
}
TEST(chrono_test, tm_align) {
auto t = make_tm(1975, 12, 29, 12, 14, 16);
EXPECT_EQ("1975-12-29 12:14:16", fmt::format("{:%F %T}", t));
EXPECT_EQ("1975-12-29 12:14:16 ", fmt::format("{:30%F %T}", t));
EXPECT_EQ("1975-12-29 12:14:16 ", fmt::format("{:{}%F %T}", t, 30));
EXPECT_EQ("1975-12-29 12:14:16 ", fmt::format("{:<30%F %T}", t));
EXPECT_EQ(" 1975-12-29 12:14:16 ", fmt::format("{:^30%F %T}", t));
EXPECT_EQ(" 1975-12-29 12:14:16", fmt::format("{:>30%F %T}", t));
EXPECT_EQ("1975-12-29 12:14:16***********", fmt::format("{:*<30%F %T}", t));
EXPECT_EQ("*****1975-12-29 12:14:16******", fmt::format("{:*^30%F %T}", t));
EXPECT_EQ("***********1975-12-29 12:14:16", fmt::format("{:*>30%F %T}", t));
}
TEST(chrono_test, tp_align) {
auto tp = std::chrono::time_point_cast<std::chrono::microseconds>(
std::chrono::system_clock::from_time_t(0));
EXPECT_EQ("00:00.000000", fmt::format("{:%M:%S}", tp));
EXPECT_EQ("00:00.000000 ", fmt::format("{:15%M:%S}", tp));
EXPECT_EQ("00:00.000000 ", fmt::format("{:{}%M:%S}", tp, 15));
EXPECT_EQ("00:00.000000 ", fmt::format("{:<15%M:%S}", tp));
EXPECT_EQ(" 00:00.000000 ", fmt::format("{:^15%M:%S}", tp));
EXPECT_EQ(" 00:00.000000", fmt::format("{:>15%M:%S}", tp));
EXPECT_EQ("00:00.000000***", fmt::format("{:*<15%M:%S}", tp));
EXPECT_EQ("*00:00.000000**", fmt::format("{:*^15%M:%S}", tp));
EXPECT_EQ("***00:00.000000", fmt::format("{:*>15%M:%S}", tp));
}
TEST(chrono_test, format_specs) {
2018-12-09 17:11:52 +00:00
EXPECT_EQ("%", fmt::format("{:%%}", std::chrono::seconds(0)));
EXPECT_EQ("\n", fmt::format("{:%n}", std::chrono::seconds(0)));
EXPECT_EQ("\t", fmt::format("{:%t}", std::chrono::seconds(0)));
EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(0)));
EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(60)));
EXPECT_EQ("42", fmt::format("{:%S}", std::chrono::seconds(42)));
EXPECT_EQ("01.234", fmt::format("{:%S}", std::chrono::milliseconds(1234)));
EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(0)));
EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(60)));
EXPECT_EQ("42", fmt::format("{:%M}", std::chrono::minutes(42)));
EXPECT_EQ("01", fmt::format("{:%M}", std::chrono::seconds(61)));
EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(0)));
EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(24)));
EXPECT_EQ("14", fmt::format("{:%H}", std::chrono::hours(14)));
EXPECT_EQ("01", fmt::format("{:%H}", std::chrono::minutes(61)));
EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(0)));
EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(12)));
EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(24)));
EXPECT_EQ("04", fmt::format("{:%I}", std::chrono::hours(4)));
EXPECT_EQ("02", fmt::format("{:%I}", std::chrono::hours(14)));
EXPECT_EQ("12345", fmt::format("{:%j}", days(12345)));
EXPECT_EQ("12345", fmt::format("{:%j}", std::chrono::hours(12345 * 24 + 12)));
EXPECT_EQ("03:25:45",
fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ("03:25", fmt::format("{:%R}", std::chrono::seconds(12345)));
2018-12-09 17:11:52 +00:00
EXPECT_EQ("03:25:45", fmt::format("{:%T}", std::chrono::seconds(12345)));
EXPECT_EQ("12345", fmt::format("{:%Q}", std::chrono::seconds(12345)));
EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(12345)));
2018-12-09 17:11:52 +00:00
}
TEST(chrono_test, invalid_specs) {
2018-12-09 17:11:52 +00:00
auto sec = std::chrono::seconds(0);
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%a}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%A}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%c}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%x}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Ex}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%X}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%EX}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%D}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%F}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Ec}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%w}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%u}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%b}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%B}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%z}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Z}"), sec), fmt::format_error,
2021-05-19 02:38:52 +00:00
"no date");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Eq}"), sec), fmt::format_error,
2018-12-09 17:11:52 +00:00
"invalid format");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Oq}"), sec), fmt::format_error,
2018-12-09 17:11:52 +00:00
"invalid format");
2022-12-17 09:52:20 +00:00
EXPECT_THROW_MSG((void)fmt::format(runtime("{:abc}"), sec), fmt::format_error,
"invalid format");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:.2f}"), sec), fmt::format_error,
"invalid format");
}
auto format_tm(const std::tm& time, fmt::string_view spec,
const std::locale& loc) -> std::string {
auto& facet = std::use_facet<std::time_put<char>>(loc);
std::ostringstream os;
os.imbue(loc);
facet.put(os, os, ' ', &time, spec.begin(), spec.end());
return os.str();
}
TEST(chrono_test, locale) {
auto loc = get_locale("ja_JP.utf8");
if (loc == std::locale::classic()) return;
# define EXPECT_TIME(spec, time, duration) \
{ \
auto jp_loc = std::locale("ja_JP.utf8"); \
EXPECT_EQ(format_tm(time, spec, jp_loc), \
fmt::format(jp_loc, "{:L" spec "}", duration)); \
}
EXPECT_TIME("%OH", make_hour(14), std::chrono::hours(14));
EXPECT_TIME("%OI", make_hour(14), std::chrono::hours(14));
EXPECT_TIME("%OM", make_minute(42), std::chrono::minutes(42));
EXPECT_TIME("%OS", make_second(42), std::chrono::seconds(42));
auto time = make_tm();
time.tm_hour = 3;
time.tm_min = 25;
time.tm_sec = 45;
2018-12-09 17:11:52 +00:00
auto sec = std::chrono::seconds(12345);
EXPECT_TIME("%r", time, sec);
EXPECT_TIME("%p", time, sec);
}
using dms = std::chrono::duration<double, std::milli>;
TEST(chrono_test, format_default_fp) {
typedef std::chrono::duration<float> fs;
EXPECT_EQ("1.234s", fmt::format("{}", fs(1.234)));
typedef std::chrono::duration<float, std::milli> fms;
EXPECT_EQ("1.234ms", fmt::format("{}", fms(1.234)));
typedef std::chrono::duration<double> ds;
EXPECT_EQ("1.234s", fmt::format("{}", ds(1.234)));
EXPECT_EQ("1.234ms", fmt::format("{}", dms(1.234)));
}
TEST(chrono_test, format_precision) {
EXPECT_THROW_MSG(
(void)fmt::format(runtime("{:.2%Q}"), std::chrono::seconds(42)),
fmt::format_error, "precision not allowed for this argument type");
EXPECT_EQ("1ms", fmt::format("{:.0}", dms(1.234)));
EXPECT_EQ("1.2ms", fmt::format("{:.1}", dms(1.234)));
EXPECT_EQ("1.23ms", fmt::format("{:.{}}", dms(1.234), 2));
EXPECT_EQ("13ms", fmt::format("{:.0}", dms(12.56)));
EXPECT_EQ("12.6ms", fmt::format("{:.1}", dms(12.56)));
EXPECT_EQ("12.56ms", fmt::format("{:.2}", dms(12.56)));
}
TEST(chrono_test, format_full_specs) {
EXPECT_EQ("1ms ", fmt::format("{:6.0}", dms(1.234)));
EXPECT_EQ("1.2ms ", fmt::format("{:6.1}", dms(1.234)));
EXPECT_EQ(" 1.23ms", fmt::format("{:>8.{}}", dms(1.234), 2));
EXPECT_EQ(" 1.2ms ", fmt::format("{:^{}.{}}", dms(1.234), 7, 1));
EXPECT_EQ(" 1.23ms ", fmt::format("{0:^{2}.{1}}", dms(1.234), 2, 8));
EXPECT_EQ("=1.234ms=", fmt::format("{:=^{}.{}}", dms(1.234), 9, 3));
EXPECT_EQ("*1.2340ms*", fmt::format("{:*^10.4}", dms(1.234)));
EXPECT_EQ("13ms ", fmt::format("{:6.0}", dms(12.56)));
EXPECT_EQ(" 13ms", fmt::format("{:>8.{}}", dms(12.56), 0));
EXPECT_EQ(" 13ms ", fmt::format("{:^{}.{}}", dms(12.56), 6, 0));
EXPECT_EQ(" 13ms ", fmt::format("{0:^{2}.{1}}", dms(12.56), 0, 8));
EXPECT_EQ("==13ms===", fmt::format("{:=^{}.{}}", dms(12.56), 9, 0));
EXPECT_EQ("***13ms***", fmt::format("{:*^10.0}", dms(12.56)));
}
TEST(chrono_test, format_simple_q) {
typedef std::chrono::duration<float> fs;
EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", fs(1.234)));
typedef std::chrono::duration<float, std::milli> fms;
EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", fms(1.234)));
typedef std::chrono::duration<double> ds;
EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", ds(1.234)));
EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", dms(1.234)));
}
TEST(chrono_test, format_precision_q) {
EXPECT_THROW_MSG(
(void)fmt::format(runtime("{:.2%Q %q}"), std::chrono::seconds(42)),
fmt::format_error, "precision not allowed for this argument type");
EXPECT_EQ("1.2 ms", fmt::format("{:.1%Q %q}", dms(1.234)));
EXPECT_EQ("1.23 ms", fmt::format("{:.{}%Q %q}", dms(1.234), 2));
}
TEST(chrono_test, format_full_specs_q) {
EXPECT_EQ("1 ms ", fmt::format("{:7.0%Q %q}", dms(1.234)));
EXPECT_EQ("1.2 ms ", fmt::format("{:7.1%Q %q}", dms(1.234)));
EXPECT_EQ(" 1.23 ms", fmt::format("{:>8.{}%Q %q}", dms(1.234), 2));
EXPECT_EQ(" 1.2 ms ", fmt::format("{:^{}.{}%Q %q}", dms(1.234), 8, 1));
EXPECT_EQ(" 1.23 ms ", fmt::format("{0:^{2}.{1}%Q %q}", dms(1.234), 2, 9));
EXPECT_EQ("=1.234 ms=", fmt::format("{:=^{}.{}%Q %q}", dms(1.234), 10, 3));
EXPECT_EQ("*1.2340 ms*", fmt::format("{:*^11.4%Q %q}", dms(1.234)));
EXPECT_EQ("13 ms ", fmt::format("{:7.0%Q %q}", dms(12.56)));
EXPECT_EQ(" 13 ms", fmt::format("{:>8.{}%Q %q}", dms(12.56), 0));
EXPECT_EQ(" 13 ms ", fmt::format("{:^{}.{}%Q %q}", dms(12.56), 8, 0));
EXPECT_EQ(" 13 ms ", fmt::format("{0:^{2}.{1}%Q %q}", dms(12.56), 0, 9));
EXPECT_EQ("==13 ms==", fmt::format("{:=^{}.{}%Q %q}", dms(12.56), 9, 0));
EXPECT_EQ("***13 ms***", fmt::format("{:*^11.0%Q %q}", dms(12.56)));
}
TEST(chrono_test, invalid_width_id) {
EXPECT_THROW((void)fmt::format(runtime("{:{o}"), std::chrono::seconds(0)),
fmt::format_error);
}
TEST(chrono_test, invalid_colons) {
EXPECT_THROW((void)fmt::format(runtime("{0}=:{0::"), std::chrono::seconds(0)),
fmt::format_error);
}
TEST(chrono_test, negative_durations) {
EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345)));
EXPECT_EQ("-03:25:45",
fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345)));
EXPECT_EQ("-00:01",
fmt::format("{:%M:%S}", std::chrono::duration<double>(-1)));
EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(-12345)));
EXPECT_EQ("-00.127",
fmt::format("{:%S}",
std::chrono::duration<signed char, std::milli>{-127}));
auto min = std::numeric_limits<int>::min();
EXPECT_EQ(fmt::format("{}", min),
fmt::format("{:%Q}", std::chrono::duration<int>(min)));
}
TEST(chrono_test, special_durations) {
auto value = fmt::format("{:%S}", std::chrono::duration<double>(1e20));
EXPECT_EQ(value, "40");
2019-05-05 15:34:54 +00:00
auto nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_EQ(
add oss-fuzz support see https://github.com/google/oss-fuzz/pull/2381 the history of the fuzz branch is long and messy and is difficult to rebase on top of the current master. Squashed commit of the following: commit b9d6db50010e185d0af2590a35472e9334102248 Author: Paul Dreik <github@pauldreik.se> Date: Sat Jun 29 21:50:34 2019 +0200 update exception with a more accurate description commit f3fbaf60cc80c7f57fa95962dc0069b10c3d3e61 Author: Paul Dreik <github@pauldreik.se> Date: Sat Jun 29 21:34:55 2019 +0200 fix missing flags in reproduce build commit 40a17bec7a1ad724203577842a254ca9c42da388 Author: Paul Dreik <github@pauldreik.se> Date: Sat Jun 29 21:22:48 2019 +0200 move check for large precision values closer to where needed commit ef6e23e1f52d639c5aec1a1e713157cec380a8c3 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 28 20:55:34 2019 +0200 simplify the fuzzer build script commit eadee6e0557be6df695e80f0f2717046a29846e0 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 28 20:47:54 2019 +0200 minimize source code pollution commit 1ece6416438f199c164ee9aa89f42ad1f21a4985 Merge: f404079b 037b84f2 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 28 20:22:52 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # CMakeLists.txt commit f404079b4e00e51b0d5a4c9218cbe7afb350b777 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 28 20:20:52 2019 +0200 make named_arg write into a string or a memory_buffer this makes the fuzzer consistent with the others. commit 545dbe136817eef9e734c32991a324874a51bb4a Author: Paul Dreik <github@pauldreik.se> Date: Thu Jun 20 06:34:17 2019 +0200 tidy up extra newlines, missing std:: etc. commit 2d816ef2b13fc2a46c0df76a91f7912bd7196087 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:49:08 2019 +0200 update unit test to handle expected result following review comment commit a5b9a26808d0165acd2edc4c3baabf9bff40d8bd Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:40:06 2019 +0200 update build script to reflect changes after review commit 8411cb78984f76c74bca273c0bb18918e084e711 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:39:39 2019 +0200 review comment: clarify what the .gitignore is for commit 18d9e7bb43d98568fe491e076106e4fa29070b33 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:36:56 2019 +0200 review comment: don't touch root .gitignore commit 7683d7faa116a6e261da824ec6c1a6a75689841b Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:35:40 2019 +0200 review comment: condiionally include main.cpp commit be0bdaeb27b0c1914cc0b0fd85c2b3bcc6fd2245 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:31:28 2019 +0200 review comment: drop commented out code not working on travis commit 013429812d7fb745eec146296623ea245c4848b4 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:30:26 2019 +0200 review comment: renumber case labels the old ones were to be able to reuse the corpus, let's drop it commit f66fe7bead4a71978f21d9e47a8f3f9e4935fccd Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:06:47 2019 +0200 review comment: libfmt->fmt commit 4a4ddb654dd5b90646cd7e6ff45318c17b66dc9f Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:05:32 2019 +0200 reuse fmt_safe_duration_cast commit 0a1679411a8bd77c2ff34e1cd572307c92e12040 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:02:48 2019 +0200 review comment: name convention, better name C was for "chrono duration" commit 63084cac00b798c636e0dc13207df46a5c4539f6 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 20:00:50 2019 +0200 reuse earlier extract fmt_safe_... function commit b23388d4d7f919163ead9a9e9bdd50d14daf80b7 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 19:58:55 2019 +0200 review comment: don't output inf.inf commit 6f861f1d89d2127bbe2446d176d59a354665cc15 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 19:57:00 2019 +0200 review comment: extract function for invoking safe_duration_cast commit df19bc87ccff77d4bedf54fa3d3992f78ef699bd Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 19:47:30 2019 +0200 review comment: leftover garbage commit 84eea802efb1164c4f2a83b2e480a7c5bdf4e921 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 19:45:22 2019 +0200 review comment: turn cmake option into macro for SAFE_DURATION_CAST decided to have it on by default commit c3a159498c2544a52662cd03d23d5a1d00537bba Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 19:40:14 2019 +0200 review comment: extra newline commit aa556875c5161d817c347ff984dad171c7a35df9 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 19:38:49 2019 +0200 review comment: file name convention commit 4102d82c455324bda4ccd64072eab86b3f0ecebf Merge: 28add37d 4912cff6 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 17 16:29:29 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 28add37df3944cbaa00f614e8063210a6d83c17c Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 21:44:06 2019 +0200 disable check to pass travis commit 4119378aedfd3e4063058e8f1f03c29d9f44d5e8 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 21:32:39 2019 +0200 add missing include commit ba2efb82f20d6ecb5e49a8c6ced96a7febedc175 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 21:04:41 2019 +0200 try working around build issue on travis commit 380671a2cb6e52f2b7d5eaad409d491baba5b7e6 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 20:22:41 2019 +0200 write positive infinity without sign commit fd72b9adace17e00c46aae24e061bf14c3af6bb1 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 20:20:50 2019 +0200 remove leftover from merge commit 1ae3128be2c53914e4c840d12e1b02c59758c378 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 20:14:45 2019 +0200 format to buffer instead of string commit 1d83a561244c2fe81231d17e911c6eb24c87cac4 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 19:50:19 2019 +0200 fix warnings commit a33b45a7bb5cf70eb3ef1cd95908282621195f1f Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 19:43:46 2019 +0200 refactor and fix warnings commit 02afb12dd5b05804a1a8b55e1b9fb7e3de593e84 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 19:17:27 2019 +0200 use fixed size input commit 35f84c8cf20efb18a137efecd10dcdc6bcebf7b5 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 19:07:43 2019 +0200 factor out main into a separate file commit a23b7a198ba739dd813897901855c98441e6f29b Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 18:56:40 2019 +0200 refactor commit 9a3f4cfb3bc32a304a1a49b8ff24fbc2f924266c Merge: 7842582a 12f46838 Author: Paul Dreik <github@pauldreik.se> Date: Fri Jun 14 18:20:03 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # include/fmt/chrono.h commit 7842582a0089c24a5d44bbb2d156beb732bb7b58 Merge: 90cab5aa cbbee1b3 Author: Paul Dreik <github@pauldreik.se> Date: Thu Jun 13 10:41:34 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 90cab5aa023271a3a746cf9c60dd613b4546ca10 Merge: 8feb8a3f e5422db4 Author: Paul Dreik <github@pauldreik.se> Date: Wed Jun 12 18:49:08 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 8feb8a3fe20da043a8303e59b1580b4b2862cc57 Merge: e9fabac1 87fbc6f7 Author: Paul Dreik <github@pauldreik.se> Date: Tue Jun 11 19:18:35 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit e9fabac1dd6d710fec1b30ca51dc953f57f2f9f5 Merge: eaff9316 e1a67b52 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 10 22:38:36 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit eaff93166402ff9a16a9ab0fab1081104f4f06b8 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 22:29:01 2019 +0200 drop old crashes commit 7f861e481abb7367bd187c92fe202e25d36d0dd0 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 21:47:30 2019 +0200 build fuzzers as part of the linux clang 6 build commit 42c339066dce148723f452d4a94487a6ac80637f Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 21:42:12 2019 +0200 travis has old libs commit 9264e3ac82582a941eba3501301dee1468175c08 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 21:33:26 2019 +0200 more travis workarounds commit c6eed3adaf6cf65d440dd58c88a034f61c55114f Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 21:27:49 2019 +0200 travis workaround commit 5e230d6240841dbc67f0c08ace3a1c24defea54f Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 21:15:36 2019 +0200 fix constexpr issues commit cc5fc033479c769a8ac19115aef48020c532c943 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 21:11:13 2019 +0200 add a fuzzer build commit 3997375296eca0d0455e0935ef3aed8b010ecf2d Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:53:04 2019 +0200 fix minor documentation errors commit 1572411261abd5c0756ff2998ab707f1131d4fdf Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:49:25 2019 +0200 polish the documentation commit 9e5274437cfc3e9c82131c14cf7f3a0abdb10025 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:32:45 2019 +0200 remove unused headers commit 4b2492a5e037d3153de342ef7f2729b69e8f5dce Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:28:12 2019 +0200 clang format commit a0004ebb417bce5a24c15ea65a0f3741e45b8480 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:27:02 2019 +0200 format also void* commit 820142ee2076ae17fea25857c41a1ecdca4a8521 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:12:21 2019 +0200 improve two_args with lessons learnt from the others commit 7b8fd7f5123fccf78b600c69ca25d025582c095e Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:11:18 2019 +0200 improve function names commit 641bf36a7a061abf6a02d5e31f3adeb33b079f43 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:07:29 2019 +0200 clang format commit 7975c0c3cbe19a7159336ad8fcb170fa6259b1cb Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 20:06:02 2019 +0200 apply lessons learned from chrono fuzzer on sprintf commit 972124c9f921f8ef786f99c294f556bb7dd9b9ee Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:55:49 2019 +0200 format to buffer instead of string commit 7b015c692364d1e087a59dfe83dda1b8f8fd2991 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:50:25 2019 +0200 apply lessons learned from the chrono fuzzer at one_arg commit daa8ea95dd71704e367b760fa6605f5a7cac6890 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:41:17 2019 +0200 renumber cases commit a667365d0e0f3eb0bc6d6f2cfee5e128a6574aee Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:38:06 2019 +0200 clang format commit e0e361b8a3594c43e131d661a28381613a186c2b Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:36:35 2019 +0200 disable fuzzing by default commit ccb4274ab246ee1fe3becb2b73432179a8a5fe6f Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:36:25 2019 +0200 refresh named_arg with lessons learnt from the chrono fuzzer commit 60da706d4ef35c18eb967bf4ba8d395ef05a9c61 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:36:00 2019 +0200 fix build error commit e361bfc24246d7c7e91f5e45209eda2f22689d98 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 19:00:11 2019 +0200 add comment about formatting to string vs. memory buffer commit 74c0ed062d34eae1786ca699886ad4f3bccc7fd1 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 18:51:23 2019 +0200 try to use better names commit 4efea36f77020eecf3c7826f891417f94aedf6f4 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 18:46:07 2019 +0200 fix clang build error commit 03cdd2e4631ad302dde3e1048671d3bb08956096 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 18:44:21 2019 +0200 drop workarounds fixed upstream commit e936829ebbd97ed2e6f8c5f595b414c0982f2e4d Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 18:41:02 2019 +0200 move the fuzzers into the test/ subdirectory commit 2967765698259764c1f06966a7cdefbc5365e5f2 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 18:30:03 2019 +0200 revert temporary tests handled upstream commit 749c5027b0eab3d90d8fbfb6e55ee313a7f7dfe4 Merge: dee69088 5d9100fa Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 17:49:00 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit dee690881bd33bb77bee1d5ffce643e8bef84a33 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 17:40:37 2019 +0200 keep documentation comment formatted properly commit 87d2c99487eef586ce54d432697f384cbe7a50e1 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 17:36:12 2019 +0200 switch to fmt constexpr macros commit c23fa59139c425a3dfa2e5eeaeb3269c251c90d1 Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 17:30:22 2019 +0200 clang format commit 9e58207e9b24a8cc90c721277405b409dd61740d Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 17:27:03 2019 +0200 get rid of safe_duration_cast submodule replaced with an embedded miniature version commit a4d36eac46e5db45ded96f80f84986f4f76ea0ec Author: Paul Dreik <github@pauldreik.se> Date: Sun Jun 9 17:25:00 2019 +0200 add safe_duration_cast into fmt commit 7d5b0ecef37722c40952251c88d74a2552221d84 Author: Paul Dreik <github@pauldreik.se> Date: Sat Jun 8 22:39:33 2019 +0200 mark #1194 as fixed commit ee91514ecf7a8788f2081996db85eef50d7cd57b Merge: 60569117 4faadff0 Author: Paul Dreik <github@pauldreik.se> Date: Sat Jun 8 22:25:37 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 6056911784bc86e6caf56a61fd64142f113d531e Author: Paul Dreik <github@pauldreik.se> Date: Wed Jun 5 09:58:30 2019 +0200 format to small size buffer instead of string commit 9f006097255c239188840b589f6e39cbb4476481 Author: Paul Dreik <github@pauldreik.se> Date: Wed Jun 5 09:45:23 2019 +0200 switch to fmt::string_view and workaround reported bug commit 387de0d9440852fac974ff165b2555d54e2380da Author: Paul Dreik <github@pauldreik.se> Date: Wed Jun 5 06:26:15 2019 +0200 ignore build directories commit 55da271c5bb3c11a239c4e46570b6741803ce329 Merge: 3716491e c264e641 Author: Paul Dreik <github@pauldreik.se> Date: Wed Jun 5 06:12:36 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 3716491ec51c34a918834857c67300eea180ba02 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 3 07:03:29 2019 +0200 fix UB in on_second commit 2740241b13b7417a4dae655f825ea5a551ffe7ba Merge: 1c258402 d54e64b3 Author: Paul Dreik <github@pauldreik.se> Date: Mon Jun 3 06:37:18 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # include/fmt/chrono.h commit 1c258402a4bd03f390e0256fa9475cc5187d37f9 Merge: ca9596d1 f57227a1 Author: Paul Dreik <github@pauldreik.se> Date: Sat Jun 1 08:01:58 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit ca9596d1c91b0315b407ce2c4b3e9e5ba1aeb640 Merge: 1c274cfd d07cc202 Author: Paul Dreik <github@pauldreik.se> Date: Thu May 30 19:42:33 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 1c274cfd4112138bfc59dd16f58022016128fe85 Author: Paul Dreik <github@pauldreik.se> Date: Thu May 30 08:12:10 2019 +0200 make it easier for the chrono fuzzer to explore using a fixed size makes the cases cross pollinate each other better. the execution speed is much higher as well commit f0d7cccdc70c98576b7129428c416e7c9e68a8aa Author: Paul Dreik <github@pauldreik.se> Date: Thu May 30 07:36:21 2019 +0200 add a build adapted for analysis of fuzzing performance commit 56f7cf3fa979de415174a10b18221727e3138b7b Author: Paul Dreik <github@pauldreik.se> Date: Thu May 30 06:25:10 2019 +0200 allow negative values again commit a77a5fc505bbeab1cfa36be16d40f7799689317a Author: Paul Dreik <github@pauldreik.se> Date: Thu May 30 05:45:55 2019 +0200 fix UB on signed int overflow in chrono_formatter constructor see https://github.com/fmtlib/fmt/issues/1179 commit b6a592720be520b58ed2f2d8668ffc6c8b71f0f7 Merge: 492a2046 30bce6c1 Author: Paul Dreik <github@pauldreik.se> Date: Thu May 30 05:26:30 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # include/fmt/chrono.h commit 492a204623c3c4bbf04c9d47d69979d3a484959c Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 21:36:00 2019 +0200 fix bad assert commit 0ae68b03fbb0e80e292a01f529d5cd7e76349907 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 21:35:49 2019 +0200 add unsigned types for chrono fuzzing commit 2753d7db76645e8847ff2110c5e98f5c8de4a6b9 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 20:25:21 2019 +0200 use C++17 commit bc12742f098ec8b513985daedc57faa518203eb0 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 19:44:59 2019 +0200 add symlink for safe_duration_cast commit 67201d2639b93736768e109d73b3e9ccc9401c48 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 19:40:40 2019 +0200 turn on safe duration cast for the fuzzer builds commit 31a70080a63a5213594e4b4e6a33e7e315cf756e Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 19:32:52 2019 +0200 clang format commit 981e30c5782d04453ece1b31e887da4f29268370 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 19:30:19 2019 +0200 reduce maximum allocation size commit 7ba51da81de7ecbc5498a22dc29de5b0648bcad2 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 19:30:01 2019 +0200 make nan unit test pass commit 95b4b9c28a589c30727826dd4e1367bebfad5894 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 18:39:08 2019 +0200 special case nan and inf commit 2673c965506e51d150c005340698a6e15d98aaba Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 16:40:11 2019 +0200 build a fast fuzzer, for making coverage fast commit db52b62612fd7ea3ceeaee05584fd8cb83e54a35 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 16:39:48 2019 +0200 add safe duration cast as submodule commit c8a028faec5d91728472f5de01ea8b1766fb929d Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 16:00:26 2019 +0200 enable chrono fuzzing for non-negative values commit de3555cc573e561691858ca16586f8b45a3ae703 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 13:06:35 2019 +0200 try start using safe duration cast commit 5c3245118c3debcb3f6f69c04c2c32d48449ee16 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 09:59:34 2019 +0200 add failing test commit 3a565d3b091c29210e24042f86869fecafb70914 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 09:59:09 2019 +0200 fix cmake option type (should be string, not bool) commit 61c67564207a13992b1c69d95614b2c4aec5df86 Merge: 63e7b9e3 bb254d14 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 29 07:03:42 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 63e7b9e32c714c594d019ef463c9c40a3510a2f2 Merge: 7dd1d80f 5e7bdf1b Author: Paul Dreik <github@pauldreik.se> Date: Fri May 17 19:17:20 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 7dd1d80f3a32465d0fa13ce733bff8686a5b0bad Merge: 2c9aa5a3 2a9e8b52 Author: Paul Dreik <github@pauldreik.se> Date: Tue May 14 19:38:32 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 2c9aa5a31e64af25f8bb4afa8134258822532d3e Merge: 16a442c8 2c77562b Author: Paul Dreik <github@pauldreik.se> Date: Tue May 14 06:33:16 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 16a442c864dbdce70c22b4a859dba5e3b5edaf35 Merge: b1d70b61 f4dfd6e3 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 12 15:24:31 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # include/fmt/chrono.h commit b1d70b6144c7a61e580eb44ec7d1bdd2368f5531 Author: Paul Dreik <github@pauldreik.se> Date: Fri May 10 08:52:57 2019 +0200 prevent excessive time (found by oss-fuzz) the following triggered this: std::string message = fmt::format("\377{:.214718908}\377", fmt::arg("/\0", 0.f)); there are probably more places with calls to fill_n which could be checked commit 9a91093a6b20fd22afd6739f5dcba3b00f6f8eaf Merge: 7de0fdec e9bab6d0 Author: Paul Dreik <github@pauldreik.se> Date: Thu May 9 06:06:32 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # include/fmt/chrono.h commit 7de0fdec38270f2d0302413904a5ef1b13d47177 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 20:08:53 2019 +0200 clang format commit bb375e1ca10eb3cc2c6684bf698ad4738ab7eb10 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 19:47:10 2019 +0200 seems to pass the unit test now (except for the nan stuff from victor) commit 786b4b7351bc8e305ad7e68d11ca6b542f66d456 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 19:25:23 2019 +0200 add assert triggering data, and unit test commit 2790e480b81ec83d00315aa69407fe71b8c4c637 Merge: fa859a05 ca978b3d Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 18:42:51 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit fa859a05c2c3abef263166f3a44cdbaa3122d642 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 18:18:54 2019 +0200 add crash commit 1f6e341b1c4bc966a44c7a98b63f22bd65958d0b Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 18:18:27 2019 +0200 assert floating point is finite internally commit 50877748d08a0f4433af4f1213c5bc9021e76e7a Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 17:32:03 2019 +0200 invoke undefined behaviour inside chrono commit bac7ac4149f2d001f7b36236e1710484674d029b Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 17:31:35 2019 +0200 refactor the fuzzer build script commit b19c4cd84a0c8b6d4a7beb281ad881156173ce78 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 16:25:11 2019 +0200 add one more crash commit 7607592e06ebaa189dc180441fa1863430e0938e Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 16:24:05 2019 +0200 add crashing input commit b059a98b27b40cd284e08a54493c25363d743557 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 16:21:25 2019 +0200 trigger undefined behaviour with NaN durations commit 7cce33250282b397c00159e6809125f5fc1c0190 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 16:20:51 2019 +0200 add asan only fuzzer commit 757319a4e30978d8661b3be8f75937266071b413 Merge: a574b21c c1d430e6 Author: Paul Dreik <github@pauldreik.se> Date: Sun May 5 06:34:59 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # test/chrono-test.cc commit a574b21c840339abef5e4ad33612b6efac6ad54b Author: Paul Dreik <github@pauldreik.se> Date: Sat May 4 12:54:13 2019 +0200 disable chrono fuzzing for now it triggers integer overflow and is not trivial to solve. commit ff17322bceba53e0c2d9ebcf3756115ad148195e Merge: d6a59851 29c10fbf Author: Paul Dreik <github@pauldreik.se> Date: Sat May 4 07:29:39 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit d6a598511c7dc0c208c2d688b2943b0d7c092029 Merge: 663b1592 4a4d72f9 Author: Paul Dreik <github@pauldreik.se> Date: Wed May 1 20:44:16 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz # Conflicts: # test/chrono-test.cc commit 663b159235f8ae5f58fe80bb02d49bfa392056b0 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 22:36:07 2019 +0200 add crash case (triggers assertion) commit 082a5cb226142ea30b415d4231cea9425748741a Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 21:44:19 2019 +0200 add const commit b8d70919ea6be0d2e4c58ef82887496f55125ba9 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 21:29:43 2019 +0200 provoke assertion fmt/include/fmt/core.h:246: typename std::make_unsigned<_Tp>::type fmt::v5::internal::to_unsigned(Int) [with Int = long int; typename std::make_unsigned<_Tp>::type = long unsigned int]: Assertion `(value >= 0) && "negative value"' failed. commit e1966013af4eb7febf047d4629cc6236a6aae0e3 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 20:46:16 2019 +0200 add more crashes commit 1394ae3fe915319ce7dc63d6a9dc820a29c9539e Merge: 89338cad 4c721e3a Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 17:16:14 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 89338cad4eed9441644ec8c5f1687b511c829ea4 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 09:40:32 2019 +0200 add notes on how to reproduce crashes commit 7dc3e4c7223617da274c4cccb9cf5459d0510e0b Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 09:28:20 2019 +0200 add crashes from chrono duration commit b62e8bc783134c2d15ebf0372c8a61b41624e6b1 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 09:26:53 2019 +0200 rename fuzzer commit 7f4ab2b80d072fe3ad96e37e45f3fa807a85c99f Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 09:15:38 2019 +0200 clang format commit a6cc2a35a9799e88b9ed89e578b7aefd9b09ad09 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 09:12:04 2019 +0200 add chrono duration fuzzer commit 682713c9a61d52b46e95fdb7d970a8733f77ce88 Merge: 8b934b37 8d8ea21c Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 28 08:07:56 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 8b934b37161d1389de603ced6560982507bb7ae5 Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 10:23:44 2019 +0200 clang format commit 793d97b9af33269f5628094f547f9771e968e3f2 Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 10:23:17 2019 +0200 tighten memory allocation commit e2301f2430b15c9817433206597ef82c990f49a0 Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 10:19:56 2019 +0200 clean up and set license (BSD 2-clause simplified, same as fmt) commit e64c3fb35719afa644dee1f9f17829cace6e17ff Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 10:04:23 2019 +0200 clean up and add afl commit ab46241206aaf46759fd3f292ee4a1088b652d15 Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 09:54:48 2019 +0200 drop c++17 requirement commit 20c01e1acf330c8a28192f55b16efeebddb72ab0 Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 09:25:19 2019 +0200 initial oss-fuzz compatible version commit 6cbd91a37cf36a1d0e994bb16cf44a12622f7dca Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 08:42:51 2019 +0200 initial commit of fuzzers from https://github.com/pauldreik/fuzzfmt commit eaddfb16d86ef1c259b737e2aab40145b0c956a6 Merge: e37d7db3 134904c8 Author: Paul Dreik <github@pauldreik.se> Date: Sat Apr 27 08:38:19 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit e37d7db3b938c82f569d71e6bb00bd1bf8394db7 Merge: 99b2e08b bd516e34 Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 21 17:28:06 2019 +0200 Merge remote-tracking branch 'upstream/master' into fuzz commit 99b2e08b6bef25b793df5ef07621c9c4402587de Author: Paul Dreik <github@pauldreik.se> Date: Sun Apr 21 10:30:56 2019 +0200 stop high memory use when fuzzing
2019-06-30 07:11:13 +00:00
"nan nan nan nan nan:nan nan",
2019-05-05 15:34:54 +00:00
fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan)));
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::exa>(1)),
"1Es");
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)),
"1as");
EXPECT_EQ(fmt::format("{:%R}", std::chrono::duration<char, std::mega>{2}),
"03:33");
EXPECT_EQ(fmt::format("{:%T}", std::chrono::duration<char, std::mega>{2}),
"03:33:20");
2023-07-20 20:47:32 +00:00
EXPECT_EQ("01.234",
fmt::format("{:.3%S}", std::chrono::duration<float, std::pico>(
1.234e12)));
2019-05-04 23:33:17 +00:00
}
TEST(chrono_test, unsigned_duration) {
2020-11-12 15:00:11 +00:00
EXPECT_EQ("42s", fmt::format("{}", std::chrono::duration<unsigned>(42)));
}
2021-05-25 13:40:21 +00:00
TEST(chrono_test, weekday) {
2023-10-08 15:45:37 +00:00
auto loc = get_locale("es_ES.UTF-8");
std::locale::global(loc);
2023-10-08 15:45:37 +00:00
auto sat = fmt::weekday(6);
auto tm = std::tm();
2023-10-08 15:45:37 +00:00
tm.tm_wday = static_cast<int>(sat.c_encoding());
2023-10-08 15:45:37 +00:00
EXPECT_EQ(fmt::format("{}", sat), "Sat");
EXPECT_EQ(fmt::format("{:%a}", tm), "Sat");
if (loc != std::locale::classic()) {
2023-10-08 15:45:37 +00:00
auto saturdays = std::vector<std::string>{"sáb", "sá."};
EXPECT_THAT(saturdays, Contains(fmt::format(loc, "{:L}", sat)));
EXPECT_THAT(saturdays, Contains(fmt::format(loc, "{:%a}", tm)));
}
}
TEST(chrono_test, cpp20_duration_subsecond_support) {
using attoseconds = std::chrono::duration<long long, std::atto>;
// Check that 18 digits of subsecond precision are supported.
EXPECT_EQ(fmt::format("{:%S}", attoseconds{999999999999999999}),
"00.999999999999999999");
EXPECT_EQ(fmt::format("{:%S}", attoseconds{673231113420148734}),
"00.673231113420148734");
EXPECT_EQ(fmt::format("{:%S}", attoseconds{-673231113420148734}),
"-00.673231113420148734");
EXPECT_EQ(fmt::format("{:%S}", std::chrono::nanoseconds{13420148734}),
"13.420148734");
EXPECT_EQ(fmt::format("{:%S}", std::chrono::nanoseconds{-13420148734}),
"-13.420148734");
EXPECT_EQ(fmt::format("{:%S}", std::chrono::milliseconds{1234}), "01.234");
// Check subsecond presision modifier.
EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::nanoseconds{1234}),
"00.000001");
EXPECT_EQ(fmt::format("{:.18%S}", std::chrono::nanoseconds{1234}),
"00.000001234000000000");
EXPECT_EQ(fmt::format("{:.{}%S}", std::chrono::nanoseconds{1234}, 6),
"00.000001");
EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{1234}),
"01.234000");
EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}),
"-01.234000");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::seconds{1234}), "34.000");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::hours{1234}), "00.000");
EXPECT_EQ(fmt::format("{:.5%S}", dms(1.234)), "00.00123");
EXPECT_EQ(fmt::format("{:.8%S}", dms(1.234)), "00.00123400");
{
// Check that {:%H:%M:%S} is equivalent to {:%T}.
auto dur = std::chrono::milliseconds{3601234};
auto formatted_dur = fmt::format("{:%T}", dur);
EXPECT_EQ(formatted_dur, "01:00:01.234");
EXPECT_EQ(fmt::format("{:%H:%M:%S}", dur), formatted_dur);
EXPECT_EQ(fmt::format("{:.6%H:%M:%S}", dur), "01:00:01.234000");
}
using nanoseconds_dbl = std::chrono::duration<double, std::nano>;
EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{-123456789}), "-00.123456789");
EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{9123456789}), "09.123456789");
// Verify that only the seconds part is extracted and printed.
EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{99123456789}), "39.123456789");
EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{99123000000}), "39.123000000");
{
// Now the hour is printed, and we also test if negative doubles work.
auto dur = nanoseconds_dbl{-99123456789};
auto formatted_dur = fmt::format("{:%T}", dur);
EXPECT_EQ(formatted_dur, "-00:01:39.123456789");
EXPECT_EQ(fmt::format("{:%H:%M:%S}", dur), formatted_dur);
EXPECT_EQ(fmt::format("{:.3%H:%M:%S}", dur), "-00:01:39.123");
}
// Check that durations with precision greater than std::chrono::seconds have
// fixed precision, and print zeros even if there is no fractional part.
EXPECT_EQ(fmt::format("{:%S}", std::chrono::microseconds{7000000}),
"07.000000");
EXPECT_EQ(fmt::format("{:%S}",
std::chrono::duration<long long, std::ratio<1, 3>>(1)),
"00.333333");
EXPECT_EQ(fmt::format("{:%S}",
std::chrono::duration<long long, std::ratio<1, 7>>(1)),
"00.142857");
EXPECT_EQ(
fmt::format("{:%S}",
std::chrono::duration<signed char, std::ratio<1, 100>>(0x80)),
"-01.28");
EXPECT_EQ(
fmt::format("{:%M:%S}",
std::chrono::duration<short, std::ratio<1, 100>>(0x8000)),
"-05:27.68");
// Check that floating point seconds with ratio<1,1> are printed.
EXPECT_EQ(fmt::format("{:%S}", std::chrono::duration<double>{1.5}),
"01.500000");
EXPECT_EQ(fmt::format("{:%M:%S}", std::chrono::duration<double>{-61.25}),
"-01:01.250000");
}
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
// Disable the utc_clock test for windows, as the icu.dll used for tzdb
// (time zone database) is not shipped with many windows versions.
#if FMT_USE_UTC_TIME && !defined(_WIN32)
TEST(chrono_test, utc_clock) {
auto t1 = std::chrono::system_clock::now();
auto t1_utc = std::chrono::utc_clock::from_sys(t1);
EXPECT_EQ(fmt::format("{:%Y-%m-%d %H:%M:%S}", t1),
fmt::format("{:%Y-%m-%d %H:%M:%S}", t1_utc));
}
#endif
TEST(chrono_test, timestamps_ratios) {
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
t1(std::chrono::milliseconds(67890));
EXPECT_EQ(fmt::format("{:%M:%S}", t1), "01:07.890");
std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>
t2(std::chrono::minutes(7));
EXPECT_EQ(fmt::format("{:%M:%S}", t2), "07:00");
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<int, std::ratio<9>>>
t3(std::chrono::duration<int, std::ratio<9>>(7));
EXPECT_EQ(fmt::format("{:%M:%S}", t3), "01:03");
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<int, std::ratio<63>>>
t4(std::chrono::duration<int, std::ratio<63>>(1));
EXPECT_EQ(fmt::format("{:%M:%S}", t4), "01:03");
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
t5(std::chrono::seconds(32503680000));
EXPECT_EQ(fmt::format("{:%Y-%m-%d}", t5), "3000-01-01");
#if FMT_SAFE_DURATION_CAST
using years = std::chrono::duration<std::int64_t, std::ratio<31556952>>;
std::chrono::time_point<std::chrono::system_clock, years> t6(
(years(std::numeric_limits<std::int64_t>::max())));
EXPECT_THROW_MSG((void)fmt::format("{:%Y-%m-%d}", t6), fmt::format_error,
"cannot format duration");
#endif
}
TEST(chrono_test, timestamps_sub_seconds) {
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<long long, std::ratio<1, 3>>>
t1(std::chrono::duration<long long, std::ratio<1, 3>>(4));
EXPECT_EQ(fmt::format("{:%S}", t1), "01.333333");
std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<double, std::ratio<1, 3>>>
t2(std::chrono::duration<double, std::ratio<1, 3>>(4));
EXPECT_EQ(fmt::format("{:%S}", t2), "01.333333");
const std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>
t3(std::chrono::seconds(2));
EXPECT_EQ(fmt::format("{:%S}", t3), "02");
const std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<double>>
t4(std::chrono::duration<double, std::ratio<1, 1>>(9.5));
EXPECT_EQ(fmt::format("{:%S}", t4), "09.500000");
const std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<double>>
t5(std::chrono::duration<double, std::ratio<1, 1>>(9));
EXPECT_EQ(fmt::format("{:%S}", t5), "09");
const std::chrono::time_point<std::chrono::system_clock,
std::chrono::milliseconds>
t6(std::chrono::seconds(1) + std::chrono::milliseconds(120));
EXPECT_EQ(fmt::format("{:%S}", t6), "01.120");
const std::chrono::time_point<std::chrono::system_clock,
std::chrono::microseconds>
t7(std::chrono::microseconds(1234567));
EXPECT_EQ(fmt::format("{:%S}", t7), "01.234567");
const std::chrono::time_point<std::chrono::system_clock,
std::chrono::nanoseconds>
t8(std::chrono::nanoseconds(123456789));
EXPECT_EQ(fmt::format("{:%S}", t8), "00.123456789");
const auto t9 = std::chrono::time_point_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now());
const auto t9_sec = std::chrono::time_point_cast<std::chrono::seconds>(t9);
auto t9_sub_sec_part = fmt::format("{0:09}", (t9 - t9_sec).count());
EXPECT_EQ(fmt::format("{}.{}", strftime_full_utc(t9_sec), t9_sub_sec_part),
fmt::format("{:%Y-%m-%d %H:%M:%S}", t9));
2023-03-18 14:16:22 +00:00
EXPECT_EQ(fmt::format("{}.{}", strftime_full_utc(t9_sec), t9_sub_sec_part),
fmt::format("{:%Y-%m-%d %T}", t9));
const std::chrono::time_point<std::chrono::system_clock,
std::chrono::milliseconds>
t10(std::chrono::milliseconds(2000));
EXPECT_EQ(fmt::format("{:%S}", t10), "02.000");
{
const auto epoch = std::chrono::time_point<std::chrono::system_clock,
std::chrono::milliseconds>();
const auto d = std::chrono::milliseconds(250);
EXPECT_EQ("59.750", fmt::format("{:%S}", epoch - d));
EXPECT_EQ("00.000", fmt::format("{:%S}", epoch));
EXPECT_EQ("00.250", fmt::format("{:%S}", epoch + d));
}
}
TEST(chrono_test, glibc_extensions) {
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%0}"), std::chrono::seconds()),
fmt::format_error, "invalid format");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%_}"), std::chrono::seconds()),
fmt::format_error, "invalid format");
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%-}"), std::chrono::seconds()),
fmt::format_error, "invalid format");
{
const auto d = std::chrono::hours(1) + std::chrono::minutes(2) +
std::chrono::seconds(3);
EXPECT_EQ(fmt::format("{:%I,%H,%M,%S}", d), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%0I,%0H,%0M,%0S}", d), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%_I,%_H,%_M,%_S}", d), " 1, 1, 2, 3");
EXPECT_EQ(fmt::format("{:%-I,%-H,%-M,%-S}", d), "1,1,2,3");
EXPECT_EQ(fmt::format("{:%OI,%OH,%OM,%OS}", d), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%0OI,%0OH,%0OM,%0OS}", d), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%_OI,%_OH,%_OM,%_OS}", d), " 1, 1, 2, 3");
EXPECT_EQ(fmt::format("{:%-OI,%-OH,%-OM,%-OS}", d), "1,1,2,3");
}
{
const auto tm = make_tm(1970, 1, 1, 1, 2, 3);
EXPECT_EQ(fmt::format("{:%I,%H,%M,%S}", tm), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%0I,%0H,%0M,%0S}", tm), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%_I,%_H,%_M,%_S}", tm), " 1, 1, 2, 3");
EXPECT_EQ(fmt::format("{:%-I,%-H,%-M,%-S}", tm), "1,1,2,3");
EXPECT_EQ(fmt::format("{:%OI,%OH,%OM,%OS}", tm), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%0OI,%0OH,%0OM,%0OS}", tm), "01,01,02,03");
EXPECT_EQ(fmt::format("{:%_OI,%_OH,%_OM,%_OS}", tm), " 1, 1, 2, 3");
EXPECT_EQ(fmt::format("{:%-OI,%-OH,%-OM,%-OS}", tm), "1,1,2,3");
}
{
const auto d = std::chrono::seconds(3) + std::chrono::milliseconds(140);
EXPECT_EQ(fmt::format("{:%S}", d), "03.140");
EXPECT_EQ(fmt::format("{:%0S}", d), "03.140");
EXPECT_EQ(fmt::format("{:%_S}", d), " 3.140");
EXPECT_EQ(fmt::format("{:%-S}", d), "3.140");
}
{
const auto d = std::chrono::duration<double>(3.14);
EXPECT_EQ(fmt::format("{:%S}", d), "03.140000");
EXPECT_EQ(fmt::format("{:%0S}", d), "03.140000");
EXPECT_EQ(fmt::format("{:%_S}", d), " 3.140000");
EXPECT_EQ(fmt::format("{:%-S}", d), "3.140000");
}
}