]> git.proxmox.com Git - ceph.git/blame - ceph/src/fmt/test/chrono-test.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / fmt / test / chrono-test.cc
CommitLineData
eafe8130
TL
1// Formatting library for C++ - time formatting tests
2//
3// Copyright (c) 2012 - present, Victor Zverovich
4// All rights reserved.
5//
6// For the license information refer to format.h.
7
8#include "fmt/chrono.h"
eafe8130 9
20effc67
TL
10#include "gtest-extra.h" // EXPECT_THROW_MSG
11#include "util.h" // get_locale
12
13using fmt::runtime;
eafe8130 14
20effc67 15using testing::Contains;
f67539c2 16
20effc67 17auto make_tm() -> std::tm {
eafe8130
TL
18 auto time = std::tm();
19 time.tm_mday = 1;
20 return time;
21}
22
20effc67 23auto make_hour(int h) -> std::tm {
eafe8130
TL
24 auto time = make_tm();
25 time.tm_hour = h;
26 return time;
27}
28
20effc67 29auto make_minute(int m) -> std::tm {
eafe8130
TL
30 auto time = make_tm();
31 time.tm_min = m;
32 return time;
33}
34
20effc67 35auto make_second(int s) -> std::tm {
eafe8130
TL
36 auto time = make_tm();
37 time.tm_sec = s;
38 return time;
39}
40
20effc67
TL
41TEST(chrono_test, format_tm) {
42 auto tm = std::tm();
9f95a23c
TL
43 tm.tm_year = 116;
44 tm.tm_mon = 3;
45 tm.tm_mday = 25;
20effc67
TL
46 tm.tm_hour = 11;
47 tm.tm_min = 22;
48 tm.tm_sec = 33;
49 EXPECT_EQ(fmt::format("The date is {:%Y-%m-%d %H:%M:%S}.", tm),
50 "The date is 2016-04-25 11:22:33.");
9f95a23c
TL
51}
52
20effc67
TL
53TEST(chrono_test, grow_buffer) {
54 auto s = std::string("{:");
9f95a23c
TL
55 for (int i = 0; i < 30; ++i) s += "%c";
56 s += "}\n";
20effc67
TL
57 auto t = std::time(nullptr);
58 fmt::format(fmt::runtime(s), *std::localtime(&t));
9f95a23c
TL
59}
60
20effc67 61TEST(chrono_test, format_to_empty_container) {
9f95a23c
TL
62 auto time = std::tm();
63 time.tm_sec = 42;
20effc67 64 auto s = std::string();
9f95a23c
TL
65 fmt::format_to(std::back_inserter(s), "{:%S}", time);
66 EXPECT_EQ(s, "42");
67}
68
20effc67 69TEST(chrono_test, empty_result) { EXPECT_EQ(fmt::format("{}", std::tm()), ""); }
9f95a23c 70
20effc67 71auto equal(const std::tm& lhs, const std::tm& rhs) -> bool {
9f95a23c
TL
72 return lhs.tm_sec == rhs.tm_sec && lhs.tm_min == rhs.tm_min &&
73 lhs.tm_hour == rhs.tm_hour && lhs.tm_mday == rhs.tm_mday &&
74 lhs.tm_mon == rhs.tm_mon && lhs.tm_year == rhs.tm_year &&
75 lhs.tm_wday == rhs.tm_wday && lhs.tm_yday == rhs.tm_yday &&
76 lhs.tm_isdst == rhs.tm_isdst;
77}
78
20effc67
TL
79TEST(chrono_test, localtime) {
80 auto t = std::time(nullptr);
81 auto tm = *std::localtime(&t);
82 EXPECT_TRUE(equal(tm, fmt::localtime(t)));
9f95a23c
TL
83}
84
20effc67
TL
85TEST(chrono_test, gmtime) {
86 auto t = std::time(nullptr);
87 auto tm = *std::gmtime(&t);
88 EXPECT_TRUE(equal(tm, fmt::gmtime(t)));
9f95a23c
TL
89}
90
20effc67
TL
91template <typename TimePoint> auto strftime(TimePoint tp) -> std::string {
92 auto t = std::chrono::system_clock::to_time_t(tp);
93 auto tm = *std::localtime(&t);
94 char output[256] = {};
95 std::strftime(output, sizeof(output), "%Y-%m-%d %H:%M:%S", &tm);
96 return output;
97}
98
99TEST(chrono_test, time_point) {
100 auto t1 = std::chrono::system_clock::now();
101 EXPECT_EQ(strftime(t1), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1));
102 EXPECT_EQ(strftime(t1), fmt::format("{}", t1));
103 using time_point =
104 std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
105 auto t2 = time_point(std::chrono::seconds(42));
106 EXPECT_EQ(strftime(t2), fmt::format("{:%Y-%m-%d %H:%M:%S}", t2));
107}
eafe8130 108
9f95a23c
TL
109#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
110
20effc67 111TEST(chrono_test, format_default) {
eafe8130
TL
112 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
113 EXPECT_EQ("42as",
114 fmt::format("{}", std::chrono::duration<int, std::atto>(42)));
115 EXPECT_EQ("42fs",
116 fmt::format("{}", std::chrono::duration<int, std::femto>(42)));
117 EXPECT_EQ("42ps",
118 fmt::format("{}", std::chrono::duration<int, std::pico>(42)));
119 EXPECT_EQ("42ns", fmt::format("{}", std::chrono::nanoseconds(42)));
120 EXPECT_EQ("42µs", fmt::format("{}", std::chrono::microseconds(42)));
121 EXPECT_EQ("42ms", fmt::format("{}", std::chrono::milliseconds(42)));
122 EXPECT_EQ("42cs",
123 fmt::format("{}", std::chrono::duration<int, std::centi>(42)));
124 EXPECT_EQ("42ds",
125 fmt::format("{}", std::chrono::duration<int, std::deci>(42)));
126 EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
127 EXPECT_EQ("42das",
128 fmt::format("{}", std::chrono::duration<int, std::deca>(42)));
129 EXPECT_EQ("42hs",
130 fmt::format("{}", std::chrono::duration<int, std::hecto>(42)));
131 EXPECT_EQ("42ks",
132 fmt::format("{}", std::chrono::duration<int, std::kilo>(42)));
133 EXPECT_EQ("42Ms",
134 fmt::format("{}", std::chrono::duration<int, std::mega>(42)));
135 EXPECT_EQ("42Gs",
136 fmt::format("{}", std::chrono::duration<int, std::giga>(42)));
137 EXPECT_EQ("42Ts",
138 fmt::format("{}", std::chrono::duration<int, std::tera>(42)));
139 EXPECT_EQ("42Ps",
140 fmt::format("{}", std::chrono::duration<int, std::peta>(42)));
141 EXPECT_EQ("42Es",
142 fmt::format("{}", std::chrono::duration<int, std::exa>(42)));
143 EXPECT_EQ("42m", fmt::format("{}", std::chrono::minutes(42)));
144 EXPECT_EQ("42h", fmt::format("{}", std::chrono::hours(42)));
9f95a23c
TL
145 EXPECT_EQ(
146 "42[15]s",
147 fmt::format("{}", std::chrono::duration<int, std::ratio<15, 1>>(42)));
148 EXPECT_EQ(
149 "42[15/4]s",
150 fmt::format("{}", std::chrono::duration<int, std::ratio<15, 4>>(42)));
151}
152
20effc67 153TEST(chrono_test, align) {
9f95a23c
TL
154 auto s = std::chrono::seconds(42);
155 EXPECT_EQ("42s ", fmt::format("{:5}", s));
156 EXPECT_EQ("42s ", fmt::format("{:{}}", s, 5));
157 EXPECT_EQ(" 42s", fmt::format("{:>5}", s));
158 EXPECT_EQ("**42s**", fmt::format("{:*^7}", s));
159 EXPECT_EQ("03:25:45 ",
160 fmt::format("{:12%H:%M:%S}", std::chrono::seconds(12345)));
161 EXPECT_EQ(" 03:25:45",
162 fmt::format("{:>12%H:%M:%S}", std::chrono::seconds(12345)));
163 EXPECT_EQ("~~03:25:45~~",
164 fmt::format("{:~^12%H:%M:%S}", std::chrono::seconds(12345)));
165 EXPECT_EQ("03:25:45 ",
166 fmt::format("{:{}%H:%M:%S}", std::chrono::seconds(12345), 12));
eafe8130
TL
167}
168
20effc67 169TEST(chrono_test, format_specs) {
eafe8130
TL
170 EXPECT_EQ("%", fmt::format("{:%%}", std::chrono::seconds(0)));
171 EXPECT_EQ("\n", fmt::format("{:%n}", std::chrono::seconds(0)));
172 EXPECT_EQ("\t", fmt::format("{:%t}", std::chrono::seconds(0)));
173 EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(0)));
174 EXPECT_EQ("00", fmt::format("{:%S}", std::chrono::seconds(60)));
175 EXPECT_EQ("42", fmt::format("{:%S}", std::chrono::seconds(42)));
176 EXPECT_EQ("01.234", fmt::format("{:%S}", std::chrono::milliseconds(1234)));
177 EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(0)));
178 EXPECT_EQ("00", fmt::format("{:%M}", std::chrono::minutes(60)));
179 EXPECT_EQ("42", fmt::format("{:%M}", std::chrono::minutes(42)));
180 EXPECT_EQ("01", fmt::format("{:%M}", std::chrono::seconds(61)));
181 EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(0)));
182 EXPECT_EQ("00", fmt::format("{:%H}", std::chrono::hours(24)));
183 EXPECT_EQ("14", fmt::format("{:%H}", std::chrono::hours(14)));
184 EXPECT_EQ("01", fmt::format("{:%H}", std::chrono::minutes(61)));
185 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(0)));
186 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(12)));
187 EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(24)));
188 EXPECT_EQ("04", fmt::format("{:%I}", std::chrono::hours(4)));
189 EXPECT_EQ("02", fmt::format("{:%I}", std::chrono::hours(14)));
190 EXPECT_EQ("03:25:45",
191 fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
192 EXPECT_EQ("03:25", fmt::format("{:%R}", std::chrono::seconds(12345)));
193 EXPECT_EQ("03:25:45", fmt::format("{:%T}", std::chrono::seconds(12345)));
9f95a23c
TL
194 EXPECT_EQ("12345", fmt::format("{:%Q}", std::chrono::seconds(12345)));
195 EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(12345)));
eafe8130
TL
196}
197
20effc67 198TEST(chrono_test, invalid_specs) {
eafe8130 199 auto sec = std::chrono::seconds(0);
20effc67
TL
200 EXPECT_THROW_MSG(fmt::format(runtime("{:%a}"), sec), fmt::format_error,
201 "no date");
202 EXPECT_THROW_MSG(fmt::format(runtime("{:%A}"), sec), fmt::format_error,
203 "no date");
204 EXPECT_THROW_MSG(fmt::format(runtime("{:%c}"), sec), fmt::format_error,
205 "no date");
206 EXPECT_THROW_MSG(fmt::format(runtime("{:%x}"), sec), fmt::format_error,
207 "no date");
208 EXPECT_THROW_MSG(fmt::format(runtime("{:%Ex}"), sec), fmt::format_error,
209 "no date");
210 EXPECT_THROW_MSG(fmt::format(runtime("{:%X}"), sec), fmt::format_error,
211 "no date");
212 EXPECT_THROW_MSG(fmt::format(runtime("{:%EX}"), sec), fmt::format_error,
213 "no date");
214 EXPECT_THROW_MSG(fmt::format(runtime("{:%D}"), sec), fmt::format_error,
215 "no date");
216 EXPECT_THROW_MSG(fmt::format(runtime("{:%F}"), sec), fmt::format_error,
217 "no date");
218 EXPECT_THROW_MSG(fmt::format(runtime("{:%Ec}"), sec), fmt::format_error,
219 "no date");
220 EXPECT_THROW_MSG(fmt::format(runtime("{:%w}"), sec), fmt::format_error,
221 "no date");
222 EXPECT_THROW_MSG(fmt::format(runtime("{:%u}"), sec), fmt::format_error,
223 "no date");
224 EXPECT_THROW_MSG(fmt::format(runtime("{:%b}"), sec), fmt::format_error,
225 "no date");
226 EXPECT_THROW_MSG(fmt::format(runtime("{:%B}"), sec), fmt::format_error,
227 "no date");
228 EXPECT_THROW_MSG(fmt::format(runtime("{:%z}"), sec), fmt::format_error,
229 "no date");
230 EXPECT_THROW_MSG(fmt::format(runtime("{:%Z}"), sec), fmt::format_error,
231 "no date");
232 EXPECT_THROW_MSG(fmt::format(runtime("{:%Eq}"), sec), fmt::format_error,
eafe8130 233 "invalid format");
20effc67 234 EXPECT_THROW_MSG(fmt::format(runtime("{:%Oq}"), sec), fmt::format_error,
eafe8130
TL
235 "invalid format");
236}
237
20effc67
TL
238auto format_tm(const std::tm& time, fmt::string_view spec,
239 const std::locale& loc) -> std::string {
240 auto& facet = std::use_facet<std::time_put<char>>(loc);
241 std::ostringstream os;
242 os.imbue(loc);
243 facet.put(os, os, ' ', &time, spec.begin(), spec.end());
244 return os.str();
245}
246
247TEST(chrono_test, locale) {
248 auto loc = get_locale("ja_JP.utf8");
249 if (loc == std::locale::classic()) return;
250# define EXPECT_TIME(spec, time, duration) \
251 { \
252 auto jp_loc = std::locale("ja_JP.utf8"); \
253 EXPECT_EQ(format_tm(time, spec, jp_loc), \
254 fmt::format(jp_loc, "{:L" spec "}", duration)); \
255 }
eafe8130
TL
256 EXPECT_TIME("%OH", make_hour(14), std::chrono::hours(14));
257 EXPECT_TIME("%OI", make_hour(14), std::chrono::hours(14));
258 EXPECT_TIME("%OM", make_minute(42), std::chrono::minutes(42));
259 EXPECT_TIME("%OS", make_second(42), std::chrono::seconds(42));
260 auto time = make_tm();
261 time.tm_hour = 3;
262 time.tm_min = 25;
263 time.tm_sec = 45;
264 auto sec = std::chrono::seconds(12345);
265 EXPECT_TIME("%r", time, sec);
266 EXPECT_TIME("%p", time, sec);
267}
9f95a23c 268
20effc67 269using dms = std::chrono::duration<double, std::milli>;
9f95a23c 270
20effc67 271TEST(chrono_test, format_default_fp) {
9f95a23c
TL
272 typedef std::chrono::duration<float> fs;
273 EXPECT_EQ("1.234s", fmt::format("{}", fs(1.234)));
274 typedef std::chrono::duration<float, std::milli> fms;
275 EXPECT_EQ("1.234ms", fmt::format("{}", fms(1.234)));
276 typedef std::chrono::duration<double> ds;
277 EXPECT_EQ("1.234s", fmt::format("{}", ds(1.234)));
278 EXPECT_EQ("1.234ms", fmt::format("{}", dms(1.234)));
279}
280
20effc67
TL
281TEST(chrono_test, format_precision) {
282 EXPECT_THROW_MSG(fmt::format(runtime("{:.2}"), std::chrono::seconds(42)),
9f95a23c
TL
283 fmt::format_error,
284 "precision not allowed for this argument type");
285 EXPECT_EQ("1.2ms", fmt::format("{:.1}", dms(1.234)));
286 EXPECT_EQ("1.23ms", fmt::format("{:.{}}", dms(1.234), 2));
287}
288
20effc67 289TEST(chrono_test, format_full_specs) {
9f95a23c
TL
290 EXPECT_EQ("1.2ms ", fmt::format("{:6.1}", dms(1.234)));
291 EXPECT_EQ(" 1.23ms", fmt::format("{:>8.{}}", dms(1.234), 2));
292 EXPECT_EQ(" 1.2ms ", fmt::format("{:^{}.{}}", dms(1.234), 7, 1));
293 EXPECT_EQ(" 1.23ms ", fmt::format("{0:^{2}.{1}}", dms(1.234), 2, 8));
294 EXPECT_EQ("=1.234ms=", fmt::format("{:=^{}.{}}", dms(1.234), 9, 3));
295 EXPECT_EQ("*1.2340ms*", fmt::format("{:*^10.4}", dms(1.234)));
296}
297
20effc67 298TEST(chrono_test, format_simple_q) {
9f95a23c
TL
299 typedef std::chrono::duration<float> fs;
300 EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", fs(1.234)));
301 typedef std::chrono::duration<float, std::milli> fms;
302 EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", fms(1.234)));
303 typedef std::chrono::duration<double> ds;
304 EXPECT_EQ("1.234 s", fmt::format("{:%Q %q}", ds(1.234)));
305 EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", dms(1.234)));
306}
307
20effc67
TL
308TEST(chrono_test, format_precision_q) {
309 EXPECT_THROW_MSG(fmt::format(runtime("{:.2%Q %q}"), std::chrono::seconds(42)),
9f95a23c
TL
310 fmt::format_error,
311 "precision not allowed for this argument type");
312 EXPECT_EQ("1.2 ms", fmt::format("{:.1%Q %q}", dms(1.234)));
313 EXPECT_EQ("1.23 ms", fmt::format("{:.{}%Q %q}", dms(1.234), 2));
314}
315
20effc67 316TEST(chrono_test, format_full_specs_q) {
9f95a23c
TL
317 EXPECT_EQ("1.2 ms ", fmt::format("{:7.1%Q %q}", dms(1.234)));
318 EXPECT_EQ(" 1.23 ms", fmt::format("{:>8.{}%Q %q}", dms(1.234), 2));
319 EXPECT_EQ(" 1.2 ms ", fmt::format("{:^{}.{}%Q %q}", dms(1.234), 8, 1));
320 EXPECT_EQ(" 1.23 ms ", fmt::format("{0:^{2}.{1}%Q %q}", dms(1.234), 2, 9));
321 EXPECT_EQ("=1.234 ms=", fmt::format("{:=^{}.{}%Q %q}", dms(1.234), 10, 3));
322 EXPECT_EQ("*1.2340 ms*", fmt::format("{:*^11.4%Q %q}", dms(1.234)));
323}
324
20effc67
TL
325TEST(chrono_test, invalid_width_id) {
326 EXPECT_THROW(fmt::format(runtime("{:{o}"), std::chrono::seconds(0)),
f67539c2
TL
327 fmt::format_error);
328}
329
20effc67
TL
330TEST(chrono_test, invalid_colons) {
331 EXPECT_THROW(fmt::format(runtime("{0}=:{0::"), std::chrono::seconds(0)),
f67539c2
TL
332 fmt::format_error);
333}
334
20effc67 335TEST(chrono_test, negative_durations) {
f67539c2
TL
336 EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345)));
337 EXPECT_EQ("-03:25:45",
338 fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345)));
339 EXPECT_EQ("-00:01",
340 fmt::format("{:%M:%S}", std::chrono::duration<double>(-1)));
341 EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(-12345)));
342 EXPECT_EQ("-00.127",
343 fmt::format("{:%S}",
344 std::chrono::duration<signed char, std::milli>{-127}));
345 auto min = std::numeric_limits<int>::min();
346 EXPECT_EQ(fmt::format("{}", min),
347 fmt::format("{:%Q}", std::chrono::duration<int>(min)));
348}
349
20effc67 350TEST(chrono_test, special_durations) {
f67539c2
TL
351 EXPECT_EQ(
352 "40.",
353 fmt::format("{:%S}", std::chrono::duration<double>(1e20)).substr(0, 3));
354 auto nan = std::numeric_limits<double>::quiet_NaN();
355 EXPECT_EQ(
356 "nan nan nan nan nan:nan nan",
357 fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan)));
358 fmt::format("{:%S}",
359 std::chrono::duration<float, std::atto>(1.79400457e+31f));
360 EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::exa>(1)),
361 "1Es");
362 EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)),
363 "1as");
364 EXPECT_EQ(fmt::format("{:%R}", std::chrono::duration<char, std::mega>{2}),
365 "03:33");
366 EXPECT_EQ(fmt::format("{:%T}", std::chrono::duration<char, std::mega>{2}),
367 "03:33:20");
368}
369
20effc67
TL
370TEST(chrono_test, unsigned_duration) {
371 EXPECT_EQ("42s", fmt::format("{}", std::chrono::duration<unsigned>(42)));
372}
373
374TEST(chrono_test, weekday) {
375 auto loc = get_locale("ru_RU.UTF-8");
376 std::locale::global(loc);
377 auto mon = fmt::weekday(1);
378 EXPECT_EQ(fmt::format("{}", mon), "Mon");
379 if (loc != std::locale::classic()) {
380 EXPECT_THAT((std::vector<std::string>{"пн", "Пн", "пнд", "Пнд"}),
381 Contains(fmt::format(loc, "{:L}", mon)));
382 }
383}
384
9f95a23c 385#endif // FMT_STATIC_THOUSANDS_SEPARATOR