aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/fmt/test
diff options
context:
space:
mode:
authordakovalkov <dakovalkov@yandex-team.com>2023-02-17 12:41:41 +0300
committerdakovalkov <dakovalkov@yandex-team.com>2023-02-17 12:41:41 +0300
commitcd21459f6ea789b57cb76b39cb52553923024abd (patch)
tree332cedd2db0f9ce57952887c19c1ce97e775cd52 /contrib/libs/fmt/test
parent14530b5eb2df23bc3b0027fdd6d07e0035bafe2e (diff)
downloadydb-cd21459f6ea789b57cb76b39cb52553923024abd.tar.gz
Update fmtlib to 8.1.1 + spdlog to 1.11.0 + jinja2cpp to 1.2.1
Diffstat (limited to 'contrib/libs/fmt/test')
-rw-r--r--contrib/libs/fmt/test/args-test.cc186
-rw-r--r--contrib/libs/fmt/test/assert-test.cc9
-rw-r--r--contrib/libs/fmt/test/chrono-test.cc521
-rw-r--r--contrib/libs/fmt/test/color-test.cc69
-rw-r--r--contrib/libs/fmt/test/compile-fp-test.cc62
-rw-r--r--contrib/libs/fmt/test/compile-test.cc397
-rw-r--r--contrib/libs/fmt/test/core-test.cc890
-rw-r--r--contrib/libs/fmt/test/enforce-checks-test.cc63
-rw-r--r--contrib/libs/fmt/test/format-impl-test.cc165
-rw-r--r--contrib/libs/fmt/test/format-test.cc2719
-rw-r--r--contrib/libs/fmt/test/gtest-extra-test.cc124
-rw-r--r--contrib/libs/fmt/test/gtest-extra.cc45
-rw-r--r--contrib/libs/fmt/test/gtest-extra.h51
-rw-r--r--contrib/libs/fmt/test/header-only-test.cc8
-rw-r--r--contrib/libs/fmt/test/header-only-test2.cc3
-rw-r--r--contrib/libs/fmt/test/locale-test.cc160
-rw-r--r--contrib/libs/fmt/test/mock-allocator.h12
-rw-r--r--contrib/libs/fmt/test/os-test.cc311
-rw-r--r--contrib/libs/fmt/test/ostream-test.cc229
-rw-r--r--contrib/libs/fmt/test/posix-mock-test.cc138
-rw-r--r--contrib/libs/fmt/test/printf-test.cc234
-rw-r--r--contrib/libs/fmt/test/ranges-odr-test.cc17
-rw-r--r--contrib/libs/fmt/test/ranges-test.cc372
-rw-r--r--contrib/libs/fmt/test/scan-test.cc38
-rw-r--r--contrib/libs/fmt/test/scan.h9
-rw-r--r--contrib/libs/fmt/test/test-assert.h13
-rw-r--r--contrib/libs/fmt/test/unicode-test.cc48
-rw-r--r--contrib/libs/fmt/test/util.cc46
-rw-r--r--contrib/libs/fmt/test/util.h39
-rw-r--r--contrib/libs/fmt/test/xchar-test.cc502
30 files changed, 4226 insertions, 3254 deletions
diff --git a/contrib/libs/fmt/test/args-test.cc b/contrib/libs/fmt/test/args-test.cc
new file mode 100644
index 0000000000..aa01fa4e08
--- /dev/null
+++ b/contrib/libs/fmt/test/args-test.cc
@@ -0,0 +1,186 @@
+// Formatting library for C++ - dynamic argument store tests
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include "fmt/args.h"
+
+#include <memory>
+
+#include "gtest/gtest.h"
+
+TEST(args_test, basic) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ store.push_back(42);
+ store.push_back("abc1");
+ store.push_back(1.5f);
+ EXPECT_EQ("42 and abc1 and 1.5", fmt::vformat("{} and {} and {}", store));
+}
+
+TEST(args_test, strings_and_refs) {
+ // Unfortunately the tests are compiled with old ABI so strings use COW.
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ char str[] = "1234567890";
+ store.push_back(str);
+ store.push_back(std::cref(str));
+ store.push_back(fmt::string_view{str});
+ str[0] = 'X';
+
+ auto result = fmt::vformat("{} and {} and {}", store);
+ EXPECT_EQ("1234567890 and X234567890 and X234567890", result);
+}
+
+struct custom_type {
+ int i = 0;
+};
+
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<custom_type> {
+ auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+
+ template <typename FormatContext>
+ auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) {
+ return format_to(ctx.out(), "cust={}", p.i);
+ }
+};
+FMT_END_NAMESPACE
+
+TEST(args_test, custom_format) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ auto c = custom_type();
+ store.push_back(c);
+ ++c.i;
+ store.push_back(c);
+ ++c.i;
+ store.push_back(std::cref(c));
+ ++c.i;
+ auto result = fmt::vformat("{} and {} and {}", store);
+ EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
+}
+
+struct to_stringable {
+ friend fmt::string_view to_string_view(to_stringable) { return {}; }
+};
+
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<to_stringable> {
+ auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+
+ auto format(to_stringable, format_context& ctx) -> decltype(ctx.out()) {
+ return ctx.out();
+ }
+};
+FMT_END_NAMESPACE
+
+TEST(args_test, to_string_and_formatter) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ auto s = to_stringable();
+ store.push_back(s);
+ store.push_back(std::cref(s));
+ fmt::vformat("", store);
+}
+
+TEST(args_test, named_int) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ store.push_back(fmt::arg("a1", 42));
+ EXPECT_EQ("42", fmt::vformat("{a1}", store));
+}
+
+TEST(args_test, named_strings) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ char str[] = "1234567890";
+ store.push_back(fmt::arg("a1", str));
+ store.push_back(fmt::arg("a2", std::cref(str)));
+ str[0] = 'X';
+ EXPECT_EQ("1234567890 and X234567890", fmt::vformat("{a1} and {a2}", store));
+}
+
+TEST(args_test, named_arg_by_ref) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ char band[] = "Rolling Stones";
+ store.push_back(fmt::arg("band", std::cref(band)));
+ band[9] = 'c'; // Changing band affects the output.
+ EXPECT_EQ(fmt::vformat("{band}", store), "Rolling Scones");
+}
+
+TEST(args_test, named_custom_format) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ auto c = custom_type();
+ store.push_back(fmt::arg("c1", c));
+ ++c.i;
+ store.push_back(fmt::arg("c2", c));
+ ++c.i;
+ store.push_back(fmt::arg("c_ref", std::cref(c)));
+ ++c.i;
+ auto result = fmt::vformat("{c1} and {c2} and {c_ref}", store);
+ EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
+}
+
+TEST(args_test, clear) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ store.push_back(42);
+
+ auto result = fmt::vformat("{}", store);
+ EXPECT_EQ("42", result);
+
+ store.push_back(43);
+ result = fmt::vformat("{} and {}", store);
+ EXPECT_EQ("42 and 43", result);
+
+ store.clear();
+ store.push_back(44);
+ result = fmt::vformat("{}", store);
+ EXPECT_EQ("44", result);
+}
+
+TEST(args_test, reserve) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ store.reserve(2, 1);
+ store.push_back(1.5f);
+ store.push_back(fmt::arg("a1", 42));
+ auto result = fmt::vformat("{a1} and {}", store);
+ EXPECT_EQ("42 and 1.5", result);
+}
+
+struct copy_throwable {
+ copy_throwable() {}
+ copy_throwable(const copy_throwable&) { throw "deal with it"; }
+};
+
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<copy_throwable> {
+ auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+ auto format(copy_throwable, format_context& ctx) -> decltype(ctx.out()) {
+ return ctx.out();
+ }
+};
+FMT_END_NAMESPACE
+
+TEST(args_test, throw_on_copy) {
+ fmt::dynamic_format_arg_store<fmt::format_context> store;
+ store.push_back(std::string("foo"));
+ try {
+ store.push_back(copy_throwable());
+ } catch (...) {
+ }
+ EXPECT_EQ(fmt::vformat("{}", store), "foo");
+}
+
+TEST(args_test, move_constructor) {
+ using store_type = fmt::dynamic_format_arg_store<fmt::format_context>;
+ auto store = std::unique_ptr<store_type>(new store_type());
+ store->push_back(42);
+ store->push_back(std::string("foo"));
+ store->push_back(fmt::arg("a1", "foo"));
+ auto moved_store = std::move(*store);
+ store.reset();
+ EXPECT_EQ(fmt::vformat("{} {} {a1}", moved_store), "42 foo foo");
+}
diff --git a/contrib/libs/fmt/test/assert-test.cc b/contrib/libs/fmt/test/assert-test.cc
index 73f622e56b..c74e617e68 100644
--- a/contrib/libs/fmt/test/assert-test.cc
+++ b/contrib/libs/fmt/test/assert-test.cc
@@ -10,9 +10,9 @@
// For the license information refer to format.h.
#include "fmt/core.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
-TEST(AssertTest, Fail) {
+TEST(assert_test, fail) {
#if GTEST_HAS_DEATH_TEST
EXPECT_DEBUG_DEATH(FMT_ASSERT(false, "don't panic!"), "don't panic!");
#else
@@ -20,9 +20,8 @@ TEST(AssertTest, Fail) {
#endif
}
-bool test_condition = false;
-
-TEST(AssertTest, DanglingElse) {
+TEST(assert_test, dangling_else) {
+ bool test_condition = false;
bool executed_else = false;
if (test_condition)
FMT_ASSERT(true, "");
diff --git a/contrib/libs/fmt/test/chrono-test.cc b/contrib/libs/fmt/test/chrono-test.cc
index fa383c1446..42360e5f12 100644
--- a/contrib/libs/fmt/test/chrono-test.cc
+++ b/contrib/libs/fmt/test/chrono-test.cc
@@ -5,77 +5,221 @@
//
// For the license information refer to format.h.
-#ifdef WIN32
-# define _CRT_SECURE_NO_WARNINGS
-#endif
-
#include "fmt/chrono.h"
-#include <iomanip>
+#include <ctime>
+#include <vector>
+
+#include "gtest-extra.h" // EXPECT_THROW_MSG
+#include "util.h" // get_locale
+
+using fmt::runtime;
-#include "gtest-extra.h"
+using testing::Contains;
-std::tm make_tm() {
+auto make_tm() -> std::tm {
auto time = std::tm();
time.tm_mday = 1;
return time;
}
-std::tm make_hour(int h) {
+auto make_hour(int h) -> std::tm {
auto time = make_tm();
time.tm_hour = h;
return time;
}
-std::tm make_minute(int m) {
+auto make_minute(int m) -> std::tm {
auto time = make_tm();
time.tm_min = m;
return time;
}
-std::tm make_second(int s) {
+auto make_second(int s) -> std::tm {
auto time = make_tm();
time.tm_sec = s;
return time;
}
-std::string format_tm(const std::tm& time, const char* spec,
- const std::locale& loc) {
+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, ' ', &time, spec, spec + std::strlen(spec));
+ facet.put(os, os, ' ', timeptr, format.c_str(),
+ format.c_str() + format.size());
+#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();
+#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(TimeTest, Format) {
- std::tm tm = std::tm();
+TEST(chrono_test, format_tm) {
+ auto tm = std::tm();
tm.tm_year = 116;
tm.tm_mon = 3;
tm.tm_mday = 25;
- EXPECT_EQ("The date is 2016-04-25.",
- fmt::format("The date is {:%Y-%m-%d}.", tm));
+ 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");
+ EXPECT_EQ(fmt::format("{:%C}", tm), "20");
+ 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");
+ EXPECT_EQ(fmt::format("{:%F}", tm), "2016-04-25");
+ EXPECT_EQ(fmt::format("{:%T}", tm), "11:22:33");
+
+ // Short year
+ tm.tm_year = 999 - 1900;
+ tm.tm_mon = 0; // for %G
+ tm.tm_mday = 2; // for %G
+ tm.tm_wday = 3; // for %G
+ tm.tm_yday = 1; // for %G
+ EXPECT_EQ(fmt::format("{:%Y}", tm), "0999");
+ EXPECT_EQ(fmt::format("{:%C%y}", tm), "0999");
+ EXPECT_EQ(fmt::format("{:%G}", tm), "0999");
+
+ 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");
+
+ // 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
+ };
+ 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);
+ 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));
+ }
}
-TEST(TimeTest, GrowBuffer) {
- std::string s = "{:";
+// 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");
+ EXPECT_EQ(fmt::format("{:%C}", tm), "123");
+ 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");
+
+ // macOS %C - "-1"
+ // Linux %C - "-2"
+ // fmt %C - "-1"
+ EXPECT_EQ(fmt::format("{:%C}", tm), "-1");
+ EXPECT_EQ(fmt::format("{:%C%y}", tm), fmt::format("{:%Y}", tm));
+
+ // 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("{:");
for (int i = 0; i < 30; ++i) s += "%c";
s += "}\n";
- std::time_t t = std::time(nullptr);
- fmt::format(s, *std::localtime(&t));
+ auto t = std::time(nullptr);
+ (void)fmt::format(fmt::runtime(s), *std::localtime(&t));
}
-TEST(TimeTest, FormatToEmptyContainer) {
- std::string s;
+TEST(chrono_test, format_to_empty_container) {
auto time = std::tm();
time.tm_sec = 42;
+ auto s = std::string();
fmt::format_to(std::back_inserter(s), "{:%S}", time);
EXPECT_EQ(s, "42");
}
-TEST(TimeTest, EmptyResult) { EXPECT_EQ("", fmt::format("{}", std::tm())); }
+TEST(chrono_test, empty_result) { EXPECT_EQ(fmt::format("{}", std::tm()), ""); }
-static bool EqualTime(const std::tm& lhs, const std::tm& rhs) {
+auto equal(const std::tm& lhs, const std::tm& rhs) -> bool {
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 &&
@@ -83,39 +227,62 @@ static bool EqualTime(const std::tm& lhs, const std::tm& rhs) {
lhs.tm_isdst == rhs.tm_isdst;
}
-TEST(TimeTest, LocalTime) {
- std::time_t t = std::time(nullptr);
- std::tm tm = *std::localtime(&t);
- EXPECT_TRUE(EqualTime(tm, fmt::localtime(t)));
+TEST(chrono_test, localtime) {
+ auto t = std::time(nullptr);
+ auto tm = *std::localtime(&t);
+ EXPECT_TRUE(equal(tm, fmt::localtime(t)));
}
-TEST(TimeTest, GMTime) {
- std::time_t t = std::time(nullptr);
- std::tm tm = *std::gmtime(&t);
- EXPECT_TRUE(EqualTime(tm, fmt::gmtime(t)));
+TEST(chrono_test, gmtime) {
+ auto t = std::time(nullptr);
+ auto tm = *std::gmtime(&t);
+ EXPECT_TRUE(equal(tm, fmt::gmtime(t)));
}
-TEST(TimeTest, TimePoint) {
- std::chrono::system_clock::time_point point = std::chrono::system_clock::now();
+template <typename TimePoint> auto strftime_full(TimePoint tp) -> std::string {
+ auto t = std::chrono::system_clock::to_time_t(tp);
+ auto tm = *std::localtime(&t);
+ return system_strftime("%Y-%m-%d %H:%M:%S", &tm);
+}
- std::time_t t = std::chrono::system_clock::to_time_t(point);
- std::tm tm = *std::localtime(&t);
- char strftime_output[256];
- std::strftime(strftime_output, sizeof(strftime_output), "It is %Y-%m-%d %H:%M:%S", &tm);
+TEST(chrono_test, time_point) {
+ auto t1 = std::chrono::system_clock::now();
+ EXPECT_EQ(strftime_full(t1), fmt::format("{:%Y-%m-%d %H:%M:%S}", t1));
+ EXPECT_EQ(strftime_full(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(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"};
+ spec_list.push_back("%Y-%m-%d %H:%M:%S");
+#ifndef _WIN32
+ // Disabled on Windows because these formats are not consistent among
+ // platforms.
+ spec_list.insert(spec_list.end(), {"%c", "%Ec", "%r"});
+#endif
- EXPECT_EQ(strftime_output, fmt::format("It is {:%Y-%m-%d %H:%M:%S}", point));
-}
+ 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);
-#define EXPECT_TIME(spec, time, duration) \
- { \
- std::locale loc("ja_JP.utf8"); \
- EXPECT_EQ(format_tm(time, spec, loc), \
- fmt::format(loc, "{:" spec "}", duration)); \
+ 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));
}
+}
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
-TEST(ChronoTest, FormatDefault) {
+TEST(chrono_test, format_default) {
EXPECT_EQ("42s", fmt::format("{}", std::chrono::seconds(42)));
EXPECT_EQ("42as",
fmt::format("{}", std::chrono::duration<int, std::atto>(42)));
@@ -157,49 +324,7 @@ TEST(ChronoTest, FormatDefault) {
fmt::format("{}", std::chrono::duration<int, std::ratio<15, 4>>(42)));
}
-TEST(ChronoTest, FormatWide) {
- EXPECT_EQ(L"42s", fmt::format(L"{}", std::chrono::seconds(42)));
- EXPECT_EQ(L"42as",
- fmt::format(L"{}", std::chrono::duration<int, std::atto>(42)));
- EXPECT_EQ(L"42fs",
- fmt::format(L"{}", std::chrono::duration<int, std::femto>(42)));
- EXPECT_EQ(L"42ps",
- fmt::format(L"{}", std::chrono::duration<int, std::pico>(42)));
- EXPECT_EQ(L"42ns", fmt::format(L"{}", std::chrono::nanoseconds(42)));
- EXPECT_EQ(L"42\u00B5s", fmt::format(L"{}", std::chrono::microseconds(42)));
- EXPECT_EQ(L"42ms", fmt::format(L"{}", std::chrono::milliseconds(42)));
- EXPECT_EQ(L"42cs",
- fmt::format(L"{}", std::chrono::duration<int, std::centi>(42)));
- EXPECT_EQ(L"42ds",
- fmt::format(L"{}", std::chrono::duration<int, std::deci>(42)));
- EXPECT_EQ(L"42s", fmt::format(L"{}", std::chrono::seconds(42)));
- EXPECT_EQ(L"42das",
- fmt::format(L"{}", std::chrono::duration<int, std::deca>(42)));
- EXPECT_EQ(L"42hs",
- fmt::format(L"{}", std::chrono::duration<int, std::hecto>(42)));
- EXPECT_EQ(L"42ks",
- fmt::format(L"{}", std::chrono::duration<int, std::kilo>(42)));
- EXPECT_EQ(L"42Ms",
- fmt::format(L"{}", std::chrono::duration<int, std::mega>(42)));
- EXPECT_EQ(L"42Gs",
- fmt::format(L"{}", std::chrono::duration<int, std::giga>(42)));
- EXPECT_EQ(L"42Ts",
- fmt::format(L"{}", std::chrono::duration<int, std::tera>(42)));
- EXPECT_EQ(L"42Ps",
- fmt::format(L"{}", std::chrono::duration<int, std::peta>(42)));
- EXPECT_EQ(L"42Es",
- fmt::format(L"{}", std::chrono::duration<int, std::exa>(42)));
- EXPECT_EQ(L"42m", fmt::format(L"{}", std::chrono::minutes(42)));
- EXPECT_EQ(L"42h", fmt::format(L"{}", std::chrono::hours(42)));
- EXPECT_EQ(
- L"42[15]s",
- fmt::format(L"{}", std::chrono::duration<int, std::ratio<15, 1>>(42)));
- EXPECT_EQ(
- L"42[15/4]s",
- fmt::format(L"{}", std::chrono::duration<int, std::ratio<15, 4>>(42)));
-}
-
-TEST(ChronoTest, Align) {
+TEST(chrono_test, align) {
auto s = std::chrono::seconds(42);
EXPECT_EQ("42s ", fmt::format("{:5}", s));
EXPECT_EQ("42s ", fmt::format("{:{}}", s, 5));
@@ -215,7 +340,7 @@ TEST(ChronoTest, Align) {
fmt::format("{:{}%H:%M:%S}", std::chrono::seconds(12345), 12));
}
-TEST(ChronoTest, FormatSpecs) {
+TEST(chrono_test, format_specs) {
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)));
@@ -244,43 +369,64 @@ TEST(ChronoTest, FormatSpecs) {
EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(12345)));
}
-TEST(ChronoTest, InvalidSpecs) {
+TEST(chrono_test, invalid_specs) {
auto sec = std::chrono::seconds(0);
- EXPECT_THROW_MSG(fmt::format("{:%a}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%A}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%c}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%x}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%Ex}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%X}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%EX}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%D}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%F}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%Ec}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%w}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%u}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%b}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%B}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%z}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%Z}", sec), fmt::format_error, "no date");
- EXPECT_THROW_MSG(fmt::format("{:%Eq}", sec), fmt::format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%a}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%A}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%c}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%x}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Ex}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%X}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%EX}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%D}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%F}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Ec}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%w}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%u}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%b}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%B}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%z}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Z}"), sec), fmt::format_error,
+ "no date");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Eq}"), sec), fmt::format_error,
"invalid format");
- EXPECT_THROW_MSG(fmt::format("{:%Oq}", sec), fmt::format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:%Oq}"), sec), fmt::format_error,
"invalid format");
}
-TEST(ChronoTest, Locale) {
- const char* loc_name = "ja_JP.utf8";
- bool has_locale = false;
- std::locale loc;
- try {
- loc = std::locale(loc_name);
- has_locale = true;
- } catch (const std::runtime_error&) {
- }
- if (!has_locale) {
- fmt::print("{} locale is missing.\n", loc_name);
- return;
- }
+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));
@@ -294,9 +440,9 @@ TEST(ChronoTest, Locale) {
EXPECT_TIME("%p", time, sec);
}
-typedef std::chrono::duration<double, std::milli> dms;
+using dms = std::chrono::duration<double, std::milli>;
-TEST(ChronoTest, FormatDefaultFP) {
+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;
@@ -306,24 +452,37 @@ TEST(ChronoTest, FormatDefaultFP) {
EXPECT_EQ("1.234ms", fmt::format("{}", dms(1.234)));
}
-TEST(ChronoTest, FormatPrecision) {
- EXPECT_THROW_MSG(fmt::format("{:.2}", std::chrono::seconds(42)),
- fmt::format_error,
- "precision not allowed for this argument type");
+TEST(chrono_test, format_precision) {
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{:.2}"), 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(ChronoTest, FormatFullSpecs) {
+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(ChronoTest, FormatSimpleQq) {
+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;
@@ -333,34 +492,42 @@ TEST(ChronoTest, FormatSimpleQq) {
EXPECT_EQ("1.234 ms", fmt::format("{:%Q %q}", dms(1.234)));
}
-TEST(ChronoTest, FormatPrecisionQq) {
- EXPECT_THROW_MSG(fmt::format("{:.2%Q %q}", std::chrono::seconds(42)),
- fmt::format_error,
- "precision not allowed for this argument type");
+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(ChronoTest, FormatFullSpecsQq) {
+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(ChronoTest, InvalidWidthId) {
- EXPECT_THROW(fmt::format("{:{o}", std::chrono::seconds(0)),
+TEST(chrono_test, invalid_width_id) {
+ EXPECT_THROW((void)fmt::format(runtime("{:{o}"), std::chrono::seconds(0)),
fmt::format_error);
}
-TEST(ChronoTest, InvalidColons) {
- EXPECT_THROW(fmt::format("{0}=:{0::", std::chrono::seconds(0)),
+TEST(chrono_test, invalid_colons) {
+ EXPECT_THROW((void)fmt::format(runtime("{0}=:{0::"), std::chrono::seconds(0)),
fmt::format_error);
}
-TEST(ChronoTest, NegativeDurations) {
+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)));
@@ -375,16 +542,13 @@ TEST(ChronoTest, NegativeDurations) {
fmt::format("{:%Q}", std::chrono::duration<int>(min)));
}
-TEST(ChronoTest, SpecialDurations) {
- EXPECT_EQ(
- "40.",
- fmt::format("{:%S}", std::chrono::duration<double>(1e20)).substr(0, 3));
+TEST(chrono_test, special_durations) {
+ auto value = fmt::format("{:%S}", std::chrono::duration<double>(1e20));
+ EXPECT_EQ(value, "40");
auto nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_EQ(
"nan nan nan nan nan:nan nan",
fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan)));
- fmt::format("{:%S}",
- std::chrono::duration<float, std::atto>(1.79400457e+31f));
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::exa>(1)),
"1Es");
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)),
@@ -395,4 +559,67 @@ TEST(ChronoTest, SpecialDurations) {
"03:33:20");
}
+TEST(chrono_test, unsigned_duration) {
+ EXPECT_EQ("42s", fmt::format("{}", std::chrono::duration<unsigned>(42)));
+}
+
+TEST(chrono_test, weekday) {
+ auto loc = get_locale("ru_RU.UTF-8");
+ std::locale::global(loc);
+ auto mon = fmt::weekday(1);
+
+ auto tm = std::tm();
+ tm.tm_wday = static_cast<int>(mon.c_encoding());
+
+ EXPECT_EQ(fmt::format("{}", mon), "Mon");
+ EXPECT_EQ(fmt::format("{:%a}", tm), "Mon");
+
+ if (loc != std::locale::classic()) {
+ EXPECT_THAT((std::vector<std::string>{"пн", "Пн", "пнд", "Пнд"}),
+ Contains(fmt::format(loc, "{:L}", mon)));
+ EXPECT_THAT((std::vector<std::string>{"пн", "Пн", "пнд", "Пнд"}),
+ 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 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);
+ }
+ 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);
+ }
+ // 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");
+}
+
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
diff --git a/contrib/libs/fmt/test/color-test.cc b/contrib/libs/fmt/test/color-test.cc
index 3073808541..af8f149426 100644
--- a/contrib/libs/fmt/test/color-test.cc
+++ b/contrib/libs/fmt/test/color-test.cc
@@ -7,66 +7,29 @@
#include "fmt/color.h"
-#include <iterator>
-#include <string>
-#include <utility>
+#include <iterator> // std::back_inserter
-#include "gtest-extra.h"
+#include "gtest-extra.h" // EXPECT_WRITE
-TEST(ColorsTest, ColorsPrint) {
- EXPECT_WRITE(stdout, fmt::print(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
- "\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
- EXPECT_WRITE(stdout, fmt::print(fg(fmt::color::blue), "blue"),
- "\x1b[38;2;000;000;255mblue\x1b[0m");
- EXPECT_WRITE(
- stdout,
- fmt::print(fg(fmt::color::blue) | bg(fmt::color::red), "two color"),
- "\x1b[38;2;000;000;255m\x1b[48;2;255;000;000mtwo color\x1b[0m");
- EXPECT_WRITE(stdout, fmt::print(fmt::emphasis::bold, "bold"),
- "\x1b[1mbold\x1b[0m");
- EXPECT_WRITE(stdout, fmt::print(fmt::emphasis::italic, "italic"),
- "\x1b[3mitalic\x1b[0m");
- EXPECT_WRITE(stdout, fmt::print(fmt::emphasis::underline, "underline"),
- "\x1b[4munderline\x1b[0m");
- EXPECT_WRITE(stdout,
- fmt::print(fmt::emphasis::strikethrough, "strikethrough"),
- "\x1b[9mstrikethrough\x1b[0m");
- EXPECT_WRITE(
- stdout,
- fmt::print(fg(fmt::color::blue) | fmt::emphasis::bold, "blue/bold"),
- "\x1b[1m\x1b[38;2;000;000;255mblue/bold\x1b[0m");
- EXPECT_WRITE(stderr, fmt::print(stderr, fmt::emphasis::bold, "bold error"),
- "\x1b[1mbold error\x1b[0m");
- EXPECT_WRITE(stderr, fmt::print(stderr, fg(fmt::color::blue), "blue log"),
- "\x1b[38;2;000;000;255mblue log\x1b[0m");
- EXPECT_WRITE(stdout, fmt::print(fmt::text_style(), "hi"), "hi");
- EXPECT_WRITE(stdout, fmt::print(fg(fmt::terminal_color::red), "tred"),
- "\x1b[31mtred\x1b[0m");
- EXPECT_WRITE(stdout, fmt::print(bg(fmt::terminal_color::cyan), "tcyan"),
- "\x1b[46mtcyan\x1b[0m");
- EXPECT_WRITE(stdout,
- fmt::print(fg(fmt::terminal_color::bright_green), "tbgreen"),
- "\x1b[92mtbgreen\x1b[0m");
- EXPECT_WRITE(stdout,
- fmt::print(bg(fmt::terminal_color::bright_magenta), "tbmagenta"),
- "\x1b[105mtbmagenta\x1b[0m");
-}
-
-TEST(ColorsTest, Format) {
+TEST(color_test, format) {
EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
"\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
- EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), L"rgb(255,20,30) wide"),
- L"\x1b[38;2;255;020;030mrgb(255,20,30) wide\x1b[0m");
EXPECT_EQ(fmt::format(fg(fmt::color::blue), "blue"),
"\x1b[38;2;000;000;255mblue\x1b[0m");
EXPECT_EQ(
fmt::format(fg(fmt::color::blue) | bg(fmt::color::red), "two color"),
"\x1b[38;2;000;000;255m\x1b[48;2;255;000;000mtwo color\x1b[0m");
EXPECT_EQ(fmt::format(fmt::emphasis::bold, "bold"), "\x1b[1mbold\x1b[0m");
+ EXPECT_EQ(fmt::format(fmt::emphasis::faint, "faint"), "\x1b[2mfaint\x1b[0m");
EXPECT_EQ(fmt::format(fmt::emphasis::italic, "italic"),
"\x1b[3mitalic\x1b[0m");
EXPECT_EQ(fmt::format(fmt::emphasis::underline, "underline"),
"\x1b[4munderline\x1b[0m");
+ EXPECT_EQ(fmt::format(fmt::emphasis::blink, "blink"), "\x1b[5mblink\x1b[0m");
+ EXPECT_EQ(fmt::format(fmt::emphasis::reverse, "reverse"),
+ "\x1b[7mreverse\x1b[0m");
+ EXPECT_EQ(fmt::format(fmt::emphasis::conceal, "conceal"),
+ "\x1b[8mconceal\x1b[0m");
EXPECT_EQ(fmt::format(fmt::emphasis::strikethrough, "strikethrough"),
"\x1b[9mstrikethrough\x1b[0m");
EXPECT_EQ(
@@ -89,11 +52,15 @@ TEST(ColorsTest, Format) {
"\x1b[31mfoo\x1b[0m");
}
-TEST(ColorsTest, FormatToOutAcceptsTextStyle) {
- fmt::text_style ts = fg(fmt::rgb(255, 20, 30));
- std::string out;
- fmt::format_to(std::back_inserter(out), ts, "rgb(255,20,30){}{}{}", 1, 2, 3);
-
+TEST(color_test, format_to) {
+ auto out = std::string();
+ fmt::format_to(std::back_inserter(out), fg(fmt::rgb(255, 20, 30)),
+ "rgb(255,20,30){}{}{}", 1, 2, 3);
EXPECT_EQ(fmt::to_string(out),
"\x1b[38;2;255;020;030mrgb(255,20,30)123\x1b[0m");
}
+
+TEST(color_test, print) {
+ EXPECT_WRITE(stdout, fmt::print(fg(fmt::rgb(255, 20, 30)), "rgb(255,20,30)"),
+ "\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m");
+}
diff --git a/contrib/libs/fmt/test/compile-fp-test.cc b/contrib/libs/fmt/test/compile-fp-test.cc
new file mode 100644
index 0000000000..afedc26d06
--- /dev/null
+++ b/contrib/libs/fmt/test/compile-fp-test.cc
@@ -0,0 +1,62 @@
+// Formatting library for C++ - formatting library tests
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include "fmt/compile.h"
+#include "gmock/gmock.h"
+
+#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806 && \
+ defined(__cpp_constexpr) && __cpp_constexpr >= 201907 && \
+ defined(__cpp_constexpr_dynamic_alloc) && \
+ __cpp_constexpr_dynamic_alloc >= 201907 && __cplusplus >= 202002L
+template <size_t max_string_length, typename Char = char> struct test_string {
+ template <typename T> constexpr bool operator==(const T& rhs) const noexcept {
+ return fmt::basic_string_view<Char>(rhs).compare(buffer) == 0;
+ }
+ Char buffer[max_string_length]{};
+};
+
+template <size_t max_string_length, typename Char = char, typename... Args>
+consteval auto test_format(auto format, const Args&... args) {
+ test_string<max_string_length, Char> string{};
+ fmt::format_to(string.buffer, format, args...);
+ return string;
+}
+
+TEST(compile_time_formatting_test, floating_point) {
+ EXPECT_EQ("0", test_format<2>(FMT_COMPILE("{}"), 0.0f));
+ EXPECT_EQ("392.500000", test_format<11>(FMT_COMPILE("{0:f}"), 392.5f));
+
+ EXPECT_EQ("0", test_format<2>(FMT_COMPILE("{:}"), 0.0));
+ EXPECT_EQ("0.000000", test_format<9>(FMT_COMPILE("{:f}"), 0.0));
+ EXPECT_EQ("0", test_format<2>(FMT_COMPILE("{:g}"), 0.0));
+ EXPECT_EQ("392.65", test_format<7>(FMT_COMPILE("{:}"), 392.65));
+ EXPECT_EQ("392.65", test_format<7>(FMT_COMPILE("{:g}"), 392.65));
+ EXPECT_EQ("392.65", test_format<7>(FMT_COMPILE("{:G}"), 392.65));
+ EXPECT_EQ("4.9014e+06", test_format<11>(FMT_COMPILE("{:g}"), 4.9014e6));
+ EXPECT_EQ("-392.650000", test_format<12>(FMT_COMPILE("{:f}"), -392.65));
+ EXPECT_EQ("-392.650000", test_format<12>(FMT_COMPILE("{:F}"), -392.65));
+
+ EXPECT_EQ("3.926500e+02", test_format<13>(FMT_COMPILE("{0:e}"), 392.65));
+ EXPECT_EQ("3.926500E+02", test_format<13>(FMT_COMPILE("{0:E}"), 392.65));
+ EXPECT_EQ("+0000392.6", test_format<11>(FMT_COMPILE("{0:+010.4g}"), 392.65));
+ EXPECT_EQ("9223372036854775808.000000",
+ test_format<27>(FMT_COMPILE("{:f}"), 9223372036854775807.0));
+
+ constexpr double nan = std::numeric_limits<double>::quiet_NaN();
+ EXPECT_EQ("nan", test_format<4>(FMT_COMPILE("{}"), nan));
+ EXPECT_EQ("+nan", test_format<5>(FMT_COMPILE("{:+}"), nan));
+ if (std::signbit(-nan))
+ EXPECT_EQ("-nan", test_format<5>(FMT_COMPILE("{}"), -nan));
+ else
+ fmt::print("Warning: compiler doesn't handle negative NaN correctly");
+
+ constexpr double inf = std::numeric_limits<double>::infinity();
+ EXPECT_EQ("inf", test_format<4>(FMT_COMPILE("{}"), inf));
+ EXPECT_EQ("+inf", test_format<5>(FMT_COMPILE("{:+}"), inf));
+ EXPECT_EQ("-inf", test_format<5>(FMT_COMPILE("{}"), -inf));
+}
+#endif
diff --git a/contrib/libs/fmt/test/compile-test.cc b/contrib/libs/fmt/test/compile-test.cc
index 9bb9bb7d9e..1765961b89 100644
--- a/contrib/libs/fmt/test/compile-test.cc
+++ b/contrib/libs/fmt/test/compile-test.cc
@@ -5,121 +5,100 @@
//
// For the license information refer to format.h.
-#include <string>
-#include <type_traits>
+#include "fmt/compile.h"
-// Check that fmt/compile.h compiles with windows.h included before it.
-#ifdef _WIN32
-# include <windows.h>
-#endif
+#include <type_traits>
-#include "fmt/compile.h"
-#include <gmock/gmock.h>
+#include "fmt/chrono.h"
+#include "gmock/gmock.h"
#include "gtest-extra.h"
-#include "util.h"
-
-// compiletime_prepared_parts_type_provider is useful only with relaxed
-// constexpr.
-#if FMT_USE_CONSTEXPR
-template <unsigned EXPECTED_PARTS_COUNT, typename Format>
-void check_prepared_parts_type(Format format) {
- typedef fmt::detail::compiled_format_base<decltype(format)> provider;
- typedef fmt::detail::format_part<char>
- expected_parts_type[EXPECTED_PARTS_COUNT];
- static_assert(std::is_same<typename provider::parts_container,
- expected_parts_type>::value,
- "CompileTimePreparedPartsTypeProvider test failed");
-}
-
-TEST(CompileTest, CompileTimePreparedPartsTypeProvider) {
- check_prepared_parts_type<1u>(FMT_STRING("text"));
- check_prepared_parts_type<1u>(FMT_STRING("{}"));
- check_prepared_parts_type<2u>(FMT_STRING("text{}"));
- check_prepared_parts_type<2u>(FMT_STRING("{}text"));
- check_prepared_parts_type<3u>(FMT_STRING("text{}text"));
- check_prepared_parts_type<3u>(FMT_STRING("{:{}.{}} {:{}}"));
-
- check_prepared_parts_type<3u>(FMT_STRING("{{{}}}")); // '{', 'argument', '}'
- check_prepared_parts_type<2u>(FMT_STRING("text{{")); // 'text', '{'
- check_prepared_parts_type<3u>(FMT_STRING("text{{ ")); // 'text', '{', ' '
- check_prepared_parts_type<2u>(FMT_STRING("}}text")); // '}', text
- check_prepared_parts_type<2u>(FMT_STRING("text}}text")); // 'text}', 'text'
- check_prepared_parts_type<4u>(
- FMT_STRING("text{{}}text")); // 'text', '{', '}', 'text'
-}
-#endif
-TEST(CompileTest, PassStringLiteralFormat) {
- const auto prepared = fmt::detail::compile<int>("test {}");
- EXPECT_EQ("test 42", fmt::format(prepared, 42));
- const auto wprepared = fmt::detail::compile<int>(L"test {}");
- EXPECT_EQ(L"test 42", fmt::format(wprepared, 42));
+TEST(iterator_test, counting_iterator) {
+ auto it = fmt::detail::counting_iterator();
+ auto prev = it++;
+ EXPECT_EQ(prev.count(), 0);
+ EXPECT_EQ(it.count(), 1);
+ EXPECT_EQ((it + 41).count(), 42);
}
-TEST(CompileTest, FormatToArrayOfChars) {
- char buffer[32] = {0};
- const auto prepared = fmt::detail::compile<int>("4{}");
- fmt::format_to(fmt::detail::make_checked(buffer, 32), prepared, 2);
- EXPECT_EQ(std::string("42"), buffer);
- wchar_t wbuffer[32] = {0};
- const auto wprepared = fmt::detail::compile<int>(L"4{}");
- fmt::format_to(fmt::detail::make_checked(wbuffer, 32), wprepared, 2);
- EXPECT_EQ(std::wstring(L"42"), wbuffer);
+TEST(iterator_test, truncating_iterator) {
+ char* p = nullptr;
+ auto it = fmt::detail::truncating_iterator<char*>(p, 3);
+ auto prev = it++;
+ EXPECT_EQ(prev.base(), p);
+ EXPECT_EQ(it.base(), p + 1);
}
-TEST(CompileTest, FormatToIterator) {
- std::string s(2, ' ');
- const auto prepared = fmt::detail::compile<int>("4{}");
- fmt::format_to(s.begin(), prepared, 2);
- EXPECT_EQ("42", s);
- std::wstring ws(2, L' ');
- const auto wprepared = fmt::detail::compile<int>(L"4{}");
- fmt::format_to(ws.begin(), wprepared, 2);
- EXPECT_EQ(L"42", ws);
+TEST(iterator_test, truncating_iterator_default_construct) {
+ auto it = fmt::detail::truncating_iterator<char*>();
+ EXPECT_EQ(nullptr, it.base());
+ EXPECT_EQ(std::size_t{0}, it.count());
}
-TEST(CompileTest, FormatToN) {
- char buf[5];
- auto f = fmt::detail::compile<int>("{:10}");
- auto result = fmt::format_to_n(buf, 5, f, 42);
- EXPECT_EQ(result.size, 10);
- EXPECT_EQ(result.out, buf + 5);
- EXPECT_EQ(fmt::string_view(buf, 5), " ");
+#ifdef __cpp_lib_ranges
+TEST(iterator_test, truncating_iterator_is_output_iterator) {
+ static_assert(
+ std::output_iterator<fmt::detail::truncating_iterator<char*>, char>);
}
+#endif
-TEST(CompileTest, FormattedSize) {
- auto f = fmt::detail::compile<int>("{:10}");
- EXPECT_EQ(fmt::formatted_size(f, 42), 10);
+TEST(iterator_test, truncating_back_inserter) {
+ auto buffer = std::string();
+ auto bi = std::back_inserter(buffer);
+ auto it = fmt::detail::truncating_iterator<decltype(bi)>(bi, 2);
+ *it++ = '4';
+ *it++ = '2';
+ *it++ = '1';
+ EXPECT_EQ(buffer.size(), 2);
+ EXPECT_EQ(buffer, "42");
}
-TEST(CompileTest, MultipleTypes) {
- auto f = fmt::detail::compile<int, int>("{} {}");
- EXPECT_EQ(fmt::format(f, 42, 42), "42 42");
+TEST(compile_test, compile_fallback) {
+ // FMT_COMPILE should fallback on runtime formatting when `if constexpr` is
+ // not available.
+ EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42));
}
-struct test_formattable {};
+struct type_with_get {
+ template <int> friend void get(type_with_get);
+};
FMT_BEGIN_NAMESPACE
-template <> struct formatter<test_formattable> : formatter<const char*> {
+template <> struct formatter<type_with_get> : formatter<int> {
template <typename FormatContext>
- auto format(test_formattable, FormatContext& ctx) -> decltype(ctx.out()) {
- return formatter<const char*>::format("foo", ctx);
+ auto format(type_with_get, FormatContext& ctx) -> decltype(ctx.out()) {
+ return formatter<int>::format(42, ctx);
}
};
FMT_END_NAMESPACE
-TEST(CompileTest, FormatUserDefinedType) {
- auto f = fmt::detail::compile<test_formattable>("{}");
- EXPECT_EQ(fmt::format(f, test_formattable()), "foo");
+TEST(compile_test, compile_type_with_get) {
+ EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), type_with_get()));
}
-TEST(CompileTest, EmptyFormatString) {
- auto f = fmt::detail::compile<>("");
- EXPECT_EQ(fmt::format(f), "");
-}
+#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
+struct test_formattable {};
+
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<test_formattable> : formatter<const char*> {
+ char word_spec = 'f';
+ constexpr auto parse(format_parse_context& ctx) {
+ auto it = ctx.begin(), end = ctx.end();
+ if (it == end || *it == '}') return it;
+ if (it != end && (*it == 'f' || *it == 'b')) word_spec = *it++;
+ if (it != end && *it != '}') throw format_error("invalid format");
+ return it;
+ }
+ template <typename FormatContext>
+ constexpr auto format(test_formattable, FormatContext& ctx) const
+ -> decltype(ctx.out()) {
+ return formatter<const char*>::format(word_spec == 'f' ? "foo" : "bar",
+ ctx);
+ }
+};
+FMT_END_NAMESPACE
-#ifdef __cpp_if_constexpr
-TEST(CompileTest, FormatDefault) {
+TEST(compile_test, format_default) {
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42));
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42u));
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42ll));
@@ -130,22 +109,99 @@ TEST(CompileTest, FormatDefault) {
EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), "foo"));
EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), std::string("foo")));
EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), test_formattable()));
+ auto t = std::chrono::system_clock::now();
+ EXPECT_EQ(fmt::format("{}", t), fmt::format(FMT_COMPILE("{}"), t));
+# ifdef __cpp_lib_byte
+ EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), std::byte{42}));
+# endif
}
-TEST(CompileTest, FormatWideString) {
+TEST(compile_test, format_wide_string) {
EXPECT_EQ(L"42", fmt::format(FMT_COMPILE(L"{}"), 42));
}
-TEST(CompileTest, FormatSpecs) {
+TEST(compile_test, format_specs) {
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{:x}"), 0x42));
+ EXPECT_EQ("1.2 ms ",
+ fmt::format(FMT_COMPILE("{:7.1%Q %q}"),
+ std::chrono::duration<double, std::milli>(1.234)));
+}
+
+TEST(compile_test, dynamic_format_specs) {
+ EXPECT_EQ("foo ", fmt::format(FMT_COMPILE("{:{}}"), "foo", 5));
+ EXPECT_EQ(" 3.14", fmt::format(FMT_COMPILE("{:{}.{}f}"), 3.141592, 6, 2));
+ EXPECT_EQ(
+ "=1.234ms=",
+ fmt::format(FMT_COMPILE("{:=^{}.{}}"),
+ std::chrono::duration<double, std::milli>(1.234), 9, 3));
}
-TEST(CompileTest, DynamicWidth) {
- EXPECT_EQ(" 42foo ",
- fmt::format(FMT_COMPILE("{:{}}{:{}}"), 42, 4, "foo", 5));
+TEST(compile_test, manual_ordering) {
+ EXPECT_EQ("42", fmt::format(FMT_COMPILE("{0}"), 42));
+ EXPECT_EQ(" -42", fmt::format(FMT_COMPILE("{0:4}"), -42));
+ EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{0} {1}"), 41, 43));
+ EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{1} {0}"), 43, 41));
+ EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{0} {2}"), 41, 42, 43));
+ EXPECT_EQ(" 41 43", fmt::format(FMT_COMPILE("{1:{2}} {0:4}"), 43, 41, 4));
+ EXPECT_EQ("42 1.2 ms ",
+ fmt::format(FMT_COMPILE("{0} {1:7.1%Q %q}"), 42,
+ std::chrono::duration<double, std::milli>(1.234)));
+ EXPECT_EQ(
+ "true 42 42 foo 0x1234 foo",
+ fmt::format(FMT_COMPILE("{0} {1} {2} {3} {4} {5}"), true, 42, 42.0f,
+ "foo", reinterpret_cast<void*>(0x1234), test_formattable()));
+ EXPECT_EQ(L"42", fmt::format(FMT_COMPILE(L"{0}"), 42));
+}
+
+TEST(compile_test, named) {
+ auto runtime_named_field_compiled =
+ fmt::detail::compile<decltype(fmt::arg("arg", 42))>(FMT_COMPILE("{arg}"));
+ static_assert(std::is_same_v<decltype(runtime_named_field_compiled),
+ fmt::detail::runtime_named_field<char>>);
+
+ EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), fmt::arg("arg", 42)));
+ EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{} {}"), fmt::arg("arg", 41),
+ fmt::arg("arg", 43)));
+
+ EXPECT_EQ("foobar",
+ fmt::format(FMT_COMPILE("{a0}{a1}"), fmt::arg("a0", "foo"),
+ fmt::arg("a1", "bar")));
+ EXPECT_EQ("foobar", fmt::format(FMT_COMPILE("{}{a1}"), fmt::arg("a0", "foo"),
+ fmt::arg("a1", "bar")));
+ EXPECT_EQ("foofoo", fmt::format(FMT_COMPILE("{a0}{}"), fmt::arg("a0", "foo"),
+ fmt::arg("a1", "bar")));
+ EXPECT_EQ("foobar", fmt::format(FMT_COMPILE("{0}{a1}"), fmt::arg("a0", "foo"),
+ fmt::arg("a1", "bar")));
+ EXPECT_EQ("foobar", fmt::format(FMT_COMPILE("{a0}{1}"), fmt::arg("a0", "foo"),
+ fmt::arg("a1", "bar")));
+
+ EXPECT_EQ("foobar",
+ fmt::format(FMT_COMPILE("{}{a1}"), "foo", fmt::arg("a1", "bar")));
+ EXPECT_EQ("foobar",
+ fmt::format(FMT_COMPILE("{a0}{a1}"), fmt::arg("a1", "bar"),
+ fmt::arg("a2", "baz"), fmt::arg("a0", "foo")));
+ EXPECT_EQ(" bar foo ",
+ fmt::format(FMT_COMPILE(" {foo} {bar} "), fmt::arg("foo", "bar"),
+ fmt::arg("bar", "foo")));
+
+ EXPECT_THROW(fmt::format(FMT_COMPILE("{invalid}"), fmt::arg("valid", 42)),
+ fmt::format_error);
+
+# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+ using namespace fmt::literals;
+ auto statically_named_field_compiled =
+ fmt::detail::compile<decltype("arg"_a = 42)>(FMT_COMPILE("{arg}"));
+ static_assert(std::is_same_v<decltype(statically_named_field_compiled),
+ fmt::detail::field<char, int, 0>>);
+
+ EXPECT_EQ("41 43",
+ fmt::format(FMT_COMPILE("{a0} {a1}"), "a0"_a = 41, "a1"_a = 43));
+ EXPECT_EQ("41 43",
+ fmt::format(FMT_COMPILE("{a1} {a0}"), "a0"_a = 43, "a1"_a = 41));
+# endif
}
-TEST(CompileTest, FormatTo) {
+TEST(compile_test, format_to) {
char buf[8];
auto end = fmt::format_to(buf, FMT_COMPILE("{}"), 42);
*end = '\0';
@@ -155,7 +211,7 @@ TEST(CompileTest, FormatTo) {
EXPECT_STREQ("2a", buf);
}
-TEST(CompileTest, FormatToNWithCompileMacro) {
+TEST(compile_test, format_to_n) {
constexpr auto buffer_size = 8;
char buffer[buffer_size];
auto res = fmt::format_to_n(buffer, buffer_size, FMT_COMPILE("{}"), 42);
@@ -166,8 +222,155 @@ TEST(CompileTest, FormatToNWithCompileMacro) {
EXPECT_STREQ("2a", buffer);
}
-TEST(CompileTest, TextAndArg) {
+TEST(compile_test, formatted_size) {
+ EXPECT_EQ(2, fmt::formatted_size(FMT_COMPILE("{0}"), 42));
+ EXPECT_EQ(5, fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0));
+}
+
+TEST(compile_test, text_and_arg) {
EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42));
EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42));
}
+
+TEST(compile_test, unknown_format_fallback) {
+ EXPECT_EQ(" 42 ",
+ fmt::format(FMT_COMPILE("{name:^4}"), fmt::arg("name", 42)));
+
+ std::vector<char> v;
+ fmt::format_to(std::back_inserter(v), FMT_COMPILE("{name:^4}"),
+ fmt::arg("name", 42));
+ EXPECT_EQ(" 42 ", fmt::string_view(v.data(), v.size()));
+
+ char buffer[4];
+ auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"),
+ fmt::arg("name", 42));
+ EXPECT_EQ(5u, result.size);
+ EXPECT_EQ(buffer + 4, result.out);
+ EXPECT_EQ(" 42 ", fmt::string_view(buffer, 4));
+}
+
+TEST(compile_test, empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); }
+
+struct to_stringable {
+ friend fmt::string_view to_string_view(to_stringable) { return {}; }
+};
+
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<to_stringable> {
+ auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+
+ template <typename FormatContext>
+ auto format(const to_stringable&, FormatContext& ctx) -> decltype(ctx.out()) {
+ return ctx.out();
+ }
+};
+FMT_END_NAMESPACE
+
+TEST(compile_test, to_string_and_formatter) {
+ fmt::format(FMT_COMPILE("{}"), to_stringable());
+}
+
+TEST(compile_test, print) {
+ EXPECT_WRITE(stdout, fmt::print(FMT_COMPILE("Don't {}!"), "panic"),
+ "Don't panic!");
+ EXPECT_WRITE(stderr, fmt::print(stderr, FMT_COMPILE("Don't {}!"), "panic"),
+ "Don't panic!");
+}
+#endif
+
+#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+TEST(compile_test, compile_format_string_literal) {
+ using namespace fmt::literals;
+ EXPECT_EQ("", fmt::format(""_cf));
+ EXPECT_EQ("42", fmt::format("{}"_cf, 42));
+ EXPECT_EQ(L"42", fmt::format(L"{}"_cf, 42));
+}
+#endif
+
+#if __cplusplus >= 202002L || \
+ (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002)
+template <size_t max_string_length, typename Char = char> struct test_string {
+ template <typename T> constexpr bool operator==(const T& rhs) const noexcept {
+ return fmt::basic_string_view<Char>(rhs).compare(buffer) == 0;
+ }
+ Char buffer[max_string_length]{};
+};
+
+template <size_t max_string_length, typename Char = char, typename... Args>
+consteval auto test_format(auto format, const Args&... args) {
+ test_string<max_string_length, Char> string{};
+ fmt::format_to(string.buffer, format, args...);
+ return string;
+}
+
+TEST(compile_time_formatting_test, bool) {
+ EXPECT_EQ("true", test_format<5>(FMT_COMPILE("{}"), true));
+ EXPECT_EQ("false", test_format<6>(FMT_COMPILE("{}"), false));
+ EXPECT_EQ("true ", test_format<6>(FMT_COMPILE("{:5}"), true));
+ EXPECT_EQ("1", test_format<2>(FMT_COMPILE("{:d}"), true));
+}
+
+TEST(compile_time_formatting_test, integer) {
+ EXPECT_EQ("42", test_format<3>(FMT_COMPILE("{}"), 42));
+ EXPECT_EQ("420", test_format<4>(FMT_COMPILE("{}"), 420));
+ EXPECT_EQ("42 42", test_format<6>(FMT_COMPILE("{} {}"), 42, 42));
+ EXPECT_EQ("42 42",
+ test_format<6>(FMT_COMPILE("{} {}"), uint32_t{42}, uint64_t{42}));
+
+ EXPECT_EQ("+42", test_format<4>(FMT_COMPILE("{:+}"), 42));
+ EXPECT_EQ("42", test_format<3>(FMT_COMPILE("{:-}"), 42));
+ EXPECT_EQ(" 42", test_format<4>(FMT_COMPILE("{: }"), 42));
+
+ EXPECT_EQ("-0042", test_format<6>(FMT_COMPILE("{:05}"), -42));
+
+ EXPECT_EQ("101010", test_format<7>(FMT_COMPILE("{:b}"), 42));
+ EXPECT_EQ("0b101010", test_format<9>(FMT_COMPILE("{:#b}"), 42));
+ EXPECT_EQ("0B101010", test_format<9>(FMT_COMPILE("{:#B}"), 42));
+ EXPECT_EQ("042", test_format<4>(FMT_COMPILE("{:#o}"), 042));
+ EXPECT_EQ("0x4a", test_format<5>(FMT_COMPILE("{:#x}"), 0x4a));
+ EXPECT_EQ("0X4A", test_format<5>(FMT_COMPILE("{:#X}"), 0x4a));
+
+ EXPECT_EQ(" 42", test_format<6>(FMT_COMPILE("{:5}"), 42));
+ EXPECT_EQ(" 42", test_format<6>(FMT_COMPILE("{:5}"), 42ll));
+ EXPECT_EQ(" 42", test_format<6>(FMT_COMPILE("{:5}"), 42ull));
+
+ EXPECT_EQ("42 ", test_format<5>(FMT_COMPILE("{:<4}"), 42));
+ EXPECT_EQ(" 42", test_format<5>(FMT_COMPILE("{:>4}"), 42));
+ EXPECT_EQ(" 42 ", test_format<5>(FMT_COMPILE("{:^4}"), 42));
+ EXPECT_EQ("**-42", test_format<6>(FMT_COMPILE("{:*>5}"), -42));
+}
+
+TEST(compile_time_formatting_test, char) {
+ EXPECT_EQ("c", test_format<2>(FMT_COMPILE("{}"), 'c'));
+
+ EXPECT_EQ("c ", test_format<4>(FMT_COMPILE("{:3}"), 'c'));
+ EXPECT_EQ("99", test_format<3>(FMT_COMPILE("{:d}"), 'c'));
+}
+
+TEST(compile_time_formatting_test, string) {
+ EXPECT_EQ("42", test_format<3>(FMT_COMPILE("{}"), "42"));
+ EXPECT_EQ("The answer is 42",
+ test_format<17>(FMT_COMPILE("{} is {}"), "The answer", "42"));
+
+ EXPECT_EQ("abc**", test_format<6>(FMT_COMPILE("{:*<5}"), "abc"));
+ EXPECT_EQ("**🤡**", test_format<9>(FMT_COMPILE("{:*^6}"), "🤡"));
+}
+
+TEST(compile_time_formatting_test, combination) {
+ EXPECT_EQ("420, true, answer",
+ test_format<18>(FMT_COMPILE("{}, {}, {}"), 420, true, "answer"));
+
+ EXPECT_EQ(" -42", test_format<5>(FMT_COMPILE("{:{}}"), -42, 4));
+}
+
+TEST(compile_time_formatting_test, custom_type) {
+ EXPECT_EQ("foo", test_format<4>(FMT_COMPILE("{}"), test_formattable()));
+ EXPECT_EQ("bar", test_format<4>(FMT_COMPILE("{:b}"), test_formattable()));
+}
+
+TEST(compile_time_formatting_test, multibyte_fill) {
+ EXPECT_EQ("жж42", test_format<8>(FMT_COMPILE("{:ж>4}"), 42));
+}
#endif
diff --git a/contrib/libs/fmt/test/core-test.cc b/contrib/libs/fmt/test/core-test.cc
index a5fd01fa4d..b2f2097ea1 100644
--- a/contrib/libs/fmt/test/core-test.cc
+++ b/contrib/libs/fmt/test/core-test.cc
@@ -5,58 +5,128 @@
//
// For the license information refer to format.h.
-#include <algorithm>
-#include <climits>
-#include <cstring>
-#include <functional>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <string>
-#include <type_traits>
-
-#include <gmock/gmock.h>
+// clang-format off
#include "test-assert.h"
-
-// Check if fmt/core.h compiles with windows.h included before it.
-#ifdef _WIN32
-# include <windows.h>
-#endif
+// clang-format on
#include "fmt/core.h"
-#undef min
-#undef max
+#include <algorithm> // std::copy_n
+#include <climits> // INT_MAX
+#include <cstring> // std::strlen
+#include <functional> // std::equal_to
+#include <iterator> // std::back_insert_iterator
+#include <limits> // std::numeric_limits
+#include <string> // std::string
+#include <type_traits> // std::is_same
+
+#include "gmock/gmock.h"
-using fmt::basic_format_arg;
using fmt::string_view;
using fmt::detail::buffer;
-using fmt::detail::make_arg;
-using fmt::detail::value;
using testing::_;
using testing::Invoke;
using testing::Return;
-using testing::StrictMock;
-struct test_struct {};
+#ifdef FMT_FORMAT_H_
+# error core-test includes format.h
+#endif
-FMT_BEGIN_NAMESPACE
-template <typename Char> struct formatter<test_struct, Char> {
- template <typename ParseContext>
- auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
- return ctx.begin();
- }
+TEST(string_view_test, value_type) {
+ static_assert(std::is_same<string_view::value_type, char>::value, "");
+}
- auto format(test_struct, format_context& ctx) -> decltype(ctx.out()) {
- const Char* test = "test";
- return std::copy_n(test, std::strlen(test), ctx.out());
+TEST(string_view_test, ctor) {
+ EXPECT_STREQ("abc", fmt::string_view("abc").data());
+ EXPECT_EQ(3u, fmt::string_view("abc").size());
+
+ EXPECT_STREQ("defg", fmt::string_view(std::string("defg")).data());
+ EXPECT_EQ(4u, fmt::string_view(std::string("defg")).size());
+}
+
+TEST(string_view_test, length) {
+ // Test that string_view::size() returns string length, not buffer size.
+ char str[100] = "some string";
+ EXPECT_EQ(std::strlen(str), string_view(str).size());
+ EXPECT_LT(std::strlen(str), sizeof(str));
+}
+
+// Check string_view's comparison operator.
+template <template <typename> class Op> void check_op() {
+ const char* inputs[] = {"foo", "fop", "fo"};
+ size_t num_inputs = sizeof(inputs) / sizeof(*inputs);
+ for (size_t i = 0; i < num_inputs; ++i) {
+ for (size_t j = 0; j < num_inputs; ++j) {
+ string_view lhs(inputs[i]), rhs(inputs[j]);
+ EXPECT_EQ(Op<int>()(lhs.compare(rhs), 0), Op<string_view>()(lhs, rhs));
+ }
}
+}
+
+TEST(string_view_test, compare) {
+ EXPECT_EQ(string_view("foo").compare(string_view("foo")), 0);
+ EXPECT_GT(string_view("fop").compare(string_view("foo")), 0);
+ EXPECT_LT(string_view("foo").compare(string_view("fop")), 0);
+ EXPECT_GT(string_view("foo").compare(string_view("fo")), 0);
+ EXPECT_LT(string_view("fo").compare(string_view("foo")), 0);
+ check_op<std::equal_to>();
+ check_op<std::not_equal_to>();
+ check_op<std::less>();
+ check_op<std::less_equal>();
+ check_op<std::greater>();
+ check_op<std::greater_equal>();
+}
+
+namespace test_ns {
+template <typename Char> class test_string {
+ private:
+ std::basic_string<Char> s_;
+
+ public:
+ test_string(const Char* s) : s_(s) {}
+ const Char* data() const { return s_.data(); }
+ size_t length() const { return s_.size(); }
+ operator const Char*() const { return s_.c_str(); }
};
-FMT_END_NAMESPACE
+
+template <typename Char>
+fmt::basic_string_view<Char> to_string_view(const test_string<Char>& s) {
+ return {s.data(), s.length()};
+}
+} // namespace test_ns
+
+TEST(core_test, is_output_iterator) {
+ EXPECT_TRUE((fmt::detail::is_output_iterator<char*, char>::value));
+ EXPECT_FALSE((fmt::detail::is_output_iterator<const char*, char>::value));
+ EXPECT_FALSE((fmt::detail::is_output_iterator<std::string, char>::value));
+ EXPECT_TRUE(
+ (fmt::detail::is_output_iterator<std::back_insert_iterator<std::string>,
+ char>::value));
+ EXPECT_TRUE(
+ (fmt::detail::is_output_iterator<std::string::iterator, char>::value));
+ EXPECT_FALSE((fmt::detail::is_output_iterator<std::string::const_iterator,
+ char>::value));
+}
+
+TEST(core_test, buffer_appender) {
+ // back_insert_iterator is not default-constructible before C++20, so
+ // buffer_appender can only be default-constructible when back_insert_iterator
+ // is.
+ static_assert(
+ std::is_default_constructible<
+ std::back_insert_iterator<fmt::detail::buffer<char>>>::value ==
+ std::is_default_constructible<
+ fmt::detail::buffer_appender<char>>::value,
+ "");
+
+#ifdef __cpp_lib_ranges
+ static_assert(std::output_iterator<fmt::detail::buffer_appender<char>, char>);
+#endif
+}
#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 470
-TEST(BufferTest, Noncopyable) {
+TEST(buffer_test, noncopyable) {
EXPECT_FALSE(std::is_copy_constructible<buffer<char>>::value);
# if !FMT_MSC_VER
// std::is_copy_assignable is broken in MSVC2013.
@@ -64,7 +134,7 @@ TEST(BufferTest, Noncopyable) {
# endif
}
-TEST(BufferTest, Nonmoveable) {
+TEST(buffer_test, nonmoveable) {
EXPECT_FALSE(std::is_move_constructible<buffer<char>>::value);
# if !FMT_MSC_VER
// std::is_move_assignable is broken in MSVC2013.
@@ -73,7 +143,7 @@ TEST(BufferTest, Nonmoveable) {
}
#endif
-TEST(BufferTest, Indestructible) {
+TEST(buffer_test, indestructible) {
static_assert(!std::is_destructible<fmt::detail::buffer<int>>(),
"buffer's destructor is protected");
}
@@ -81,17 +151,19 @@ TEST(BufferTest, Indestructible) {
template <typename T> struct mock_buffer final : buffer<T> {
MOCK_METHOD1(do_grow, size_t(size_t capacity));
- void grow(size_t capacity) { this->set(this->data(), do_grow(capacity)); }
+ void grow(size_t capacity) override {
+ this->set(this->data(), do_grow(capacity));
+ }
- mock_buffer(T* data = nullptr, size_t capacity = 0) {
- this->set(data, capacity);
+ mock_buffer(T* data = nullptr, size_t buf_capacity = 0) {
+ this->set(data, buf_capacity);
ON_CALL(*this, do_grow(_)).WillByDefault(Invoke([](size_t capacity) {
return capacity;
}));
}
};
-TEST(BufferTest, Ctor) {
+TEST(buffer_test, ctor) {
{
mock_buffer<int> buffer;
EXPECT_EQ(nullptr, buffer.data());
@@ -115,7 +187,7 @@ TEST(BufferTest, Ctor) {
}
}
-TEST(BufferTest, Access) {
+TEST(buffer_test, access) {
char data[10];
mock_buffer<char> buffer(data, sizeof(data));
buffer[0] = 11;
@@ -126,7 +198,7 @@ TEST(BufferTest, Access) {
EXPECT_EQ(42, const_buffer[3]);
}
-TEST(BufferTest, TryResize) {
+TEST(buffer_test, try_resize) {
char data[123];
mock_buffer<char> buffer(data, sizeof(data));
buffer[10] = 42;
@@ -146,7 +218,7 @@ TEST(BufferTest, TryResize) {
buffer.try_resize(200);
}
-TEST(BufferTest, TryResizePartial) {
+TEST(buffer_test, try_resize_partial) {
char data[10];
mock_buffer<char> buffer(data, sizeof(data));
EXPECT_CALL(buffer, do_grow(20)).WillOnce(Return(15));
@@ -155,7 +227,7 @@ TEST(BufferTest, TryResizePartial) {
EXPECT_EQ(buffer.size(), 15);
}
-TEST(BufferTest, Clear) {
+TEST(buffer_test, clear) {
mock_buffer<char> buffer;
EXPECT_CALL(buffer, do_grow(20));
buffer.try_resize(20);
@@ -164,7 +236,7 @@ TEST(BufferTest, Clear) {
EXPECT_EQ(20u, buffer.capacity());
}
-TEST(BufferTest, Append) {
+TEST(buffer_test, append) {
char data[15];
mock_buffer<char> buffer(data, 10);
auto test = "test";
@@ -179,7 +251,7 @@ TEST(BufferTest, Append) {
EXPECT_EQ(12u, buffer.size());
}
-TEST(BufferTest, AppendPartial) {
+TEST(buffer_test, append_partial) {
char data[10];
mock_buffer<char> buffer(data, sizeof(data));
testing::InSequence seq;
@@ -193,7 +265,7 @@ TEST(BufferTest, AppendPartial) {
buffer.append(test, test + 15);
}
-TEST(BufferTest, AppendAllocatesEnoughStorage) {
+TEST(buffer_test, append_allocates_enough_storage) {
char data[19];
mock_buffer<char> buffer(data, 10);
auto test = "abcdefgh";
@@ -202,18 +274,14 @@ TEST(BufferTest, AppendAllocatesEnoughStorage) {
buffer.append(test, test + 9);
}
-TEST(ArgTest, FormatArgs) {
- auto args = fmt::format_args();
- EXPECT_FALSE(args.get(1));
-}
-
struct custom_context {
using char_type = char;
using parse_context_type = fmt::format_parse_context;
+ bool called = false;
+
template <typename T> struct formatter_type {
- template <typename ParseContext>
- auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ auto parse(fmt::format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
@@ -223,31 +291,39 @@ struct custom_context {
}
};
- bool called;
- fmt::format_parse_context ctx;
-
- fmt::format_parse_context& parse_context() { return ctx; }
void advance_to(const char*) {}
};
-TEST(ArgTest, MakeValueWithCustomContext) {
+struct test_struct {};
+
+FMT_BEGIN_NAMESPACE
+template <typename Char> struct formatter<test_struct, Char> {
+ auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+
+ auto format(test_struct, format_context& ctx) -> decltype(ctx.out()) {
+ auto test = string_view("test");
+ return std::copy_n(test.data(), test.size(), ctx.out());
+ }
+};
+FMT_END_NAMESPACE
+
+TEST(arg_test, format_args) {
+ auto args = fmt::format_args();
+ EXPECT_FALSE(args.get(1));
+}
+
+TEST(arg_test, make_value_with_custom_context) {
auto t = test_struct();
fmt::detail::value<custom_context> arg(
fmt::detail::arg_mapper<custom_context>().map(t));
- custom_context ctx = {false, fmt::format_parse_context("")};
- arg.custom.format(&t, ctx.parse_context(), ctx);
+ auto ctx = custom_context();
+ auto parse_ctx = fmt::format_parse_context("");
+ arg.custom.format(&t, parse_ctx, ctx);
EXPECT_TRUE(ctx.called);
}
-FMT_BEGIN_NAMESPACE
-namespace detail {
-template <typename Char>
-bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
- return lhs.value == rhs.value;
-}
-} // namespace detail
-FMT_END_NAMESPACE
-
// Use a unique result type to make sure that there are no undesirable
// conversions.
struct test_result {};
@@ -288,81 +364,80 @@ VISIT_TYPE(long, long long);
VISIT_TYPE(unsigned long, unsigned long long);
#endif
-#define CHECK_ARG_(Char, expected, value) \
- { \
- testing::StrictMock<mock_visitor<decltype(expected)>> visitor; \
- EXPECT_CALL(visitor, visit(expected)); \
- using iterator = std::back_insert_iterator<buffer<Char>>; \
- fmt::visit_format_arg( \
- visitor, make_arg<fmt::basic_format_context<iterator, Char>>(value)); \
+#define CHECK_ARG(Char, expected, value) \
+ { \
+ testing::StrictMock<mock_visitor<decltype(expected)>> visitor; \
+ EXPECT_CALL(visitor, visit(expected)); \
+ using iterator = std::back_insert_iterator<buffer<Char>>; \
+ fmt::visit_format_arg( \
+ visitor, \
+ fmt::detail::make_arg<fmt::basic_format_context<iterator, Char>>( \
+ value)); \
}
-#define CHECK_ARG(value, typename_) \
- { \
- using value_type = decltype(value); \
- typename_ visit_type<value_type>::type expected = value; \
- CHECK_ARG_(char, expected, value) \
- CHECK_ARG_(wchar_t, expected, value) \
+#define CHECK_ARG_SIMPLE(value) \
+ { \
+ using value_type = decltype(value); \
+ typename visit_type<value_type>::type expected = value; \
+ CHECK_ARG(char, expected, value) \
+ CHECK_ARG(wchar_t, expected, value) \
}
-template <typename T> class NumericArgTest : public testing::Test {};
+template <typename T> class numeric_arg_test : public testing::Test {};
using types =
- ::testing::Types<bool, signed char, unsigned char, signed, unsigned short,
- int, unsigned, long, unsigned long, long long,
- unsigned long long, float, double, long double>;
-TYPED_TEST_CASE(NumericArgTest, types);
+ testing::Types<bool, signed char, unsigned char, short, unsigned short, int,
+ unsigned, long, unsigned long, long long, unsigned long long,
+ float, double, long double>;
+TYPED_TEST_SUITE(numeric_arg_test, types);
-template <typename T>
-fmt::enable_if_t<std::is_integral<T>::value, T> test_value() {
+template <typename T, fmt::enable_if_t<std::is_integral<T>::value, int> = 0>
+T test_value() {
return static_cast<T>(42);
}
-template <typename T>
-fmt::enable_if_t<std::is_floating_point<T>::value, T> test_value() {
+template <typename T,
+ fmt::enable_if_t<std::is_floating_point<T>::value, int> = 0>
+T test_value() {
return static_cast<T>(4.2);
}
-TYPED_TEST(NumericArgTest, MakeAndVisit) {
- CHECK_ARG(test_value<TypeParam>(), typename);
- CHECK_ARG(std::numeric_limits<TypeParam>::min(), typename);
- CHECK_ARG(std::numeric_limits<TypeParam>::max(), typename);
+TYPED_TEST(numeric_arg_test, make_and_visit) {
+ CHECK_ARG_SIMPLE(test_value<TypeParam>());
+ CHECK_ARG_SIMPLE(std::numeric_limits<TypeParam>::min());
+ CHECK_ARG_SIMPLE(std::numeric_limits<TypeParam>::max());
}
-TEST(ArgTest, CharArg) {
- CHECK_ARG_(char, 'a', 'a');
- CHECK_ARG_(wchar_t, L'a', 'a');
- CHECK_ARG_(wchar_t, L'a', L'a');
-}
+TEST(arg_test, char_arg) { CHECK_ARG(char, 'a', 'a'); }
-TEST(ArgTest, StringArg) {
+TEST(arg_test, string_arg) {
char str_data[] = "test";
char* str = str_data;
const char* cstr = str;
- CHECK_ARG_(char, cstr, str);
+ CHECK_ARG(char, cstr, str);
- auto sref = string_view(str);
- CHECK_ARG_(char, sref, std::string(str));
+ auto sv = fmt::string_view(str);
+ CHECK_ARG(char, sv, std::string(str));
}
-TEST(ArgTest, WStringArg) {
+TEST(arg_test, wstring_arg) {
wchar_t str_data[] = L"test";
wchar_t* str = str_data;
const wchar_t* cstr = str;
- fmt::wstring_view sref(str);
- CHECK_ARG_(wchar_t, cstr, str);
- CHECK_ARG_(wchar_t, cstr, cstr);
- CHECK_ARG_(wchar_t, sref, std::wstring(str));
- CHECK_ARG_(wchar_t, sref, fmt::wstring_view(str));
+ auto sv = fmt::basic_string_view<wchar_t>(str);
+ CHECK_ARG(wchar_t, cstr, str);
+ CHECK_ARG(wchar_t, cstr, cstr);
+ CHECK_ARG(wchar_t, sv, std::wstring(str));
+ CHECK_ARG(wchar_t, sv, fmt::basic_string_view<wchar_t>(str));
}
-TEST(ArgTest, PointerArg) {
+TEST(arg_test, pointer_arg) {
void* p = nullptr;
const void* cp = nullptr;
- CHECK_ARG_(char, cp, p);
- CHECK_ARG_(wchar_t, cp, p);
- CHECK_ARG(cp, );
+ CHECK_ARG(char, cp, p);
+ CHECK_ARG(wchar_t, cp, p);
+ CHECK_ARG_SIMPLE(cp);
}
struct check_custom {
@@ -371,222 +446,237 @@ struct check_custom {
struct test_buffer final : fmt::detail::buffer<char> {
char data[10];
test_buffer() : fmt::detail::buffer<char>(data, 0, 10) {}
- void grow(size_t) {}
+ void grow(size_t) override {}
} buffer;
- fmt::format_parse_context parse_ctx("");
- fmt::format_context ctx{fmt::detail::buffer_appender<char>(buffer),
- fmt::format_args()};
+ auto parse_ctx = fmt::format_parse_context("");
+ auto ctx = fmt::format_context(fmt::detail::buffer_appender<char>(buffer),
+ fmt::format_args());
h.format(parse_ctx, ctx);
EXPECT_EQ("test", std::string(buffer.data, buffer.size()));
return test_result();
}
};
-TEST(ArgTest, CustomArg) {
- test_struct test;
+TEST(arg_test, custom_arg) {
+ auto test = test_struct();
using visitor =
mock_visitor<fmt::basic_format_arg<fmt::format_context>::handle>;
testing::StrictMock<visitor> v;
EXPECT_CALL(v, visit(_)).WillOnce(Invoke(check_custom()));
- fmt::visit_format_arg(v, make_arg<fmt::format_context>(test));
+ fmt::visit_format_arg(v, fmt::detail::make_arg<fmt::format_context>(test));
}
-TEST(ArgTest, VisitInvalidArg) {
+TEST(arg_test, visit_invalid_arg) {
testing::StrictMock<mock_visitor<fmt::monostate>> visitor;
EXPECT_CALL(visitor, visit(_));
- fmt::basic_format_arg<fmt::format_context> arg;
+ auto arg = fmt::basic_format_arg<fmt::format_context>();
fmt::visit_format_arg(visitor, arg);
}
-TEST(FormatDynArgsTest, Basic) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- store.push_back(42);
- store.push_back("abc1");
- store.push_back(1.5f);
- EXPECT_EQ("42 and abc1 and 1.5", fmt::vformat("{} and {} and {}", store));
-}
-
-TEST(FormatDynArgsTest, StringsAndRefs) {
- // Unfortunately the tests are compiled with old ABI so strings use COW.
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- char str[] = "1234567890";
- store.push_back(str);
- store.push_back(std::cref(str));
- store.push_back(fmt::string_view{str});
- str[0] = 'X';
+#if FMT_USE_CONSTEXPR
- std::string result = fmt::vformat("{} and {} and {}", store);
- EXPECT_EQ("1234567890 and X234567890 and X234567890", result);
-}
+enum class arg_id_result { none, empty, index, name, error };
+struct test_arg_id_handler {
+ arg_id_result res = arg_id_result::none;
+ int index = 0;
+ string_view name;
-struct custom_type {
- int i = 0;
-};
+ constexpr void operator()() { res = arg_id_result::empty; }
-FMT_BEGIN_NAMESPACE
-template <> struct formatter<custom_type> {
- auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
- return ctx.begin();
+ constexpr void operator()(int i) {
+ res = arg_id_result::index;
+ index = i;
}
- template <typename FormatContext>
- auto format(const custom_type& p, FormatContext& ctx) -> decltype(ctx.out()) {
- return format_to(ctx.out(), "cust={}", p.i);
+ constexpr void operator()(string_view n) {
+ res = arg_id_result::name;
+ name = n;
}
+
+ constexpr void on_error(const char*) { res = arg_id_result::error; }
};
-FMT_END_NAMESPACE
-TEST(FormatDynArgsTest, CustomFormat) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- custom_type c{};
- store.push_back(c);
- ++c.i;
- store.push_back(c);
- ++c.i;
- store.push_back(std::cref(c));
- ++c.i;
- std::string result = fmt::vformat("{} and {} and {}", store);
- EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
-}
-
-TEST(FormatDynArgsTest, NamedInt) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- store.push_back(fmt::arg("a1", 42));
- EXPECT_EQ("42", fmt::vformat("{a1}", store));
-}
-
-TEST(FormatDynArgsTest, NamedStrings) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- char str[]{"1234567890"};
- store.push_back(fmt::arg("a1", str));
- store.push_back(fmt::arg("a2", std::cref(str)));
- str[0] = 'X';
- EXPECT_EQ("1234567890 and X234567890", fmt::vformat("{a1} and {a2}", store));
-}
-
-TEST(FormatDynArgsTest, NamedArgByRef) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
-
- // Note: fmt::arg() constructs an object which holds a reference
- // to its value. It's not an aggregate, so it doesn't extend the
- // reference lifetime. As a result, it's a very bad idea passing temporary
- // as a named argument value. Only GCC with optimization level >0
- // complains about this.
- //
- // A real life usecase is when you have both name and value alive
- // guarantee their lifetime and thus don't want them to be copied into
- // storages.
- int a1_val{42};
- auto a1 = fmt::arg("a1_", a1_val);
- store.push_back("abc");
- store.push_back(1.5f);
- store.push_back(std::cref(a1));
-
- std::string result = fmt::vformat("{a1_} and {} and {} and {}", store);
- EXPECT_EQ("42 and abc and 1.5 and 42", result);
-}
-
-TEST(FormatDynArgsTest, NamedCustomFormat) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- custom_type c{};
- store.push_back(fmt::arg("c1", c));
- ++c.i;
- store.push_back(fmt::arg("c2", c));
- ++c.i;
- store.push_back(fmt::arg("c_ref", std::cref(c)));
- ++c.i;
- std::string result = fmt::vformat("{c1} and {c2} and {c_ref}", store);
- EXPECT_EQ("cust=0 and cust=1 and cust=3", result);
-}
-
-TEST(FormatDynArgsTest, Clear) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- store.push_back(42);
-
- std::string result = fmt::vformat("{}", store);
- EXPECT_EQ("42", result);
-
- store.push_back(43);
- result = fmt::vformat("{} and {}", store);
- EXPECT_EQ("42 and 43", result);
-
- store.clear();
- store.push_back(44);
- result = fmt::vformat("{}", store);
- EXPECT_EQ("44", result);
-}
-
-TEST(FormatDynArgsTest, Reserve) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- store.reserve(2, 1);
- store.push_back(1.5f);
- store.push_back(fmt::arg("a1", 42));
- std::string result = fmt::vformat("{a1} and {}", store);
- EXPECT_EQ("42 and 1.5", result);
-}
-
-struct copy_throwable {
- copy_throwable() {}
- copy_throwable(const copy_throwable&) { throw "deal with it"; }
+template <size_t N>
+constexpr test_arg_id_handler parse_arg_id(const char (&s)[N]) {
+ test_arg_id_handler h;
+ fmt::detail::parse_arg_id(s, s + N, h);
+ return h;
+}
+
+TEST(format_test, constexpr_parse_arg_id) {
+ static_assert(parse_arg_id(":").res == arg_id_result::empty, "");
+ static_assert(parse_arg_id("}").res == arg_id_result::empty, "");
+ static_assert(parse_arg_id("42:").res == arg_id_result::index, "");
+ static_assert(parse_arg_id("42:").index == 42, "");
+ static_assert(parse_arg_id("foo:").res == arg_id_result::name, "");
+ static_assert(parse_arg_id("foo:").name.size() == 3, "");
+ static_assert(parse_arg_id("!").res == arg_id_result::error, "");
+}
+
+struct test_format_specs_handler {
+ enum result { none, hash, zero, loc, error };
+ result res = none;
+
+ fmt::align_t alignment = fmt::align::none;
+ fmt::sign_t sign = fmt::sign::none;
+ char fill = 0;
+ int width = 0;
+ fmt::detail::arg_ref<char> width_ref;
+ int precision = 0;
+ fmt::detail::arg_ref<char> precision_ref;
+ fmt::presentation_type type = fmt::presentation_type::none;
+
+ // Workaround for MSVC2017 bug that results in "expression did not evaluate
+ // to a constant" with compiler-generated copy ctor.
+ constexpr test_format_specs_handler() {}
+ constexpr test_format_specs_handler(const test_format_specs_handler& other) =
+ default;
+
+ constexpr void on_align(fmt::align_t a) { alignment = a; }
+ constexpr void on_fill(fmt::string_view f) { fill = f[0]; }
+ constexpr void on_sign(fmt::sign_t s) { sign = s; }
+ constexpr void on_hash() { res = hash; }
+ constexpr void on_zero() { res = zero; }
+ constexpr void on_localized() { res = loc; }
+
+ constexpr void on_width(int w) { width = w; }
+ constexpr void on_dynamic_width(fmt::detail::auto_id) {}
+ constexpr void on_dynamic_width(int index) { width_ref = index; }
+ constexpr void on_dynamic_width(string_view) {}
+
+ constexpr void on_precision(int p) { precision = p; }
+ constexpr void on_dynamic_precision(fmt::detail::auto_id) {}
+ constexpr void on_dynamic_precision(int index) { precision_ref = index; }
+ constexpr void on_dynamic_precision(string_view) {}
+
+ constexpr void end_precision() {}
+ constexpr void on_type(fmt::presentation_type t) { type = t; }
+ constexpr void on_error(const char*) { res = error; }
};
-FMT_BEGIN_NAMESPACE
-template <> struct formatter<copy_throwable> {
- auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) {
- return ctx.begin();
- }
- auto format(copy_throwable, format_context& ctx) -> decltype(ctx.out()) {
- return ctx.out();
- }
+template <size_t N>
+constexpr test_format_specs_handler parse_test_specs(const char (&s)[N]) {
+ auto h = test_format_specs_handler();
+ fmt::detail::parse_format_specs(s, s + N - 1, h);
+ return h;
+}
+
+TEST(core_test, constexpr_parse_format_specs) {
+ using handler = test_format_specs_handler;
+ static_assert(parse_test_specs("<").alignment == fmt::align::left, "");
+ static_assert(parse_test_specs("*^").fill == '*', "");
+ static_assert(parse_test_specs("+").sign == fmt::sign::plus, "");
+ static_assert(parse_test_specs("-").sign == fmt::sign::minus, "");
+ static_assert(parse_test_specs(" ").sign == fmt::sign::space, "");
+ static_assert(parse_test_specs("#").res == handler::hash, "");
+ static_assert(parse_test_specs("0").res == handler::zero, "");
+ static_assert(parse_test_specs("L").res == handler::loc, "");
+ static_assert(parse_test_specs("42").width == 42, "");
+ static_assert(parse_test_specs("{42}").width_ref.val.index == 42, "");
+ static_assert(parse_test_specs(".42").precision == 42, "");
+ static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, "");
+ static_assert(parse_test_specs("d").type == fmt::presentation_type::dec, "");
+ static_assert(parse_test_specs("{<").res == handler::error, "");
+}
+
+struct test_parse_context {
+ using char_type = char;
+
+ constexpr int next_arg_id() { return 11; }
+ template <typename Id> FMT_CONSTEXPR void check_arg_id(Id) {}
+
+ constexpr const char* begin() { return nullptr; }
+ constexpr const char* end() { return nullptr; }
+
+ void on_error(const char*) {}
};
-FMT_END_NAMESPACE
-TEST(FormatDynArgsTest, ThrowOnCopy) {
- fmt::dynamic_format_arg_store<fmt::format_context> store;
- store.push_back(std::string("foo"));
- try {
- store.push_back(copy_throwable());
- } catch (...) {
- }
- EXPECT_EQ(fmt::vformat("{}", store), "foo");
+template <size_t N>
+constexpr fmt::detail::dynamic_format_specs<char> parse_dynamic_specs(
+ const char (&s)[N]) {
+ auto specs = fmt::detail::dynamic_format_specs<char>();
+ auto ctx = test_parse_context();
+ auto h = fmt::detail::dynamic_specs_handler<test_parse_context>(specs, ctx);
+ parse_format_specs(s, s + N - 1, h);
+ return specs;
+}
+
+TEST(format_test, constexpr_dynamic_specs_handler) {
+ static_assert(parse_dynamic_specs("<").align == fmt::align::left, "");
+ static_assert(parse_dynamic_specs("*^").fill[0] == '*', "");
+ static_assert(parse_dynamic_specs("+").sign == fmt::sign::plus, "");
+ static_assert(parse_dynamic_specs("-").sign == fmt::sign::minus, "");
+ static_assert(parse_dynamic_specs(" ").sign == fmt::sign::space, "");
+ static_assert(parse_dynamic_specs("#").alt, "");
+ static_assert(parse_dynamic_specs("0").align == fmt::align::numeric, "");
+ static_assert(parse_dynamic_specs("42").width == 42, "");
+ static_assert(parse_dynamic_specs("{}").width_ref.val.index == 11, "");
+ static_assert(parse_dynamic_specs("{42}").width_ref.val.index == 42, "");
+ static_assert(parse_dynamic_specs(".42").precision == 42, "");
+ static_assert(parse_dynamic_specs(".{}").precision_ref.val.index == 11, "");
+ static_assert(parse_dynamic_specs(".{42}").precision_ref.val.index == 42, "");
+ static_assert(parse_dynamic_specs("d").type == fmt::presentation_type::dec,
+ "");
}
-TEST(StringViewTest, ValueType) {
- static_assert(std::is_same<string_view::value_type, char>::value, "");
+template <size_t N>
+constexpr test_format_specs_handler check_specs(const char (&s)[N]) {
+ fmt::detail::specs_checker<test_format_specs_handler> checker(
+ test_format_specs_handler(), fmt::detail::type::double_type);
+ parse_format_specs(s, s + N - 1, checker);
+ return checker;
}
-TEST(StringViewTest, Length) {
- // Test that string_view::size() returns string length, not buffer size.
- char str[100] = "some string";
- EXPECT_EQ(std::strlen(str), string_view(str).size());
- EXPECT_LT(std::strlen(str), sizeof(str));
+TEST(format_test, constexpr_specs_checker) {
+ using handler = test_format_specs_handler;
+ static_assert(check_specs("<").alignment == fmt::align::left, "");
+ static_assert(check_specs("*^").fill == '*', "");
+ static_assert(check_specs("+").sign == fmt::sign::plus, "");
+ static_assert(check_specs("-").sign == fmt::sign::minus, "");
+ static_assert(check_specs(" ").sign == fmt::sign::space, "");
+ static_assert(check_specs("#").res == handler::hash, "");
+ static_assert(check_specs("0").res == handler::zero, "");
+ static_assert(check_specs("42").width == 42, "");
+ static_assert(check_specs("{42}").width_ref.val.index == 42, "");
+ static_assert(check_specs(".42").precision == 42, "");
+ static_assert(check_specs(".{42}").precision_ref.val.index == 42, "");
+ static_assert(check_specs("d").type == fmt::presentation_type::dec, "");
+ static_assert(check_specs("{<").res == handler::error, "");
}
-// Check string_view's comparison operator.
-template <template <typename> class Op> void check_op() {
- const char* inputs[] = {"foo", "fop", "fo"};
- size_t num_inputs = sizeof(inputs) / sizeof(*inputs);
- for (size_t i = 0; i < num_inputs; ++i) {
- for (size_t j = 0; j < num_inputs; ++j) {
- string_view lhs(inputs[i]), rhs(inputs[j]);
- EXPECT_EQ(Op<int>()(lhs.compare(rhs), 0), Op<string_view>()(lhs, rhs));
- }
+struct test_format_string_handler {
+ constexpr void on_text(const char*, const char*) {}
+
+ constexpr int on_arg_id() { return 0; }
+
+ template <typename T> constexpr int on_arg_id(T) { return 0; }
+
+ constexpr void on_replacement_field(int, const char*) {}
+
+ constexpr const char* on_format_specs(int, const char* begin, const char*) {
+ return begin;
}
+
+ constexpr void on_error(const char*) { error = true; }
+
+ bool error = false;
+};
+
+template <size_t N> constexpr bool parse_string(const char (&s)[N]) {
+ auto h = test_format_string_handler();
+ fmt::detail::parse_format_string<true>(fmt::string_view(s, N - 1), h);
+ return !h.error;
}
-TEST(StringViewTest, Compare) {
- EXPECT_EQ(string_view("foo").compare(string_view("foo")), 0);
- EXPECT_GT(string_view("fop").compare(string_view("foo")), 0);
- EXPECT_LT(string_view("foo").compare(string_view("fop")), 0);
- EXPECT_GT(string_view("foo").compare(string_view("fo")), 0);
- EXPECT_LT(string_view("fo").compare(string_view("foo")), 0);
- check_op<std::equal_to>();
- check_op<std::not_equal_to>();
- check_op<std::less>();
- check_op<std::less_equal>();
- check_op<std::greater>();
- check_op<std::greater_equal>();
+TEST(format_test, constexpr_parse_format_string) {
+ static_assert(parse_string("foo"), "");
+ static_assert(!parse_string("}"), "");
+ static_assert(parse_string("{}"), "");
+ static_assert(parse_string("{42}"), "");
+ static_assert(parse_string("{foo}"), "");
+ static_assert(parse_string("{:}"), "");
}
+#endif // FMT_USE_CONSTEXPR
struct enabled_formatter {};
struct disabled_formatter {};
@@ -605,7 +695,7 @@ template <> struct formatter<enabled_formatter> {
};
FMT_END_NAMESPACE
-TEST(CoreTest, HasFormatter) {
+TEST(core_test, has_formatter) {
using fmt::has_formatter;
using context = fmt::format_context;
static_assert(has_formatter<enabled_formatter, context>::value, "");
@@ -614,6 +704,90 @@ TEST(CoreTest, HasFormatter) {
"");
}
+struct const_formattable {};
+struct nonconst_formattable {};
+
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<const_formattable> {
+ auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+
+ auto format(const const_formattable&, format_context& ctx)
+ -> decltype(ctx.out()) {
+ auto test = string_view("test");
+ return std::copy_n(test.data(), test.size(), ctx.out());
+ }
+};
+
+template <> struct formatter<nonconst_formattable> {
+ auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
+
+ auto format(nonconst_formattable&, format_context& ctx)
+ -> decltype(ctx.out()) {
+ auto test = string_view("test");
+ return std::copy_n(test.data(), test.size(), ctx.out());
+ }
+};
+FMT_END_NAMESPACE
+
+struct convertible_to_pointer {
+ operator const int*() const { return nullptr; }
+};
+
+enum class test_scoped_enum {};
+
+TEST(core_test, is_formattable) {
+#if 0
+ // This should be enabled once corresponding map overloads are gone.
+ static_assert(fmt::is_formattable<signed char*>::value, "");
+ static_assert(fmt::is_formattable<unsigned char*>::value, "");
+ static_assert(fmt::is_formattable<const signed char*>::value, "");
+ static_assert(fmt::is_formattable<const unsigned char*>::value, "");
+#endif
+ static_assert(!fmt::is_formattable<wchar_t>::value, "");
+#ifdef __cpp_char8_t
+ static_assert(!fmt::is_formattable<char8_t>::value, "");
+#endif
+ static_assert(!fmt::is_formattable<char16_t>::value, "");
+ static_assert(!fmt::is_formattable<char32_t>::value, "");
+ static_assert(!fmt::is_formattable<const wchar_t*>::value, "");
+ static_assert(!fmt::is_formattable<const wchar_t[3]>::value, "");
+ static_assert(!fmt::is_formattable<fmt::basic_string_view<wchar_t>>::value,
+ "");
+ static_assert(fmt::is_formattable<enabled_formatter>::value, "");
+ static_assert(!fmt::is_formattable<disabled_formatter>::value, "");
+ static_assert(fmt::is_formattable<disabled_formatter_convertible>::value, "");
+
+ static_assert(fmt::is_formattable<const_formattable&>::value, "");
+ static_assert(fmt::is_formattable<const const_formattable&>::value, "");
+
+ static_assert(fmt::is_formattable<nonconst_formattable&>::value, "");
+#if !FMT_MSC_VER || FMT_MSC_VER >= 1910
+ static_assert(!fmt::is_formattable<const nonconst_formattable&>::value, "");
+#endif
+
+ static_assert(!fmt::is_formattable<convertible_to_pointer>::value, "");
+
+ static_assert(!fmt::is_formattable<void (*)()>::value, "");
+
+ struct s;
+
+ static_assert(!fmt::is_formattable<int(s::*)>::value, "");
+ static_assert(!fmt::is_formattable<int (s::*)()>::value, "");
+ static_assert(!fmt::is_formattable<test_scoped_enum>::value, "");
+}
+
+TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); }
+
+TEST(core_test, format_to) {
+ std::string s;
+ fmt::format_to(std::back_inserter(s), "{}", 42);
+ EXPECT_EQ(s, "42");
+}
+
struct convertible_to_int {
operator int() const { return 42; }
};
@@ -633,7 +807,7 @@ template <> struct formatter<convertible_to_int> {
};
template <> struct formatter<convertible_to_c_string> {
- auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
+ FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
auto format(convertible_to_c_string, format_context& ctx)
@@ -643,90 +817,26 @@ template <> struct formatter<convertible_to_c_string> {
};
FMT_END_NAMESPACE
-TEST(CoreTest, FormatterOverridesImplicitConversion) {
+TEST(core_test, formatter_overrides_implicit_conversion) {
EXPECT_EQ(fmt::format("{}", convertible_to_int()), "foo");
EXPECT_EQ(fmt::format("{}", convertible_to_c_string()), "bar");
}
-namespace my_ns {
-template <typename Char> class my_string {
- private:
- std::basic_string<Char> s_;
-
- public:
- my_string(const Char* s) : s_(s) {}
- const Char* data() const FMT_NOEXCEPT { return s_.data(); }
- size_t length() const FMT_NOEXCEPT { return s_.size(); }
- operator const Char*() const { return s_.c_str(); }
-};
-
-template <typename Char>
-inline fmt::basic_string_view<Char> to_string_view(const my_string<Char>& s)
- FMT_NOEXCEPT {
- return {s.data(), s.length()};
-}
-
-struct non_string {};
-} // namespace my_ns
-
-template <typename T> class IsStringTest : public testing::Test {};
-
-typedef ::testing::Types<char, wchar_t, char16_t, char32_t> StringCharTypes;
-TYPED_TEST_CASE(IsStringTest, StringCharTypes);
-
-namespace {
-template <typename Char>
-struct derived_from_string_view : fmt::basic_string_view<Char> {};
-} // namespace
-
-TYPED_TEST(IsStringTest, IsString) {
- EXPECT_TRUE(fmt::detail::is_string<TypeParam*>::value);
- EXPECT_TRUE(fmt::detail::is_string<const TypeParam*>::value);
- EXPECT_TRUE(fmt::detail::is_string<TypeParam[2]>::value);
- EXPECT_TRUE(fmt::detail::is_string<const TypeParam[2]>::value);
- EXPECT_TRUE(fmt::detail::is_string<std::basic_string<TypeParam>>::value);
- EXPECT_TRUE(fmt::detail::is_string<fmt::basic_string_view<TypeParam>>::value);
- EXPECT_TRUE(
- fmt::detail::is_string<derived_from_string_view<TypeParam>>::value);
- using string_view = fmt::detail::std_string_view<TypeParam>;
- EXPECT_TRUE(std::is_empty<string_view>::value !=
- fmt::detail::is_string<string_view>::value);
- EXPECT_TRUE(fmt::detail::is_string<my_ns::my_string<TypeParam>>::value);
- EXPECT_FALSE(fmt::detail::is_string<my_ns::non_string>::value);
-}
-
-TEST(CoreTest, Format) {
- // This should work without including fmt/format.h.
-#ifdef FMT_FORMAT_H_
-# error fmt/format.h must not be included in the core test
-#endif
- EXPECT_EQ(fmt::format("{}", 42), "42");
-}
-
-TEST(CoreTest, FormatTo) {
- // This should work without including fmt/format.h.
-#ifdef FMT_FORMAT_H_
-# error fmt/format.h must not be included in the core test
-#endif
- std::string s;
- fmt::format_to(std::back_inserter(s), "{}", 42);
- EXPECT_EQ(s, "42");
+// Test that check is not found by ADL.
+template <typename T> void check(T);
+TEST(core_test, adl_check) {
+ EXPECT_EQ(fmt::format("{}", test_struct()), "test");
}
-TEST(CoreTest, ToStringViewForeignStrings) {
- using namespace my_ns;
- EXPECT_EQ(to_string_view(my_string<char>("42")), "42");
+TEST(core_test, to_string_view_foreign_strings) {
+ using namespace test_ns;
+ EXPECT_EQ(to_string_view(test_string<char>("42")), "42");
fmt::detail::type type =
- fmt::detail::mapped_type_constant<my_string<char>,
+ fmt::detail::mapped_type_constant<test_string<char>,
fmt::format_context>::value;
EXPECT_EQ(type, fmt::detail::type::string_type);
}
-TEST(CoreTest, FormatForeignStrings) {
- using namespace my_ns;
- EXPECT_EQ(fmt::format(my_string<char>("{}"), 42), "42");
-}
-
struct implicitly_convertible_to_string {
operator std::string() const { return "foo"; }
};
@@ -735,7 +845,7 @@ struct implicitly_convertible_to_string_view {
operator fmt::string_view() const { return "foo"; }
};
-TEST(CoreTest, FormatImplicitlyConvertibleToStringView) {
+TEST(core_test, format_implicitly_convertible_to_string_view) {
EXPECT_EQ("foo", fmt::format("{}", implicitly_convertible_to_string_view()));
}
@@ -745,7 +855,7 @@ struct explicitly_convertible_to_string_view {
explicit operator fmt::string_view() const { return "foo"; }
};
-TEST(CoreTest, FormatExplicitlyConvertibleToStringView) {
+TEST(core_test, format_explicitly_convertible_to_string_view) {
EXPECT_EQ("foo", fmt::format("{}", explicitly_convertible_to_string_view()));
}
@@ -754,13 +864,21 @@ struct explicitly_convertible_to_std_string_view {
explicit operator std::string_view() const { return "foo"; }
};
-TEST(CoreTest, FormatExplicitlyConvertibleToStdStringView) {
+TEST(core_test, format_explicitly_convertible_to_std_string_view) {
EXPECT_EQ("foo",
fmt::format("{}", explicitly_convertible_to_std_string_view()));
}
# endif
#endif
+struct convertible_to_long_long {
+ operator long long() const { return 1LL << 32; }
+};
+
+TEST(format_test, format_convertible_to_long_long) {
+ EXPECT_EQ("100000000", fmt::format("{:x}", convertible_to_long_long()));
+}
+
struct disabled_rvalue_conversion {
operator const char*() const& { return "foo"; }
operator const char*() & { return "foo"; }
@@ -768,6 +886,38 @@ struct disabled_rvalue_conversion {
operator const char*() && = delete;
};
-TEST(CoreTest, DisabledRValueConversion) {
+TEST(core_test, disabled_rvalue_conversion) {
EXPECT_EQ("foo", fmt::format("{}", disabled_rvalue_conversion()));
}
+
+namespace adl_test {
+template <typename... T> void make_format_args(const T&...) = delete;
+
+struct string : std::string {};
+} // namespace adl_test
+
+// Test that formatting functions compile when make_format_args is found by ADL.
+TEST(core_test, adl) {
+ // Only check compilation and don't run the code to avoid polluting the output
+ // and since the output is tested elsewhere.
+ if (fmt::detail::const_check(true)) return;
+ auto s = adl_test::string();
+ char buf[10];
+ (void)fmt::format("{}", s);
+ fmt::format_to(buf, "{}", s);
+ fmt::format_to_n(buf, 10, "{}", s);
+ (void)fmt::formatted_size("{}", s);
+ fmt::print("{}", s);
+ fmt::print(stdout, "{}", s);
+}
+
+TEST(core_test, has_const_formatter) {
+ EXPECT_TRUE((fmt::detail::has_const_formatter<const_formattable,
+ fmt::format_context>()));
+ EXPECT_FALSE((fmt::detail::has_const_formatter<nonconst_formattable,
+ fmt::format_context>()));
+}
+
+TEST(core_test, format_nonconst) {
+ EXPECT_EQ(fmt::format("{}", nonconst_formattable()), "test");
+}
diff --git a/contrib/libs/fmt/test/enforce-checks-test.cc b/contrib/libs/fmt/test/enforce-checks-test.cc
new file mode 100644
index 0000000000..c77cb142f6
--- /dev/null
+++ b/contrib/libs/fmt/test/enforce-checks-test.cc
@@ -0,0 +1,63 @@
+// Formatting library for C++ - formatting library tests
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include <iterator>
+#include <vector>
+
+#include "fmt/chrono.h"
+#include "fmt/color.h"
+#include "fmt/format.h"
+#include "fmt/ostream.h"
+#include "fmt/ranges.h"
+#include "fmt/xchar.h"
+
+// Exercise the API to verify that everything we expect to can compile.
+void test_format_api() {
+ (void)fmt::format(FMT_STRING("{}"), 42);
+ (void)fmt::format(FMT_STRING(L"{}"), 42);
+ (void)fmt::format(FMT_STRING("noop"));
+
+ (void)fmt::to_string(42);
+ (void)fmt::to_wstring(42);
+
+ std::vector<char> out;
+ fmt::format_to(std::back_inserter(out), FMT_STRING("{}"), 42);
+
+ char buffer[4];
+ fmt::format_to_n(buffer, 3, FMT_STRING("{}"), 12345);
+
+ wchar_t wbuffer[4];
+ fmt::format_to_n(wbuffer, 3, FMT_STRING(L"{}"), 12345);
+}
+
+void test_chrono() {
+ (void)fmt::format(FMT_STRING("{}"), std::chrono::seconds(42));
+ (void)fmt::format(FMT_STRING(L"{}"), std::chrono::seconds(42));
+}
+
+void test_text_style() {
+ fmt::print(fg(fmt::rgb(255, 20, 30)), FMT_STRING("{}"), "rgb(255,20,30)");
+ (void)fmt::format(fg(fmt::rgb(255, 20, 30)), FMT_STRING("{}"),
+ "rgb(255,20,30)");
+
+ fmt::text_style ts = fg(fmt::rgb(255, 20, 30));
+ std::string out;
+ fmt::format_to(std::back_inserter(out), ts,
+ FMT_STRING("rgb(255,20,30){}{}{}"), 1, 2, 3);
+}
+
+void test_range() {
+ std::vector<char> hello = {'h', 'e', 'l', 'l', 'o'};
+ (void)fmt::format(FMT_STRING("{}"), hello);
+}
+
+int main() {
+ test_format_api();
+ test_chrono();
+ test_text_style();
+ test_range();
+}
diff --git a/contrib/libs/fmt/test/format-impl-test.cc b/contrib/libs/fmt/test/format-impl-test.cc
index 66b55b5381..a012306f5b 100644
--- a/contrib/libs/fmt/test/format-impl-test.cc
+++ b/contrib/libs/fmt/test/format-impl-test.cc
@@ -5,24 +5,16 @@
//
// For the license information refer to format.h.
-#define FMT_NOEXCEPT
-#undef FMT_SHARED
-#include "test-assert.h"
-
-// Include format.cc instead of format.h to test implementation.
#include <algorithm>
#include <cstring>
-#include "../src/format.cc"
-#include "fmt/printf.h"
-#include <gmock/gmock.h>
-#include "gtest-extra.h"
-#include "util.h"
+// clang-format off
+#include "test-assert.h"
+// clang-format on
-#ifdef _WIN32
-# include <windows.h>
-# undef max
-#endif
+#include "fmt/format.h"
+#include "gmock/gmock.h"
+#include "util.h"
using fmt::detail::bigint;
using fmt::detail::fp;
@@ -31,13 +23,13 @@ using fmt::detail::max_value;
static_assert(!std::is_copy_constructible<bigint>::value, "");
static_assert(!std::is_copy_assignable<bigint>::value, "");
-TEST(BigIntTest, Construct) {
+TEST(bigint_test, construct) {
EXPECT_EQ("", fmt::format("{}", bigint()));
EXPECT_EQ("42", fmt::format("{}", bigint(0x42)));
EXPECT_EQ("123456789abcedf0", fmt::format("{}", bigint(0x123456789abcedf0)));
}
-TEST(BigIntTest, Compare) {
+TEST(bigint_test, compare) {
bigint n1(42);
bigint n2(42);
EXPECT_EQ(compare(n1, n2), 0);
@@ -51,7 +43,7 @@ TEST(BigIntTest, Compare) {
EXPECT_GT(compare(n4, n2), 0);
}
-TEST(BigIntTest, AddCompare) {
+TEST(bigint_test, add_compare) {
EXPECT_LT(
add_compare(bigint(0xffffffff), bigint(0xffffffff), bigint(1) <<= 64), 0);
EXPECT_LT(add_compare(bigint(1) <<= 32, bigint(1), bigint(1) <<= 96), 0);
@@ -77,7 +69,7 @@ TEST(BigIntTest, AddCompare) {
0);
}
-TEST(BigIntTest, ShiftLeft) {
+TEST(bigint_test, shift_left) {
bigint n(0x42);
n <<= 0;
EXPECT_EQ("42", fmt::format("{}", n));
@@ -87,7 +79,7 @@ TEST(BigIntTest, ShiftLeft) {
EXPECT_EQ("108000000", fmt::format("{}", n));
}
-TEST(BigIntTest, Multiply) {
+TEST(bigint_test, multiply) {
bigint n(0x42);
EXPECT_THROW(n *= 0, assertion_failure);
n *= 1;
@@ -104,7 +96,7 @@ TEST(BigIntTest, Multiply) {
EXPECT_EQ("fffffffffffffffe0000000000000001", fmt::format("{}", bigmax));
}
-TEST(BigIntTest, Accumulator) {
+TEST(bigint_test, accumulator) {
fmt::detail::accumulator acc;
EXPECT_EQ(acc.lower, 0);
EXPECT_EQ(acc.upper, 0);
@@ -113,7 +105,7 @@ TEST(BigIntTest, Accumulator) {
EXPECT_EQ(static_cast<uint32_t>(acc), 34);
acc += 56;
EXPECT_EQ(acc.lower, 90);
- acc += fmt::detail::max_value<uint64_t>();
+ acc += max_value<uint64_t>();
EXPECT_EQ(acc.upper, 13);
EXPECT_EQ(acc.lower, 89);
acc >>= 32;
@@ -121,7 +113,7 @@ TEST(BigIntTest, Accumulator) {
EXPECT_EQ(acc.lower, 13 * 0x100000000);
}
-TEST(BigIntTest, Square) {
+TEST(bigint_test, square) {
bigint n0(0);
n0.square();
EXPECT_EQ("0", fmt::format("{}", n0));
@@ -139,18 +131,18 @@ TEST(BigIntTest, Square) {
EXPECT_EQ("2540be400", fmt::format("{}", n4));
}
-TEST(BigIntTest, DivModAssignZeroDivisor) {
+TEST(bigint_test, divmod_assign_zero_divisor) {
bigint zero(0);
EXPECT_THROW(bigint(0).divmod_assign(zero), assertion_failure);
EXPECT_THROW(bigint(42).divmod_assign(zero), assertion_failure);
}
-TEST(BigIntTest, DivModAssignSelf) {
+TEST(bigint_test, divmod_assign_self) {
bigint n(100);
EXPECT_THROW(n.divmod_assign(n), assertion_failure);
}
-TEST(BigIntTest, DivModAssignUnaligned) {
+TEST(bigint_test, divmod_assign_unaligned) {
// (42 << 340) / pow(10, 100):
bigint n1(42);
n1 <<= 340;
@@ -162,7 +154,7 @@ TEST(BigIntTest, DivModAssignUnaligned) {
fmt::format("{}", n1));
}
-TEST(BigIntTest, DivModAssign) {
+TEST(bigint_test, divmod_assign) {
// 100 / 10:
bigint n1(100);
int result = n1.divmod_assign(bigint(10));
@@ -191,18 +183,18 @@ template <> void run_double_tests<true>() {
EXPECT_EQ(fp(1.23), fp(0x13ae147ae147aeu, -52));
}
-TEST(FPTest, DoubleTests) {
+TEST(fp_test, double_tests) {
run_double_tests<std::numeric_limits<double>::is_iec559>();
}
-TEST(FPTest, Normalize) {
+TEST(fp_test, normalize) {
const auto v = fp(0xbeef, 42);
auto normalized = normalize(v);
EXPECT_EQ(0xbeef000000000000, normalized.f);
EXPECT_EQ(-6, normalized.e);
}
-TEST(FPTest, Multiply) {
+TEST(fp_test, multiply) {
auto v = fp(123ULL << 32, 4) * fp(56ULL << 32, 7);
EXPECT_EQ(v.f, 123u * 56u);
EXPECT_EQ(v.e, 4 + 7 + 64);
@@ -211,7 +203,7 @@ TEST(FPTest, Multiply) {
EXPECT_EQ(v.e, 4 + 8 + 64);
}
-TEST(FPTest, GetCachedPower) {
+TEST(fp_test, get_cached_power) {
using limits = std::numeric_limits<double>;
for (auto exp = limits::min_exponent; exp <= limits::max_exponent; ++exp) {
int dec_exp = 0;
@@ -248,7 +240,7 @@ TEST(FPTest, GetCachedPower) {
}
}
-TEST(FPTest, DragonboxMaxK) {
+TEST(fp_test, dragonbox_max_k) {
using fmt::detail::dragonbox::floor_log10_pow2;
using float_info = fmt::detail::dragonbox::float_info<float>;
EXPECT_EQ(fmt::detail::const_check(float_info::max_k),
@@ -261,7 +253,7 @@ TEST(FPTest, DragonboxMaxK) {
double_info::significand_bits));
}
-TEST(FPTest, GetRoundDirection) {
+TEST(fp_test, get_round_direction) {
using fmt::detail::get_round_direction;
using fmt::detail::round_direction;
EXPECT_EQ(round_direction::down, get_round_direction(100, 50, 0));
@@ -285,108 +277,42 @@ TEST(FPTest, GetRoundDirection) {
EXPECT_EQ(round_direction::up, get_round_direction(max, max - 1, 1));
}
-TEST(FPTest, FixedHandler) {
- struct handler : fmt::detail::fixed_handler {
+TEST(fp_test, fixed_handler) {
+ struct handler : fmt::detail::gen_digits_handler {
char buffer[10];
- handler(int prec = 0) : fmt::detail::fixed_handler() {
+ handler(int prec = 0) : fmt::detail::gen_digits_handler() {
buf = buffer;
precision = prec;
}
};
- int exp = 0;
- handler().on_digit('0', 100, 99, 0, exp, false);
- EXPECT_THROW(handler().on_digit('0', 100, 100, 0, exp, false),
- assertion_failure);
+ handler().on_digit('0', 100, 99, 0, false);
+ EXPECT_THROW(handler().on_digit('0', 100, 100, 0, false), assertion_failure);
namespace digits = fmt::detail::digits;
- EXPECT_EQ(handler(1).on_digit('0', 100, 10, 10, exp, false), digits::error);
+ EXPECT_EQ(handler(1).on_digit('0', 100, 10, 10, false), digits::error);
// Check that divisor - error doesn't overflow.
- EXPECT_EQ(handler(1).on_digit('0', 100, 10, 101, exp, false), digits::error);
+ EXPECT_EQ(handler(1).on_digit('0', 100, 10, 101, false), digits::error);
// Check that 2 * error doesn't overflow.
uint64_t max = max_value<uint64_t>();
- EXPECT_EQ(handler(1).on_digit('0', max, 10, max - 1, exp, false),
- digits::error);
+ EXPECT_EQ(handler(1).on_digit('0', max, 10, max - 1, false), digits::error);
}
-TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) {
+TEST(fp_test, grisu_format_compiles_with_on_ieee_double) {
fmt::memory_buffer buf;
format_float(0.42, -1, fmt::detail::float_specs(), buf);
}
-template <typename T> struct value_extractor {
- T operator()(T value) { return value; }
-
- template <typename U> FMT_NORETURN T operator()(U) {
- throw std::runtime_error(fmt::format("invalid type {}", typeid(U).name()));
- }
-
-#if FMT_USE_INT128
- // Apple Clang does not define typeid for __int128_t and __uint128_t.
- FMT_NORETURN T operator()(fmt::detail::int128_t) {
- throw std::runtime_error("invalid type __int128_t");
- }
-
- FMT_NORETURN T operator()(fmt::detail::uint128_t) {
- throw std::runtime_error("invalid type __uint128_t");
- }
-#endif
-};
-
-TEST(FormatTest, ArgConverter) {
- long long value = max_value<long long>();
- auto arg = fmt::detail::make_arg<fmt::format_context>(value);
- fmt::visit_format_arg(
- fmt::detail::arg_converter<long long, fmt::format_context>(arg, 'd'),
- arg);
- EXPECT_EQ(value, fmt::visit_format_arg(value_extractor<long long>(), arg));
-}
-
-TEST(FormatTest, StrError) {
- char* message = nullptr;
- char buffer[BUFFER_SIZE];
- EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = nullptr, 0),
- "invalid buffer");
- EXPECT_ASSERT(fmt::detail::safe_strerror(EDOM, message = buffer, 0),
- "invalid buffer");
- buffer[0] = 'x';
-#if defined(_GNU_SOURCE) && !defined(__COVERITY__)
- // Use invalid error code to make sure that safe_strerror returns an error
- // message in the buffer rather than a pointer to a static string.
- int error_code = -1;
-#else
- int error_code = EDOM;
-#endif
-
- int result =
- fmt::detail::safe_strerror(error_code, message = buffer, BUFFER_SIZE);
- EXPECT_EQ(result, 0);
- size_t message_size = std::strlen(message);
- EXPECT_GE(BUFFER_SIZE - 1u, message_size);
- EXPECT_EQ(get_system_error(error_code), message);
-
- // safe_strerror never uses buffer on MinGW.
-#if !defined(__MINGW32__) && !defined(__sun)
- result =
- fmt::detail::safe_strerror(error_code, message = buffer, message_size);
- EXPECT_EQ(ERANGE, result);
- result = fmt::detail::safe_strerror(error_code, message = buffer, 1);
- EXPECT_EQ(buffer, message); // Message should point to buffer.
- EXPECT_EQ(ERANGE, result);
- EXPECT_STREQ("", message);
-#endif
-}
-
-TEST(FormatTest, FormatErrorCode) {
+TEST(format_impl_test, format_error_code) {
std::string msg = "error 42", sep = ": ";
{
fmt::memory_buffer buffer;
- format_to(buffer, "garbage");
+ format_to(fmt::appender(buffer), "garbage");
fmt::detail::format_error_code(buffer, 42, "test");
EXPECT_EQ("test: " + msg, to_string(buffer));
}
{
fmt::memory_buffer buffer;
- std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size() + 1,
- 'x');
+ auto prefix =
+ std::string(fmt::inline_buffer_size - msg.size() - sep.size() + 1, 'x');
fmt::detail::format_error_code(buffer, 42, prefix);
EXPECT_EQ(msg, to_string(buffer));
}
@@ -395,7 +321,8 @@ TEST(FormatTest, FormatErrorCode) {
// Test maximum buffer size.
msg = fmt::format("error {}", codes[i]);
fmt::memory_buffer buffer;
- std::string prefix(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
+ auto prefix =
+ std::string(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
fmt::detail::format_error_code(buffer, codes[i], prefix);
EXPECT_EQ(prefix + sep + msg, to_string(buffer));
size_t size = fmt::inline_buffer_size;
@@ -408,9 +335,9 @@ TEST(FormatTest, FormatErrorCode) {
}
}
-TEST(FormatTest, CountCodePoints) {
+TEST(format_impl_test, compute_width) {
EXPECT_EQ(4,
- fmt::detail::count_code_points(
+ fmt::detail::compute_width(
fmt::basic_string_view<fmt::detail::char8_type>(
reinterpret_cast<const fmt::detail::char8_type*>("ёжик"))));
}
@@ -425,12 +352,12 @@ template <typename Int> void test_count_digits() {
}
}
-TEST(UtilTest, CountDigits) {
+TEST(format_impl_test, count_digits) {
test_count_digits<uint32_t>();
test_count_digits<uint64_t>();
}
-TEST(UtilTest, WriteFallbackUIntPtr) {
+TEST(format_impl_test, write_fallback_uintptr) {
std::string s;
fmt::detail::write_ptr<char>(
std::back_inserter(s),
@@ -439,7 +366,11 @@ TEST(UtilTest, WriteFallbackUIntPtr) {
}
#ifdef _WIN32
-TEST(UtilTest, WriteConsoleSignature) {
+# include <windows.h>
+#endif
+
+#ifdef _WIN32
+TEST(format_impl_test, write_console_signature) {
decltype(WriteConsoleW)* p = fmt::detail::WriteConsoleW;
(void)p;
}
diff --git a/contrib/libs/fmt/test/format-test.cc b/contrib/libs/fmt/test/format-test.cc
index 6164ad60d6..a8592ef07e 100644
--- a/contrib/libs/fmt/test/format-test.cc
+++ b/contrib/libs/fmt/test/format-test.cc
@@ -5,111 +5,63 @@
//
// For the license information refer to format.h.
-#include <stdint.h>
-
-#include <cctype>
-#include <cfloat>
-#include <climits>
-#include <cmath>
-#include <cstring>
-#include <list>
-#include <memory>
-#include <string>
-
// Check if fmt/format.h compiles with windows.h included before it.
#ifdef _WIN32
# include <windows.h>
#endif
-
-// Check if fmt/format.h compiles with the X11 index macro defined.
-#define index(x, y) no nice things
-
+// clang-format off
#include "fmt/format.h"
+// clang-format on
-#undef index
+#include <stdint.h> // uint32_t
+
+#include <climits> // INT_MAX
+#include <cmath> // std::signbit
+#include <cstring> // std::strlen
+#include <iterator> // std::back_inserter
+#include <list> // std::list
+#include <memory> // std::unique_ptr
+#include <type_traits> // std::is_default_constructible
-#include <gmock/gmock.h>
#include "gtest-extra.h"
#include "mock-allocator.h"
#include "util.h"
-#undef ERROR
-
using fmt::basic_memory_buffer;
-using fmt::format;
using fmt::format_error;
using fmt::memory_buffer;
+using fmt::runtime;
using fmt::string_view;
-using fmt::wmemory_buffer;
-using fmt::wstring_view;
using fmt::detail::max_value;
using testing::Return;
using testing::StrictMock;
-namespace {
-
-#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 408
-template <typename Char, typename T> bool check_enabled_formatter() {
- static_assert(std::is_default_constructible<fmt::formatter<T, Char>>::value,
- "");
- return true;
-}
-
-template <typename Char, typename... T> void check_enabled_formatters() {
- auto dummy = {check_enabled_formatter<Char, T>()...};
- (void)dummy;
-}
-
-TEST(FormatterTest, TestFormattersEnabled) {
- check_enabled_formatters<char, bool, char, signed char, unsigned char, short,
- unsigned short, int, unsigned, long, unsigned long,
- long long, unsigned long long, float, double,
- long double, void*, const void*, char*, const char*,
- std::string, std::nullptr_t>();
- check_enabled_formatters<wchar_t, bool, wchar_t, signed char, unsigned char,
- short, unsigned short, int, unsigned, long,
- unsigned long, long long, unsigned long long, float,
- double, long double, void*, const void*, wchar_t*,
- const wchar_t*, std::wstring, std::nullptr_t>();
-}
-#endif
-
-// Format value using the standard library.
-template <typename Char, typename T>
-void std_format(const T& value, std::basic_string<Char>& result) {
- std::basic_ostringstream<Char> os;
- os << value;
- result = os.str();
-}
-
-#ifdef __MINGW32__
-// Workaround a bug in formatting long double in MinGW.
-void std_format(long double value, std::string& result) {
- char buffer[100];
- safe_sprintf(buffer, "%Lg", value);
- result = buffer;
-}
-void std_format(long double value, std::wstring& result) {
- wchar_t buffer[100];
- swprintf(buffer, L"%Lg", value);
- result = buffer;
-}
-#endif
-} // namespace
+enum { buffer_size = 256 };
struct uint32_pair {
uint32_t u[2];
};
-TEST(UtilTest, BitCast) {
+TEST(util_test, bit_cast) {
auto s = fmt::detail::bit_cast<uint32_pair>(uint64_t{42});
EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), 42ull);
- s = fmt::detail::bit_cast<uint32_pair>(uint64_t(~0ull));
+ s = fmt::detail::bit_cast<uint32_pair>(~uint64_t{0});
EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), ~0ull);
}
-TEST(UtilTest, Increment) {
+// Increment a number in a string.
+void increment(char* s) {
+ for (int i = static_cast<int>(std::strlen(s)) - 1; i >= 0; --i) {
+ if (s[i] != '9') {
+ ++s[i];
+ break;
+ }
+ s[i] = '0';
+ }
+}
+
+TEST(util_test, increment) {
char s[10] = "123";
increment(s);
EXPECT_STREQ("124", s);
@@ -123,92 +75,52 @@ TEST(UtilTest, Increment) {
EXPECT_STREQ("200", s);
}
-TEST(UtilTest, ParseNonnegativeInt) {
- if (max_value<int>() != static_cast<int>(static_cast<unsigned>(1) << 31)) {
- fmt::print("Skipping parse_nonnegative_int test\n");
- return;
- }
- fmt::string_view s = "10000000000";
+TEST(util_test, parse_nonnegative_int) {
+ auto s = fmt::string_view("10000000000");
auto begin = s.begin(), end = s.end();
- EXPECT_THROW_MSG(
- parse_nonnegative_int(begin, end, fmt::detail::error_handler()),
- fmt::format_error, "number is too big");
+ EXPECT_EQ(fmt::detail::parse_nonnegative_int(begin, end, -1), -1);
s = "2147483649";
begin = s.begin();
end = s.end();
- EXPECT_THROW_MSG(
- parse_nonnegative_int(begin, end, fmt::detail::error_handler()),
- fmt::format_error, "number is too big");
-}
-
-TEST(IteratorTest, CountingIterator) {
- fmt::detail::counting_iterator it;
- auto prev = it++;
- EXPECT_EQ(prev.count(), 0);
- EXPECT_EQ(it.count(), 1);
- EXPECT_EQ((it + 41).count(), 42);
-}
-
-TEST(IteratorTest, TruncatingIterator) {
- char* p = nullptr;
- fmt::detail::truncating_iterator<char*> it(p, 3);
- auto prev = it++;
- EXPECT_EQ(prev.base(), p);
- EXPECT_EQ(it.base(), p + 1);
-}
-
-TEST(IteratorTest, TruncatingBackInserter) {
- std::string buffer;
- auto bi = std::back_inserter(buffer);
- fmt::detail::truncating_iterator<decltype(bi)> it(bi, 2);
- *it++ = '4';
- *it++ = '2';
- *it++ = '1';
- EXPECT_EQ(buffer.size(), 2);
- EXPECT_EQ(buffer, "42");
-}
-
-TEST(IteratorTest, IsOutputIterator) {
- EXPECT_TRUE((fmt::detail::is_output_iterator<char*, char>::value));
- EXPECT_FALSE((fmt::detail::is_output_iterator<const char*, char>::value));
- EXPECT_FALSE((fmt::detail::is_output_iterator<std::string, char>::value));
- EXPECT_TRUE(
- (fmt::detail::is_output_iterator<std::back_insert_iterator<std::string>,
- char>::value));
- EXPECT_TRUE(
- (fmt::detail::is_output_iterator<std::string::iterator, char>::value));
- EXPECT_FALSE((fmt::detail::is_output_iterator<std::string::const_iterator,
- char>::value));
- EXPECT_FALSE((fmt::detail::is_output_iterator<std::list<char>, char>::value));
- EXPECT_TRUE((
- fmt::detail::is_output_iterator<std::list<char>::iterator, char>::value));
- EXPECT_FALSE((fmt::detail::is_output_iterator<std::list<char>::const_iterator,
- char>::value));
- EXPECT_FALSE((fmt::detail::is_output_iterator<uint32_pair, char>::value));
-}
-
-TEST(MemoryBufferTest, Ctor) {
- basic_memory_buffer<char, 123> buffer;
- EXPECT_EQ(static_cast<size_t>(0), buffer.size());
- EXPECT_EQ(123u, buffer.capacity());
+ EXPECT_EQ(fmt::detail::parse_nonnegative_int(begin, end, -1), -1);
}
-static void check_forwarding(mock_allocator<int>& alloc,
- allocator_ref<mock_allocator<int>>& ref) {
- int mem;
- // Check if value_type is properly defined.
- allocator_ref<mock_allocator<int>>::value_type* ptr = &mem;
- // Check forwarding.
- EXPECT_CALL(alloc, allocate(42)).WillOnce(testing::Return(ptr));
- ref.allocate(42);
- EXPECT_CALL(alloc, deallocate(ptr, 42));
- ref.deallocate(ptr, 42);
+TEST(util_test, utf8_to_utf16) {
+ auto u = fmt::detail::utf8_to_utf16("лошадка");
+ EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
+ EXPECT_EQ(7, u.size());
+ // U+10437 { DESERET SMALL LETTER YEE }
+ EXPECT_EQ(L"\xD801\xDC37", fmt::detail::utf8_to_utf16("𐐷").str());
+ EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16("\xc3\x28"), std::runtime_error,
+ "invalid utf8");
+ EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16(fmt::string_view("л", 1)),
+ std::runtime_error, "invalid utf8");
+ EXPECT_EQ(L"123456", fmt::detail::utf8_to_utf16("123456").str());
}
-TEST(AllocatorTest, allocator_ref) {
+TEST(util_test, utf8_to_utf16_empty_string) {
+ auto s = std::string();
+ auto u = fmt::detail::utf8_to_utf16(s.c_str());
+ EXPECT_EQ(L"", u.str());
+ EXPECT_EQ(s.size(), u.size());
+}
+
+TEST(util_test, allocator_ref) {
+ using test_allocator_ref = allocator_ref<mock_allocator<int>>;
+ auto check_forwarding = [](mock_allocator<int>& alloc,
+ test_allocator_ref& ref) {
+ int mem;
+ // Check if value_type is properly defined.
+ allocator_ref<mock_allocator<int>>::value_type* ptr = &mem;
+ // Check forwarding.
+ EXPECT_CALL(alloc, allocate(42)).WillOnce(Return(ptr));
+ ref.allocate(42);
+ EXPECT_CALL(alloc, deallocate(ptr, 42));
+ ref.deallocate(ptr, 42);
+ };
+
StrictMock<mock_allocator<int>> alloc;
- typedef allocator_ref<mock_allocator<int>> test_allocator_ref;
- test_allocator_ref ref(&alloc);
+ auto ref = test_allocator_ref(&alloc);
// Check if allocator_ref forwards to the underlying allocator.
check_forwarding(alloc, ref);
test_allocator_ref ref2(ref);
@@ -219,24 +131,78 @@ TEST(AllocatorTest, allocator_ref) {
check_forwarding(alloc, ref3);
}
-typedef allocator_ref<std::allocator<char>> TestAllocator;
+TEST(util_test, format_system_error) {
+ fmt::memory_buffer message;
+ fmt::format_system_error(message, EDOM, "test");
+ auto ec = std::error_code(EDOM, std::generic_category());
+ EXPECT_EQ(to_string(message), std::system_error(ec, "test").what());
+ message = fmt::memory_buffer();
-static void check_move_buffer(
- const char* str, basic_memory_buffer<char, 5, TestAllocator>& buffer) {
- std::allocator<char>* alloc = buffer.get_allocator().get();
- basic_memory_buffer<char, 5, TestAllocator> buffer2(std::move(buffer));
- // Move shouldn't destroy the inline content of the first buffer.
- EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
- EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
- EXPECT_EQ(5u, buffer2.capacity());
- // Move should transfer allocator.
- EXPECT_EQ(nullptr, buffer.get_allocator().get());
- EXPECT_EQ(alloc, buffer2.get_allocator().get());
+ // Check if std::allocator throws on allocating max size_t / 2 chars.
+ size_t max_size = max_value<size_t>() / 2;
+ bool throws_on_alloc = false;
+ try {
+ auto alloc = std::allocator<char>();
+ alloc.deallocate(alloc.allocate(max_size), max_size);
+ } catch (const std::bad_alloc&) {
+ throws_on_alloc = true;
+ }
+ if (!throws_on_alloc) {
+ fmt::print("warning: std::allocator allocates {} chars", max_size);
+ return;
+ }
}
-TEST(MemoryBufferTest, MoveCtorInlineBuffer) {
- std::allocator<char> alloc;
- basic_memory_buffer<char, 5, TestAllocator> buffer((TestAllocator(&alloc)));
+TEST(util_test, system_error) {
+ auto test_error = fmt::system_error(EDOM, "test");
+ auto ec = std::error_code(EDOM, std::generic_category());
+ EXPECT_STREQ(test_error.what(), std::system_error(ec, "test").what());
+ EXPECT_EQ(test_error.code(), ec);
+
+ auto error = std::system_error(std::error_code());
+ try {
+ throw fmt::system_error(EDOM, "test {}", "error");
+ } catch (const std::system_error& e) {
+ error = e;
+ }
+ fmt::memory_buffer message;
+ fmt::format_system_error(message, EDOM, "test error");
+ EXPECT_EQ(error.what(), to_string(message));
+ EXPECT_EQ(error.code(), std::error_code(EDOM, std::generic_category()));
+}
+
+TEST(util_test, report_system_error) {
+ fmt::memory_buffer out;
+ fmt::format_system_error(out, EDOM, "test error");
+ out.push_back('\n');
+ EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"),
+ to_string(out));
+}
+
+TEST(memory_buffer_test, ctor) {
+ basic_memory_buffer<char, 123> buffer;
+ EXPECT_EQ(static_cast<size_t>(0), buffer.size());
+ EXPECT_EQ(123u, buffer.capacity());
+}
+
+using std_allocator = allocator_ref<std::allocator<char>>;
+
+TEST(memory_buffer_test, move_ctor_inline_buffer) {
+ auto check_move_buffer =
+ [](const char* str, basic_memory_buffer<char, 5, std_allocator>& buffer) {
+ std::allocator<char>* alloc = buffer.get_allocator().get();
+ basic_memory_buffer<char, 5, std_allocator> buffer2(std::move(buffer));
+ // Move shouldn't destroy the inline content of the first buffer.
+ EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
+ EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
+ EXPECT_EQ(5u, buffer2.capacity());
+ // Move should transfer allocator.
+ EXPECT_EQ(nullptr, buffer.get_allocator().get());
+ EXPECT_EQ(alloc, buffer2.get_allocator().get());
+ };
+
+ auto alloc = std::allocator<char>();
+ basic_memory_buffer<char, 5, std_allocator> buffer((std_allocator(&alloc)));
const char test[] = "test";
buffer.append(string_view(test, 4));
check_move_buffer("test", buffer);
@@ -246,24 +212,24 @@ TEST(MemoryBufferTest, MoveCtorInlineBuffer) {
check_move_buffer("testa", buffer);
}
-TEST(MemoryBufferTest, MoveCtorDynamicBuffer) {
- std::allocator<char> alloc;
- basic_memory_buffer<char, 4, TestAllocator> buffer((TestAllocator(&alloc)));
+TEST(memory_buffer_test, move_ctor_dynamic_buffer) {
+ auto alloc = std::allocator<char>();
+ basic_memory_buffer<char, 4, std_allocator> buffer((std_allocator(&alloc)));
const char test[] = "test";
buffer.append(test, test + 4);
const char* inline_buffer_ptr = &buffer[0];
// Adding one more character causes the content to move from the inline to
// a dynamically allocated buffer.
buffer.push_back('a');
- basic_memory_buffer<char, 4, TestAllocator> buffer2(std::move(buffer));
+ basic_memory_buffer<char, 4, std_allocator> buffer2(std::move(buffer));
// Move should rip the guts of the first buffer.
EXPECT_EQ(inline_buffer_ptr, &buffer[0]);
EXPECT_EQ("testa", std::string(&buffer2[0], buffer2.size()));
EXPECT_GT(buffer2.capacity(), 4u);
}
-static void check_move_assign_buffer(const char* str,
- basic_memory_buffer<char, 5>& buffer) {
+void check_move_assign_buffer(const char* str,
+ basic_memory_buffer<char, 5>& buffer) {
basic_memory_buffer<char, 5> buffer2;
buffer2 = std::move(buffer);
// Move shouldn't destroy the inline content of the first buffer.
@@ -272,7 +238,7 @@ static void check_move_assign_buffer(const char* str,
EXPECT_EQ(5u, buffer2.capacity());
}
-TEST(MemoryBufferTest, MoveAssignment) {
+TEST(memory_buffer_test, move_assignment) {
basic_memory_buffer<char, 5> buffer;
const char test[] = "test";
buffer.append(test, test + 4);
@@ -293,7 +259,7 @@ TEST(MemoryBufferTest, MoveAssignment) {
EXPECT_GT(buffer2.capacity(), 5u);
}
-TEST(MemoryBufferTest, Grow) {
+TEST(memory_buffer_test, grow) {
typedef allocator_ref<mock_allocator<int>> Allocator;
mock_allocator<int> alloc;
basic_memory_buffer<int, 10, Allocator> buffer((Allocator(&alloc)));
@@ -313,15 +279,15 @@ TEST(MemoryBufferTest, Grow) {
EXPECT_CALL(alloc, deallocate(mem, 20));
}
-TEST(MemoryBufferTest, Allocator) {
- typedef allocator_ref<mock_allocator<char>> TestAllocator;
- basic_memory_buffer<char, 10, TestAllocator> buffer;
+TEST(memory_buffer_test, allocator) {
+ using test_allocator = allocator_ref<mock_allocator<char>>;
+ basic_memory_buffer<char, 10, test_allocator> buffer;
EXPECT_EQ(nullptr, buffer.get_allocator().get());
StrictMock<mock_allocator<char>> alloc;
char mem;
{
- basic_memory_buffer<char, 10, TestAllocator> buffer2(
- (TestAllocator(&alloc)));
+ basic_memory_buffer<char, 10, test_allocator> buffer2(
+ (test_allocator(&alloc)));
EXPECT_EQ(&alloc, buffer2.get_allocator().get());
size_t size = 2 * fmt::inline_buffer_size;
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem));
@@ -330,21 +296,22 @@ TEST(MemoryBufferTest, Allocator) {
}
}
-TEST(MemoryBufferTest, ExceptionInDeallocate) {
- typedef allocator_ref<mock_allocator<char>> TestAllocator;
+TEST(memory_buffer_test, exception_in_deallocate) {
+ using test_allocator = allocator_ref<mock_allocator<char>>;
StrictMock<mock_allocator<char>> alloc;
- basic_memory_buffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc)));
+ basic_memory_buffer<char, 10, test_allocator> buffer(
+ (test_allocator(&alloc)));
size_t size = 2 * fmt::inline_buffer_size;
- std::vector<char> mem(size);
+ auto mem = std::vector<char>(size);
{
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0]));
buffer.resize(size);
std::fill(&buffer[0], &buffer[0] + size, 'x');
}
- std::vector<char> mem2(2 * size);
+ auto mem2 = std::vector<char>(2 * size);
{
EXPECT_CALL(alloc, allocate(2 * size)).WillOnce(Return(&mem2[0]));
- std::exception e;
+ auto e = std::exception();
EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e));
EXPECT_THROW(buffer.reserve(2 * size), std::exception);
EXPECT_EQ(&mem2[0], &buffer[0]);
@@ -354,595 +321,576 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
}
-TEST(UtilTest, UTF8ToUTF16) {
- fmt::detail::utf8_to_utf16 u("лошадка");
- EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
- EXPECT_EQ(7, u.size());
- // U+10437 { DESERET SMALL LETTER YEE }
- EXPECT_EQ(L"\xD801\xDC37", fmt::detail::utf8_to_utf16("𐐷").str());
- EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16("\xc3\x28"), std::runtime_error,
- "invalid utf8");
- EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16(fmt::string_view("л", 1)),
- std::runtime_error, "invalid utf8");
- EXPECT_EQ(L"123456", fmt::detail::utf8_to_utf16("123456").str());
-}
-
-TEST(UtilTest, UTF8ToUTF16EmptyString) {
- std::string s = "";
- fmt::detail::utf8_to_utf16 u(s.c_str());
- EXPECT_EQ(L"", u.str());
- EXPECT_EQ(s.size(), u.size());
-}
-
-TEST(UtilTest, FormatSystemError) {
- fmt::memory_buffer message;
- fmt::format_system_error(message, EDOM, "test");
- EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)),
- to_string(message));
- message = fmt::memory_buffer();
-
- // Check if std::allocator throws on allocating max size_t / 2 chars.
- size_t max_size = max_value<size_t>() / 2;
- bool throws_on_alloc = false;
- try {
- std::allocator<char> alloc;
- alloc.deallocate(alloc.allocate(max_size), max_size);
- } catch (const std::bad_alloc&) {
- throws_on_alloc = true;
- }
- if (!throws_on_alloc) {
- fmt::print("warning: std::allocator allocates {} chars", max_size);
- return;
+template <typename Allocator, size_t MaxSize>
+class max_size_allocator : public Allocator {
+ public:
+ using typename Allocator::value_type;
+ size_t max_size() const FMT_NOEXCEPT { return MaxSize; }
+ value_type* allocate(size_t n) {
+ if (n > max_size()) {
+ throw std::length_error("size > max_size");
+ }
+ return std::allocator_traits<Allocator>::allocate(
+ *static_cast<Allocator*>(this), n);
}
- fmt::format_system_error(message, EDOM, fmt::string_view(nullptr, max_size));
- EXPECT_EQ(fmt::format("error {}", EDOM), to_string(message));
-}
-
-TEST(UtilTest, SystemError) {
- fmt::system_error e(EDOM, "test");
- EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), e.what());
- EXPECT_EQ(EDOM, e.error_code());
-
- fmt::system_error error(0, "");
- try {
- throw fmt::system_error(EDOM, "test {}", "error");
- } catch (const fmt::system_error& e) {
- error = e;
+ void deallocate(value_type* p, size_t n) {
+ std::allocator_traits<Allocator>::deallocate(*static_cast<Allocator*>(this),
+ p, n);
}
- fmt::memory_buffer message;
- fmt::format_system_error(message, EDOM, "test error");
- EXPECT_EQ(to_string(message), error.what());
- EXPECT_EQ(EDOM, error.error_code());
-}
-
-TEST(UtilTest, ReportSystemError) {
- fmt::memory_buffer out;
- fmt::format_system_error(out, EDOM, "test error");
- out.push_back('\n');
- EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"),
- to_string(out));
-}
-
-TEST(StringViewTest, Ctor) {
- EXPECT_STREQ("abc", string_view("abc").data());
- EXPECT_EQ(3u, string_view("abc").size());
-
- EXPECT_STREQ("defg", string_view(std::string("defg")).data());
- EXPECT_EQ(4u, string_view(std::string("defg")).size());
-}
-
-TEST(FormatToTest, FormatWithoutArgs) {
- std::string s;
- fmt::format_to(std::back_inserter(s), "test");
- EXPECT_EQ("test", s);
-}
-
-TEST(FormatToTest, Format) {
- std::string s;
- fmt::format_to(std::back_inserter(s), "part{0}", 1);
- EXPECT_EQ("part1", s);
- fmt::format_to(std::back_inserter(s), "part{0}", 2);
- EXPECT_EQ("part1part2", s);
-}
+};
-TEST(FormatToTest, WideString) {
- std::vector<wchar_t> buf;
- fmt::format_to(std::back_inserter(buf), L"{}{}", 42, L'\0');
- EXPECT_STREQ(buf.data(), L"42");
+TEST(memory_buffer_test, max_size_allocator) {
+ // 160 = 128 + 32
+ using test_allocator = max_size_allocator<std::allocator<char>, 160>;
+ basic_memory_buffer<char, 10, test_allocator> buffer;
+ buffer.resize(128);
+ // new_capacity = 128 + 128/2 = 192 > 160
+ buffer.resize(160); // Shouldn't throw.
}
-TEST(FormatToTest, FormatToMemoryBuffer) {
- fmt::basic_memory_buffer<char, 100> buffer;
- fmt::format_to(buffer, "{}", "foo");
- EXPECT_EQ("foo", to_string(buffer));
- fmt::wmemory_buffer wbuffer;
- fmt::format_to(wbuffer, L"{}", L"foo");
- EXPECT_EQ(L"foo", to_string(wbuffer));
+TEST(memory_buffer_test, max_size_allocator_overflow) {
+ using test_allocator = max_size_allocator<std::allocator<char>, 160>;
+ basic_memory_buffer<char, 10, test_allocator> buffer;
+ EXPECT_THROW(buffer.resize(161), std::exception);
}
-TEST(FormatterTest, Escape) {
- EXPECT_EQ("{", format("{{"));
- EXPECT_EQ("before {", format("before {{"));
- EXPECT_EQ("{ after", format("{{ after"));
- EXPECT_EQ("before { after", format("before {{ after"));
+TEST(format_test, escape) {
+ EXPECT_EQ("{", fmt::format("{{"));
+ EXPECT_EQ("before {", fmt::format("before {{"));
+ EXPECT_EQ("{ after", fmt::format("{{ after"));
+ EXPECT_EQ("before { after", fmt::format("before {{ after"));
- EXPECT_EQ("}", format("}}"));
- EXPECT_EQ("before }", format("before }}"));
- EXPECT_EQ("} after", format("}} after"));
- EXPECT_EQ("before } after", format("before }} after"));
+ EXPECT_EQ("}", fmt::format("}}"));
+ EXPECT_EQ("before }", fmt::format("before }}"));
+ EXPECT_EQ("} after", fmt::format("}} after"));
+ EXPECT_EQ("before } after", fmt::format("before }} after"));
- EXPECT_EQ("{}", format("{{}}"));
- EXPECT_EQ("{42}", format("{{{0}}}", 42));
+ EXPECT_EQ("{}", fmt::format("{{}}"));
+ EXPECT_EQ("{42}", fmt::format("{{{0}}}", 42));
}
-TEST(FormatterTest, UnmatchedBraces) {
- EXPECT_THROW_MSG(format("{"), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("}"), format_error, "unmatched '}' in format string");
- EXPECT_THROW_MSG(format("{0{}"), format_error, "invalid format string");
+TEST(format_test, unmatched_braces) {
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{")), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("}")), format_error,
+ "unmatched '}' in format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0{}")), format_error,
+ "invalid format string");
}
-TEST(FormatterTest, NoArgs) { EXPECT_EQ("test", format("test")); }
+TEST(format_test, no_args) { EXPECT_EQ("test", fmt::format("test")); }
-TEST(FormatterTest, ArgsInDifferentPositions) {
- EXPECT_EQ("42", format("{0}", 42));
- EXPECT_EQ("before 42", format("before {0}", 42));
- EXPECT_EQ("42 after", format("{0} after", 42));
- EXPECT_EQ("before 42 after", format("before {0} after", 42));
- EXPECT_EQ("answer = 42", format("{0} = {1}", "answer", 42));
- EXPECT_EQ("42 is the answer", format("{1} is the {0}", "answer", 42));
- EXPECT_EQ("abracadabra", format("{0}{1}{0}", "abra", "cad"));
+TEST(format_test, args_in_different_positions) {
+ EXPECT_EQ("42", fmt::format("{0}", 42));
+ EXPECT_EQ("before 42", fmt::format("before {0}", 42));
+ EXPECT_EQ("42 after", fmt::format("{0} after", 42));
+ EXPECT_EQ("before 42 after", fmt::format("before {0} after", 42));
+ EXPECT_EQ("answer = 42", fmt::format("{0} = {1}", "answer", 42));
+ EXPECT_EQ("42 is the answer", fmt::format("{1} is the {0}", "answer", 42));
+ EXPECT_EQ("abracadabra", fmt::format("{0}{1}{0}", "abra", "cad"));
}
-TEST(FormatterTest, ArgErrors) {
- EXPECT_THROW_MSG(format("{"), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("{?}"), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("{0"), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("{0}"), format_error, "argument not found");
- EXPECT_THROW_MSG(format("{00}", 42), format_error, "invalid format string");
+TEST(format_test, arg_errors) {
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{")), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{?}")), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0")), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0}")), format_error,
+ "argument not found");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{00}"), 42), format_error,
+ "invalid format string");
- char format_str[BUFFER_SIZE];
+ char format_str[buffer_size];
safe_sprintf(format_str, "{%u", INT_MAX);
- EXPECT_THROW_MSG(format(format_str), format_error, "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str)), format_error,
+ "invalid format string");
safe_sprintf(format_str, "{%u}", INT_MAX);
- EXPECT_THROW_MSG(format(format_str), format_error, "argument not found");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str)), format_error,
+ "argument not found");
safe_sprintf(format_str, "{%u", INT_MAX + 1u);
- EXPECT_THROW_MSG(format(format_str), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str)), format_error,
+ "invalid format string");
safe_sprintf(format_str, "{%u}", INT_MAX + 1u);
- EXPECT_THROW_MSG(format(format_str), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str)), format_error,
+ "argument not found");
}
-template <int N> struct TestFormat {
- template <typename... Args>
- static std::string format(fmt::string_view format_str, const Args&... args) {
- return TestFormat<N - 1>::format(format_str, N - 1, args...);
+template <int N> struct test_format {
+ template <typename... T>
+ static std::string format(fmt::string_view fmt, const T&... args) {
+ return test_format<N - 1>::format(fmt, N - 1, args...);
}
};
-template <> struct TestFormat<0> {
- template <typename... Args>
- static std::string format(fmt::string_view format_str, const Args&... args) {
- return fmt::format(format_str, args...);
+template <> struct test_format<0> {
+ template <typename... T>
+ static std::string format(fmt::string_view fmt, const T&... args) {
+ return fmt::format(runtime(fmt), args...);
}
};
-TEST(FormatterTest, ManyArgs) {
- EXPECT_EQ("19", TestFormat<20>::format("{19}"));
- EXPECT_THROW_MSG(TestFormat<20>::format("{20}"), format_error,
+TEST(format_test, many_args) {
+ EXPECT_EQ("19", test_format<20>::format("{19}"));
+ EXPECT_THROW_MSG(test_format<20>::format("{20}"), format_error,
"argument not found");
- EXPECT_THROW_MSG(TestFormat<21>::format("{21}"), format_error,
+ EXPECT_THROW_MSG(test_format<21>::format("{21}"), format_error,
"argument not found");
- enum { max_packed_args = fmt::detail::max_packed_args };
+ using fmt::detail::max_packed_args;
std::string format_str = fmt::format("{{{}}}", max_packed_args + 1);
- EXPECT_THROW_MSG(TestFormat<max_packed_args>::format(format_str),
+ EXPECT_THROW_MSG(test_format<max_packed_args>::format(format_str),
format_error, "argument not found");
}
-TEST(FormatterTest, NamedArg) {
- EXPECT_EQ("1/a/A", format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'),
- fmt::arg("A_", "A"), fmt::arg("_1", 1)));
- EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
- EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
- EXPECT_EQ("1 2", format("{} {two}", 1, fmt::arg("two", 2)));
- EXPECT_EQ("42", format("{c}", fmt::arg("a", 0), fmt::arg("b", 0),
- fmt::arg("c", 42), fmt::arg("d", 0), fmt::arg("e", 0),
- fmt::arg("f", 0), fmt::arg("g", 0), fmt::arg("h", 0),
- fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0),
- fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0),
- fmt::arg("o", 0), fmt::arg("p", 0)));
- EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found");
- EXPECT_THROW_MSG(format("{a}", 42), format_error, "argument not found");
-}
-
-TEST(FormatterTest, AutoArgIndex) {
- EXPECT_EQ("abc", format("{}{}{}", 'a', 'b', 'c'));
- EXPECT_THROW_MSG(format("{0}{}", 'a', 'b'), format_error,
+TEST(format_test, named_arg) {
+ EXPECT_EQ("1/a/A", fmt::format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'),
+ fmt::arg("A_", "A"), fmt::arg("_1", 1)));
+ EXPECT_EQ(" -42", fmt::format("{0:{width}}", -42, fmt::arg("width", 4)));
+ EXPECT_EQ("st",
+ fmt::format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
+ EXPECT_EQ("1 2", fmt::format("{} {two}", 1, fmt::arg("two", 2)));
+ EXPECT_EQ("42",
+ fmt::format("{c}", fmt::arg("a", 0), fmt::arg("b", 0),
+ fmt::arg("c", 42), fmt::arg("d", 0), fmt::arg("e", 0),
+ fmt::arg("f", 0), fmt::arg("g", 0), fmt::arg("h", 0),
+ fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0),
+ fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0),
+ fmt::arg("o", 0), fmt::arg("p", 0)));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{a}")), format_error,
+ "argument not found");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{a}"), 42), format_error,
+ "argument not found");
+}
+
+TEST(format_test, auto_arg_index) {
+ EXPECT_EQ("abc", fmt::format("{}{}{}", 'a', 'b', 'c'));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0}{}"), 'a', 'b'), format_error,
"cannot switch from manual to automatic argument indexing");
- EXPECT_THROW_MSG(format("{}{0}", 'a', 'b'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{}{0}"), 'a', 'b'), format_error,
"cannot switch from automatic to manual argument indexing");
- EXPECT_EQ("1.2", format("{:.{}}", 1.2345, 2));
- EXPECT_THROW_MSG(format("{0}:.{}", 1.2345, 2), format_error,
+ EXPECT_EQ("1.2", fmt::format("{:.{}}", 1.2345, 2));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0}:.{}"), 1.2345, 2),
+ format_error,
"cannot switch from manual to automatic argument indexing");
- EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:.{0}}"), 1.2345, 2),
+ format_error,
"cannot switch from automatic to manual argument indexing");
- EXPECT_THROW_MSG(format("{}"), format_error, "argument not found");
-}
-
-TEST(FormatterTest, EmptySpecs) { EXPECT_EQ("42", format("{0:}", 42)); }
-
-TEST(FormatterTest, LeftAlign) {
- EXPECT_EQ("42 ", format("{0:<4}", 42));
- EXPECT_EQ("42 ", format("{0:<4o}", 042));
- EXPECT_EQ("42 ", format("{0:<4x}", 0x42));
- EXPECT_EQ("-42 ", format("{0:<5}", -42));
- EXPECT_EQ("42 ", format("{0:<5}", 42u));
- EXPECT_EQ("-42 ", format("{0:<5}", -42l));
- EXPECT_EQ("42 ", format("{0:<5}", 42ul));
- EXPECT_EQ("-42 ", format("{0:<5}", -42ll));
- EXPECT_EQ("42 ", format("{0:<5}", 42ull));
- EXPECT_EQ("-42 ", format("{0:<5}", -42.0));
- EXPECT_EQ("-42 ", format("{0:<5}", -42.0l));
- EXPECT_EQ("c ", format("{0:<5}", 'c'));
- EXPECT_EQ("abc ", format("{0:<5}", "abc"));
- EXPECT_EQ("0xface ", format("{0:<8}", reinterpret_cast<void*>(0xface)));
-}
-
-TEST(FormatterTest, RightAlign) {
- EXPECT_EQ(" 42", format("{0:>4}", 42));
- EXPECT_EQ(" 42", format("{0:>4o}", 042));
- EXPECT_EQ(" 42", format("{0:>4x}", 0x42));
- EXPECT_EQ(" -42", format("{0:>5}", -42));
- EXPECT_EQ(" 42", format("{0:>5}", 42u));
- EXPECT_EQ(" -42", format("{0:>5}", -42l));
- EXPECT_EQ(" 42", format("{0:>5}", 42ul));
- EXPECT_EQ(" -42", format("{0:>5}", -42ll));
- EXPECT_EQ(" 42", format("{0:>5}", 42ull));
- EXPECT_EQ(" -42", format("{0:>5}", -42.0));
- EXPECT_EQ(" -42", format("{0:>5}", -42.0l));
- EXPECT_EQ(" c", format("{0:>5}", 'c'));
- EXPECT_EQ(" abc", format("{0:>5}", "abc"));
- EXPECT_EQ(" 0xface", format("{0:>8}", reinterpret_cast<void*>(0xface)));
-}
-
-#if FMT_DEPRECATED_NUMERIC_ALIGN
-TEST(FormatterTest, NumericAlign) { EXPECT_EQ("0042", format("{0:=4}", 42)); }
-#endif
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{}")), format_error,
+ "argument not found");
+}
-TEST(FormatterTest, CenterAlign) {
- EXPECT_EQ(" 42 ", format("{0:^5}", 42));
- EXPECT_EQ(" 42 ", format("{0:^5o}", 042));
- EXPECT_EQ(" 42 ", format("{0:^5x}", 0x42));
- EXPECT_EQ(" -42 ", format("{0:^5}", -42));
- EXPECT_EQ(" 42 ", format("{0:^5}", 42u));
- EXPECT_EQ(" -42 ", format("{0:^5}", -42l));
- EXPECT_EQ(" 42 ", format("{0:^5}", 42ul));
- EXPECT_EQ(" -42 ", format("{0:^5}", -42ll));
- EXPECT_EQ(" 42 ", format("{0:^5}", 42ull));
- EXPECT_EQ(" -42 ", format("{0:^5}", -42.0));
- EXPECT_EQ(" -42 ", format("{0:^5}", -42.0l));
- EXPECT_EQ(" c ", format("{0:^5}", 'c'));
- EXPECT_EQ(" abc ", format("{0:^6}", "abc"));
- EXPECT_EQ(" 0xface ", format("{0:^8}", reinterpret_cast<void*>(0xface)));
-}
-
-TEST(FormatterTest, Fill) {
- EXPECT_THROW_MSG(format("{0:{<5}", 'c'), format_error,
+TEST(format_test, empty_specs) { EXPECT_EQ("42", fmt::format("{0:}", 42)); }
+
+TEST(format_test, left_align) {
+ EXPECT_EQ("42 ", fmt::format("{0:<4}", 42));
+ EXPECT_EQ("42 ", fmt::format("{0:<4o}", 042));
+ EXPECT_EQ("42 ", fmt::format("{0:<4x}", 0x42));
+ EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42));
+ EXPECT_EQ("42 ", fmt::format("{0:<5}", 42u));
+ EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42l));
+ EXPECT_EQ("42 ", fmt::format("{0:<5}", 42ul));
+ EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42ll));
+ EXPECT_EQ("42 ", fmt::format("{0:<5}", 42ull));
+ EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42.0));
+ EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42.0l));
+ EXPECT_EQ("c ", fmt::format("{0:<5}", 'c'));
+ EXPECT_EQ("abc ", fmt::format("{0:<5}", "abc"));
+ EXPECT_EQ("0xface ", fmt::format("{0:<8}", reinterpret_cast<void*>(0xface)));
+}
+
+TEST(format_test, right_align) {
+ EXPECT_EQ(" 42", fmt::format("{0:>4}", 42));
+ EXPECT_EQ(" 42", fmt::format("{0:>4o}", 042));
+ EXPECT_EQ(" 42", fmt::format("{0:>4x}", 0x42));
+ EXPECT_EQ(" -42", fmt::format("{0:>5}", -42));
+ EXPECT_EQ(" 42", fmt::format("{0:>5}", 42u));
+ EXPECT_EQ(" -42", fmt::format("{0:>5}", -42l));
+ EXPECT_EQ(" 42", fmt::format("{0:>5}", 42ul));
+ EXPECT_EQ(" -42", fmt::format("{0:>5}", -42ll));
+ EXPECT_EQ(" 42", fmt::format("{0:>5}", 42ull));
+ EXPECT_EQ(" -42", fmt::format("{0:>5}", -42.0));
+ EXPECT_EQ(" -42", fmt::format("{0:>5}", -42.0l));
+ EXPECT_EQ(" c", fmt::format("{0:>5}", 'c'));
+ EXPECT_EQ(" abc", fmt::format("{0:>5}", "abc"));
+ EXPECT_EQ(" 0xface", fmt::format("{0:>8}", reinterpret_cast<void*>(0xface)));
+}
+
+TEST(format_test, center_align) {
+ EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42));
+ EXPECT_EQ(" 42 ", fmt::format("{0:^5o}", 042));
+ EXPECT_EQ(" 42 ", fmt::format("{0:^5x}", 0x42));
+ EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42));
+ EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42u));
+ EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42l));
+ EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42ul));
+ EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42ll));
+ EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42ull));
+ EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42.0));
+ EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42.0l));
+ EXPECT_EQ(" c ", fmt::format("{0:^5}", 'c'));
+ EXPECT_EQ(" abc ", fmt::format("{0:^6}", "abc"));
+ EXPECT_EQ(" 0xface ", fmt::format("{0:^8}", reinterpret_cast<void*>(0xface)));
+}
+
+TEST(format_test, fill) {
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{<5}"), 'c'), format_error,
"invalid fill character '{'");
- EXPECT_THROW_MSG(format("{0:{<5}}", 'c'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{<5}}"), 'c'), format_error,
"invalid fill character '{'");
- EXPECT_EQ("**42", format("{0:*>4}", 42));
- EXPECT_EQ("**-42", format("{0:*>5}", -42));
- EXPECT_EQ("***42", format("{0:*>5}", 42u));
- EXPECT_EQ("**-42", format("{0:*>5}", -42l));
- EXPECT_EQ("***42", format("{0:*>5}", 42ul));
- EXPECT_EQ("**-42", format("{0:*>5}", -42ll));
- EXPECT_EQ("***42", format("{0:*>5}", 42ull));
- EXPECT_EQ("**-42", format("{0:*>5}", -42.0));
- EXPECT_EQ("**-42", format("{0:*>5}", -42.0l));
- EXPECT_EQ("c****", format("{0:*<5}", 'c'));
- EXPECT_EQ("abc**", format("{0:*<5}", "abc"));
- EXPECT_EQ("**0xface", format("{0:*>8}", reinterpret_cast<void*>(0xface)));
- EXPECT_EQ("foo=", format("{:}=", "foo"));
- EXPECT_EQ(std::string("\0\0\0*", 4), format(string_view("{:\0>4}", 6), '*'));
- EXPECT_EQ("жж42", format("{0:ж>4}", 42));
- EXPECT_THROW_MSG(format("{:\x80\x80\x80\x80\x80>}", 0), format_error,
- "missing '}' in format string");
-}
-
-TEST(FormatterTest, PlusSign) {
- EXPECT_EQ("+42", format("{0:+}", 42));
- EXPECT_EQ("-42", format("{0:+}", -42));
- EXPECT_EQ("+42", format("{0:+}", 42));
- EXPECT_THROW_MSG(format("{0:+}", 42u), format_error,
+ EXPECT_EQ("**42", fmt::format("{0:*>4}", 42));
+ EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42));
+ EXPECT_EQ("***42", fmt::format("{0:*>5}", 42u));
+ EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42l));
+ EXPECT_EQ("***42", fmt::format("{0:*>5}", 42ul));
+ EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42ll));
+ EXPECT_EQ("***42", fmt::format("{0:*>5}", 42ull));
+ EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42.0));
+ EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42.0l));
+ EXPECT_EQ("c****", fmt::format("{0:*<5}", 'c'));
+ EXPECT_EQ("abc**", fmt::format("{0:*<5}", "abc"));
+ EXPECT_EQ("**0xface",
+ fmt::format("{0:*>8}", reinterpret_cast<void*>(0xface)));
+ EXPECT_EQ("foo=", fmt::format("{:}=", "foo"));
+ EXPECT_EQ(std::string("\0\0\0*", 4),
+ fmt::format(string_view("{:\0>4}", 6), '*'));
+ EXPECT_EQ("жж42", fmt::format("{0:ж>4}", 42));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:\x80\x80\x80\x80\x80>}"), 0),
+ format_error, "invalid type specifier");
+}
+
+TEST(format_test, plus_sign) {
+ EXPECT_EQ("+42", fmt::format("{0:+}", 42));
+ EXPECT_EQ("-42", fmt::format("{0:+}", -42));
+ EXPECT_EQ("+42", fmt::format("{0:+}", 42));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), 42u), format_error,
"format specifier requires signed argument");
- EXPECT_EQ("+42", format("{0:+}", 42l));
- EXPECT_THROW_MSG(format("{0:+}", 42ul), format_error,
+ EXPECT_EQ("+42", fmt::format("{0:+}", 42l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), 42ul), format_error,
"format specifier requires signed argument");
- EXPECT_EQ("+42", format("{0:+}", 42ll));
- EXPECT_THROW_MSG(format("{0:+}", 42ull), format_error,
+ EXPECT_EQ("+42", fmt::format("{0:+}", 42ll));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), 42ull), format_error,
"format specifier requires signed argument");
- EXPECT_EQ("+42", format("{0:+}", 42.0));
- EXPECT_EQ("+42", format("{0:+}", 42.0l));
- EXPECT_THROW_MSG(format("{0:+", 'c'), format_error,
+ EXPECT_EQ("+42", fmt::format("{0:+}", 42.0));
+ EXPECT_EQ("+42", fmt::format("{0:+}", 42.0l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+"), 'c'), format_error,
"missing '}' in format string");
- EXPECT_THROW_MSG(format("{0:+}", 'c'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), 'c'), format_error,
"invalid format specifier for char");
- EXPECT_THROW_MSG(format("{0:+}", "abc"), format_error,
- "format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:+}", reinterpret_cast<void*>(0x42)), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), "abc"), format_error,
"format specifier requires numeric argument");
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0:+}"), reinterpret_cast<void*>(0x42)),
+ format_error, "format specifier requires numeric argument");
}
-TEST(FormatterTest, MinusSign) {
- EXPECT_EQ("42", format("{0:-}", 42));
- EXPECT_EQ("-42", format("{0:-}", -42));
- EXPECT_EQ("42", format("{0:-}", 42));
- EXPECT_THROW_MSG(format("{0:-}", 42u), format_error,
+TEST(format_test, minus_sign) {
+ EXPECT_EQ("42", fmt::format("{0:-}", 42));
+ EXPECT_EQ("-42", fmt::format("{0:-}", -42));
+ EXPECT_EQ("42", fmt::format("{0:-}", 42));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), 42u), format_error,
"format specifier requires signed argument");
- EXPECT_EQ("42", format("{0:-}", 42l));
- EXPECT_THROW_MSG(format("{0:-}", 42ul), format_error,
+ EXPECT_EQ("42", fmt::format("{0:-}", 42l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), 42ul), format_error,
"format specifier requires signed argument");
- EXPECT_EQ("42", format("{0:-}", 42ll));
- EXPECT_THROW_MSG(format("{0:-}", 42ull), format_error,
+ EXPECT_EQ("42", fmt::format("{0:-}", 42ll));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), 42ull), format_error,
"format specifier requires signed argument");
- EXPECT_EQ("42", format("{0:-}", 42.0));
- EXPECT_EQ("42", format("{0:-}", 42.0l));
- EXPECT_THROW_MSG(format("{0:-", 'c'), format_error,
+ EXPECT_EQ("42", fmt::format("{0:-}", 42.0));
+ EXPECT_EQ("42", fmt::format("{0:-}", 42.0l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-"), 'c'), format_error,
"missing '}' in format string");
- EXPECT_THROW_MSG(format("{0:-}", 'c'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), 'c'), format_error,
"invalid format specifier for char");
- EXPECT_THROW_MSG(format("{0:-}", "abc"), format_error,
- "format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:-}", reinterpret_cast<void*>(0x42)), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), "abc"), format_error,
"format specifier requires numeric argument");
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0:-}"), reinterpret_cast<void*>(0x42)),
+ format_error, "format specifier requires numeric argument");
}
-TEST(FormatterTest, SpaceSign) {
- EXPECT_EQ(" 42", format("{0: }", 42));
- EXPECT_EQ("-42", format("{0: }", -42));
- EXPECT_EQ(" 42", format("{0: }", 42));
- EXPECT_THROW_MSG(format("{0: }", 42u), format_error,
+TEST(format_test, space_sign) {
+ EXPECT_EQ(" 42", fmt::format("{0: }", 42));
+ EXPECT_EQ("-42", fmt::format("{0: }", -42));
+ EXPECT_EQ(" 42", fmt::format("{0: }", 42));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), 42u), format_error,
"format specifier requires signed argument");
- EXPECT_EQ(" 42", format("{0: }", 42l));
- EXPECT_THROW_MSG(format("{0: }", 42ul), format_error,
+ EXPECT_EQ(" 42", fmt::format("{0: }", 42l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), 42ul), format_error,
"format specifier requires signed argument");
- EXPECT_EQ(" 42", format("{0: }", 42ll));
- EXPECT_THROW_MSG(format("{0: }", 42ull), format_error,
+ EXPECT_EQ(" 42", fmt::format("{0: }", 42ll));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), 42ull), format_error,
"format specifier requires signed argument");
- EXPECT_EQ(" 42", format("{0: }", 42.0));
- EXPECT_EQ(" 42", format("{0: }", 42.0l));
- EXPECT_THROW_MSG(format("{0: ", 'c'), format_error,
+ EXPECT_EQ(" 42", fmt::format("{0: }", 42.0));
+ EXPECT_EQ(" 42", fmt::format("{0: }", 42.0l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: "), 'c'), format_error,
"missing '}' in format string");
- EXPECT_THROW_MSG(format("{0: }", 'c'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), 'c'), format_error,
"invalid format specifier for char");
- EXPECT_THROW_MSG(format("{0: }", "abc"), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), "abc"), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0: }", reinterpret_cast<void*>(0x42)), format_error,
- "format specifier requires numeric argument");
-}
-
-TEST(FormatterTest, SignNotTruncated) {
- wchar_t format_str[] = {L'{', L':',
- '+' | (1 << fmt::detail::num_bits<char>()), L'}', 0};
- EXPECT_THROW(format(format_str, 42), format_error);
-}
-
-TEST(FormatterTest, HashFlag) {
- EXPECT_EQ("42", format("{0:#}", 42));
- EXPECT_EQ("-42", format("{0:#}", -42));
- EXPECT_EQ("0b101010", format("{0:#b}", 42));
- EXPECT_EQ("0B101010", format("{0:#B}", 42));
- EXPECT_EQ("-0b101010", format("{0:#b}", -42));
- EXPECT_EQ("0x42", format("{0:#x}", 0x42));
- EXPECT_EQ("0X42", format("{0:#X}", 0x42));
- EXPECT_EQ("-0x42", format("{0:#x}", -0x42));
- EXPECT_EQ("0", format("{0:#o}", 0));
- EXPECT_EQ("042", format("{0:#o}", 042));
- EXPECT_EQ("-042", format("{0:#o}", -042));
- EXPECT_EQ("42", format("{0:#}", 42u));
- EXPECT_EQ("0x42", format("{0:#x}", 0x42u));
- EXPECT_EQ("042", format("{0:#o}", 042u));
-
- EXPECT_EQ("-42", format("{0:#}", -42l));
- EXPECT_EQ("0x42", format("{0:#x}", 0x42l));
- EXPECT_EQ("-0x42", format("{0:#x}", -0x42l));
- EXPECT_EQ("042", format("{0:#o}", 042l));
- EXPECT_EQ("-042", format("{0:#o}", -042l));
- EXPECT_EQ("42", format("{0:#}", 42ul));
- EXPECT_EQ("0x42", format("{0:#x}", 0x42ul));
- EXPECT_EQ("042", format("{0:#o}", 042ul));
-
- EXPECT_EQ("-42", format("{0:#}", -42ll));
- EXPECT_EQ("0x42", format("{0:#x}", 0x42ll));
- EXPECT_EQ("-0x42", format("{0:#x}", -0x42ll));
- EXPECT_EQ("042", format("{0:#o}", 042ll));
- EXPECT_EQ("-042", format("{0:#o}", -042ll));
- EXPECT_EQ("42", format("{0:#}", 42ull));
- EXPECT_EQ("0x42", format("{0:#x}", 0x42ull));
- EXPECT_EQ("042", format("{0:#o}", 042ull));
-
- EXPECT_EQ("-42.0", format("{0:#}", -42.0));
- EXPECT_EQ("-42.0", format("{0:#}", -42.0l));
- EXPECT_EQ("4.e+01", format("{:#.0e}", 42.0));
- EXPECT_EQ("0.", format("{:#.0f}", 0.01));
- EXPECT_EQ("0.50", format("{:#.2g}", 0.5));
- EXPECT_EQ("0.", format("{:#.0f}", 0.5));
- EXPECT_THROW_MSG(format("{0:#", 'c'), format_error,
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0: }"), reinterpret_cast<void*>(0x42)),
+ format_error, "format specifier requires numeric argument");
+}
+
+TEST(format_test, hash_flag) {
+ EXPECT_EQ("42", fmt::format("{0:#}", 42));
+ EXPECT_EQ("-42", fmt::format("{0:#}", -42));
+ EXPECT_EQ("0b101010", fmt::format("{0:#b}", 42));
+ EXPECT_EQ("0B101010", fmt::format("{0:#B}", 42));
+ EXPECT_EQ("-0b101010", fmt::format("{0:#b}", -42));
+ EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42));
+ EXPECT_EQ("0X42", fmt::format("{0:#X}", 0x42));
+ EXPECT_EQ("-0x42", fmt::format("{0:#x}", -0x42));
+ EXPECT_EQ("0", fmt::format("{0:#o}", 0));
+ EXPECT_EQ("042", fmt::format("{0:#o}", 042));
+ EXPECT_EQ("-042", fmt::format("{0:#o}", -042));
+ EXPECT_EQ("42", fmt::format("{0:#}", 42u));
+ EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42u));
+ EXPECT_EQ("042", fmt::format("{0:#o}", 042u));
+
+ EXPECT_EQ("-42", fmt::format("{0:#}", -42l));
+ EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42l));
+ EXPECT_EQ("-0x42", fmt::format("{0:#x}", -0x42l));
+ EXPECT_EQ("042", fmt::format("{0:#o}", 042l));
+ EXPECT_EQ("-042", fmt::format("{0:#o}", -042l));
+ EXPECT_EQ("42", fmt::format("{0:#}", 42ul));
+ EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42ul));
+ EXPECT_EQ("042", fmt::format("{0:#o}", 042ul));
+
+ EXPECT_EQ("-42", fmt::format("{0:#}", -42ll));
+ EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42ll));
+ EXPECT_EQ("-0x42", fmt::format("{0:#x}", -0x42ll));
+ EXPECT_EQ("042", fmt::format("{0:#o}", 042ll));
+ EXPECT_EQ("-042", fmt::format("{0:#o}", -042ll));
+ EXPECT_EQ("42", fmt::format("{0:#}", 42ull));
+ EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42ull));
+ EXPECT_EQ("042", fmt::format("{0:#o}", 042ull));
+
+ EXPECT_EQ("-42.0", fmt::format("{0:#}", -42.0));
+ EXPECT_EQ("-42.0", fmt::format("{0:#}", -42.0l));
+ EXPECT_EQ("4.e+01", fmt::format("{:#.0e}", 42.0));
+ EXPECT_EQ("0.", fmt::format("{:#.0f}", 0.01));
+ EXPECT_EQ("0.50", fmt::format("{:#.2g}", 0.5));
+ EXPECT_EQ("0.", fmt::format("{:#.0f}", 0.5));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#"), 'c'), format_error,
"missing '}' in format string");
- EXPECT_THROW_MSG(format("{0:#}", 'c'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#}"), 'c'), format_error,
"invalid format specifier for char");
- EXPECT_THROW_MSG(format("{0:#}", "abc"), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#}"), "abc"), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:#}", reinterpret_cast<void*>(0x42)), format_error,
- "format specifier requires numeric argument");
-}
-
-TEST(FormatterTest, ZeroFlag) {
- EXPECT_EQ("42", format("{0:0}", 42));
- EXPECT_EQ("-0042", format("{0:05}", -42));
- EXPECT_EQ("00042", format("{0:05}", 42u));
- EXPECT_EQ("-0042", format("{0:05}", -42l));
- EXPECT_EQ("00042", format("{0:05}", 42ul));
- EXPECT_EQ("-0042", format("{0:05}", -42ll));
- EXPECT_EQ("00042", format("{0:05}", 42ull));
- EXPECT_EQ("-000042", format("{0:07}", -42.0));
- EXPECT_EQ("-000042", format("{0:07}", -42.0l));
- EXPECT_THROW_MSG(format("{0:0", 'c'), format_error,
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0:#}"), reinterpret_cast<void*>(0x42)),
+ format_error, "format specifier requires numeric argument");
+}
+
+TEST(format_test, zero_flag) {
+ EXPECT_EQ("42", fmt::format("{0:0}", 42));
+ EXPECT_EQ("-0042", fmt::format("{0:05}", -42));
+ EXPECT_EQ("00042", fmt::format("{0:05}", 42u));
+ EXPECT_EQ("-0042", fmt::format("{0:05}", -42l));
+ EXPECT_EQ("00042", fmt::format("{0:05}", 42ul));
+ EXPECT_EQ("-0042", fmt::format("{0:05}", -42ll));
+ EXPECT_EQ("00042", fmt::format("{0:05}", 42ull));
+ EXPECT_EQ("-000042", fmt::format("{0:07}", -42.0));
+ EXPECT_EQ("-000042", fmt::format("{0:07}", -42.0l));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:0"), 'c'), format_error,
"missing '}' in format string");
- EXPECT_THROW_MSG(format("{0:05}", 'c'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:05}"), 'c'), format_error,
"invalid format specifier for char");
- EXPECT_THROW_MSG(format("{0:05}", "abc"), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:05}"), "abc"), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:05}", reinterpret_cast<void*>(0x42)),
- format_error, "format specifier requires numeric argument");
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0:05}"), reinterpret_cast<void*>(0x42)),
+ format_error, "format specifier requires numeric argument");
}
-TEST(FormatterTest, Width) {
- char format_str[BUFFER_SIZE];
+TEST(format_test, width) {
+ char format_str[buffer_size];
safe_sprintf(format_str, "{0:%u", UINT_MAX);
increment(format_str + 3);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
size_t size = std::strlen(format_str);
format_str[size] = '}';
format_str[size + 1] = 0;
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
safe_sprintf(format_str, "{0:%u", INT_MAX + 1u);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
- EXPECT_EQ(" -42", format("{0:4}", -42));
- EXPECT_EQ(" 42", format("{0:5}", 42u));
- EXPECT_EQ(" -42", format("{0:6}", -42l));
- EXPECT_EQ(" 42", format("{0:7}", 42ul));
- EXPECT_EQ(" -42", format("{0:6}", -42ll));
- EXPECT_EQ(" 42", format("{0:7}", 42ull));
- EXPECT_EQ(" -1.23", format("{0:8}", -1.23));
- EXPECT_EQ(" -1.23", format("{0:9}", -1.23l));
- EXPECT_EQ(" 0xcafe", format("{0:10}", reinterpret_cast<void*>(0xcafe)));
- EXPECT_EQ("x ", format("{0:11}", 'x'));
- EXPECT_EQ("str ", format("{0:12}", "str"));
- EXPECT_EQ(fmt::format("{:*^5}", "🤡"), "**🤡**");
-}
-
-template <typename T> inline T const_check(T value) { return value; }
-
-TEST(FormatterTest, RuntimeWidth) {
- char format_str[BUFFER_SIZE];
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
+ EXPECT_EQ(" -42", fmt::format("{0:4}", -42));
+ EXPECT_EQ(" 42", fmt::format("{0:5}", 42u));
+ EXPECT_EQ(" -42", fmt::format("{0:6}", -42l));
+ EXPECT_EQ(" 42", fmt::format("{0:7}", 42ul));
+ EXPECT_EQ(" -42", fmt::format("{0:6}", -42ll));
+ EXPECT_EQ(" 42", fmt::format("{0:7}", 42ull));
+ EXPECT_EQ(" -1.23", fmt::format("{0:8}", -1.23));
+ EXPECT_EQ(" -1.23", fmt::format("{0:9}", -1.23l));
+ EXPECT_EQ(" 0xcafe",
+ fmt::format("{0:10}", reinterpret_cast<void*>(0xcafe)));
+ EXPECT_EQ("x ", fmt::format("{0:11}", 'x'));
+ EXPECT_EQ("str ", fmt::format("{0:12}", "str"));
+ EXPECT_EQ(fmt::format("{:*^6}", "🤡"), "**🤡**");
+ EXPECT_EQ(fmt::format("{:*^8}", "你好"), "**你好**");
+ EXPECT_EQ(fmt::format("{:#6}", 42.0), " 42.0");
+ EXPECT_EQ(fmt::format("{:6c}", static_cast<int>('x')), "x ");
+ EXPECT_EQ(fmt::format("{:>06.0f}", 0.00884311), "000000");
+}
+
+TEST(format_test, runtime_width) {
+ char format_str[buffer_size];
safe_sprintf(format_str, "{0:{%u", UINT_MAX);
increment(format_str + 4);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "invalid format string");
size_t size = std::strlen(format_str);
format_str[size] = '}';
format_str[size + 1] = 0;
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "argument not found");
format_str[size + 1] = '}';
format_str[size + 2] = 0;
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "argument not found");
- EXPECT_THROW_MSG(format("{0:{", 0), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("{0:{}", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{"), 0), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{}"), 0), format_error,
"cannot switch from manual to automatic argument indexing");
- EXPECT_THROW_MSG(format("{0:{?}}", 0), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("{0:{1}}", 0), format_error, "argument not found");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{?}}"), 0), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0), format_error,
+ "argument not found");
- EXPECT_THROW_MSG(format("{0:{0:}}", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{0:}}"), 0), format_error,
"invalid format string");
- EXPECT_THROW_MSG(format("{0:{1}}", 0, -1), format_error, "negative width");
- EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1u)), format_error,
- "number is too big");
- EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l), format_error, "negative width");
- if (const_check(sizeof(long) > sizeof(int))) {
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, -1), format_error,
+ "negative width");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, (INT_MAX + 1u)),
+ format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, -1l), format_error,
+ "negative width");
+ if (fmt::detail::const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
- EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)), format_error,
- "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, (value + 1)),
+ format_error, "number is too big");
}
- EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1ul)), format_error,
- "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, (INT_MAX + 1ul)),
+ format_error, "number is too big");
- EXPECT_THROW_MSG(format("{0:{1}}", 0, '0'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, '0'), format_error,
"width is not integer");
- EXPECT_THROW_MSG(format("{0:{1}}", 0, 0.0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{1}}"), 0, 0.0), format_error,
"width is not integer");
- EXPECT_EQ(" -42", format("{0:{1}}", -42, 4));
- EXPECT_EQ(" 42", format("{0:{1}}", 42u, 5));
- EXPECT_EQ(" -42", format("{0:{1}}", -42l, 6));
- EXPECT_EQ(" 42", format("{0:{1}}", 42ul, 7));
- EXPECT_EQ(" -42", format("{0:{1}}", -42ll, 6));
- EXPECT_EQ(" 42", format("{0:{1}}", 42ull, 7));
- EXPECT_EQ(" -1.23", format("{0:{1}}", -1.23, 8));
- EXPECT_EQ(" -1.23", format("{0:{1}}", -1.23l, 9));
+ EXPECT_EQ(" -42", fmt::format("{0:{1}}", -42, 4));
+ EXPECT_EQ(" 42", fmt::format("{0:{1}}", 42u, 5));
+ EXPECT_EQ(" -42", fmt::format("{0:{1}}", -42l, 6));
+ EXPECT_EQ(" 42", fmt::format("{0:{1}}", 42ul, 7));
+ EXPECT_EQ(" -42", fmt::format("{0:{1}}", -42ll, 6));
+ EXPECT_EQ(" 42", fmt::format("{0:{1}}", 42ull, 7));
+ EXPECT_EQ(" -1.23", fmt::format("{0:{1}}", -1.23, 8));
+ EXPECT_EQ(" -1.23", fmt::format("{0:{1}}", -1.23l, 9));
EXPECT_EQ(" 0xcafe",
- format("{0:{1}}", reinterpret_cast<void*>(0xcafe), 10));
- EXPECT_EQ("x ", format("{0:{1}}", 'x', 11));
- EXPECT_EQ("str ", format("{0:{1}}", "str", 12));
+ fmt::format("{0:{1}}", reinterpret_cast<void*>(0xcafe), 10));
+ EXPECT_EQ("x ", fmt::format("{0:{1}}", 'x', 11));
+ EXPECT_EQ("str ", fmt::format("{0:{1}}", "str", 12));
}
-TEST(FormatterTest, Precision) {
- char format_str[BUFFER_SIZE];
+TEST(format_test, precision) {
+ char format_str[buffer_size];
safe_sprintf(format_str, "{0:.%u", UINT_MAX);
increment(format_str + 4);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
size_t size = std::strlen(format_str);
format_str[size] = '}';
format_str[size + 1] = 0;
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "number is too big");
- EXPECT_THROW_MSG(format("{0:.", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:."), 0), format_error,
"missing precision specifier");
- EXPECT_THROW_MSG(format("{0:.}", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.}"), 0), format_error,
"missing precision specifier");
- EXPECT_THROW_MSG(format("{0:.2", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2"), 0), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2}", 42), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2}"), 42), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", 42), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2f}"), 42), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2}", 42u), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2}"), 42u), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", 42u), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2f}"), 42u), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2}", 42l), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2}"), 42l), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", 42l), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2f}"), 42l), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2}", 42ul), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2}"), 42ul), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", 42ul), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2f}"), 42ul), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2}", 42ll), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2}"), 42ll), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", 42ll), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2f}"), 42ll), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2}", 42ull), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2}"), 42ull), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", 42ull), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.2f}"), 42ull), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:3.0}", 'x'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:3.0}"), 'x'), format_error,
"precision not allowed for this argument type");
- EXPECT_EQ("1.2", format("{0:.2}", 1.2345));
- EXPECT_EQ("1.2", format("{0:.2}", 1.2345l));
- EXPECT_EQ("1.2e+56", format("{:.2}", 1.234e56));
- EXPECT_EQ("1e+00", format("{:.0e}", 1.0L));
- EXPECT_EQ(" 0.0e+00", format("{:9.1e}", 0.0));
+ EXPECT_EQ("1.2", fmt::format("{0:.2}", 1.2345));
+ EXPECT_EQ("1.2", fmt::format("{0:.2}", 1.2345l));
+ EXPECT_EQ("1.2e+56", fmt::format("{:.2}", 1.234e56));
+ EXPECT_EQ("1.1", fmt::format("{0:.3}", 1.1));
+ EXPECT_EQ("1e+00", fmt::format("{:.0e}", 1.0L));
+ EXPECT_EQ(" 0.0e+00", fmt::format("{:9.1e}", 0.0));
EXPECT_EQ(
+ fmt::format("{:.494}", 4.9406564584124654E-324),
"4.9406564584124654417656879286822137236505980261432476442558568250067550"
"727020875186529983636163599237979656469544571773092665671035593979639877"
"479601078187812630071319031140452784581716784898210368871863605699873072"
"305000638740915356498438731247339727316961514003171538539807412623856559"
"117102665855668676818703956031062493194527159149245532930545654440112748"
"012970999954193198940908041656332452475714786901472678015935523861155013"
- "480352649347201937902681071074917033322268447533357208324319361e-324",
- format("{:.494}", 4.9406564584124654E-324));
+ "480352649347201937902681071074917033322268447533357208324319361e-324");
EXPECT_EQ(
+ fmt::format("{:.1074f}", 1.1125369292536e-308),
+ "0.0000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000111253692925360019747947051741965785554081512200979"
+ "355021686109411883779182127659725163430929750364498219730822952552570601"
+ "152163505899912777129583674906301179059298598412303893909188340988729019"
+ "014361467448914817838555156840459458527907308695109202499990850735085304"
+ "478476991912072201449236975063640913461919914396877093174125167509869762"
+ "482369631100360266123742648159508919592746619553246586039571522788247697"
+ "156360766271842991667238355464496455107749716934387136380536472531224398"
+ "559833794807213172371254492216255558078524900147957309382830827524104234"
+ "530961756787819847850302379672357738807808384667004752163416921762619527"
+ "462847642037420991432005657440259928195996762610375541867198059294212446"
+ "81962777939941034720757232455434770912461317493580281734466552734375");
+
+ std::string outputs[] = {
"-0X1.41FE3FFE71C9E000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000000000000000000000"
@@ -955,155 +903,193 @@ TEST(FormatterTest, Precision) {
"000000000000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000P+127",
- format("{:.838A}", -2.14001164E+38));
- EXPECT_EQ("123.", format("{:#.0f}", 123.0));
- EXPECT_EQ("1.23", format("{:.02f}", 1.234));
- EXPECT_EQ("0.001", format("{:.1g}", 0.001));
- EXPECT_EQ("1019666400", format("{}", 1019666432.0f));
- EXPECT_EQ("1e+01", format("{:.0e}", 9.5));
+ "-0XA.0FF1FFF38E4F0000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000P+124"};
+ EXPECT_THAT(outputs,
+ testing::Contains(fmt::format("{:.838A}", -2.14001164E+38)));
+
+ EXPECT_EQ("123.", fmt::format("{:#.0f}", 123.0));
+ EXPECT_EQ("1.23", fmt::format("{:.02f}", 1.234));
+ EXPECT_EQ("0.001", fmt::format("{:.1g}", 0.001));
+ EXPECT_EQ("1019666400", fmt::format("{}", 1019666432.0f));
+ EXPECT_EQ("1e+01", fmt::format("{:.0e}", 9.5));
EXPECT_EQ("1.0e-34", fmt::format("{:.1e}", 1e-34));
- EXPECT_THROW_MSG(format("{0:.2}", reinterpret_cast<void*>(0xcafe)),
- format_error,
- "precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.2f}", reinterpret_cast<void*>(0xcafe)),
- format_error,
- "precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{:.{}e}", 42.0, fmt::detail::max_value<int>()),
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0:.2}"), reinterpret_cast<void*>(0xcafe)),
+ format_error, "precision not allowed for this argument type");
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0:.2f}"), reinterpret_cast<void*>(0xcafe)),
+ format_error, "precision not allowed for this argument type");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:.{}e}"), 42.0,
+ fmt::detail::max_value<int>()),
format_error, "number is too big");
+ EXPECT_THROW_MSG(
+ (void)fmt::format("{:.2147483646f}", -2.2121295195081227E+304),
+ format_error, "number is too big");
- EXPECT_EQ("st", format("{0:.2}", "str"));
+ EXPECT_EQ("st", fmt::format("{0:.2}", "str"));
}
-TEST(FormatterTest, RuntimePrecision) {
- char format_str[BUFFER_SIZE];
+TEST(format_test, runtime_precision) {
+ char format_str[buffer_size];
safe_sprintf(format_str, "{0:.{%u", UINT_MAX);
increment(format_str + 5);
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "invalid format string");
size_t size = std::strlen(format_str);
format_str[size] = '}';
format_str[size + 1] = 0;
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "argument not found");
format_str[size + 1] = '}';
format_str[size + 2] = 0;
- EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), 0), format_error,
+ "argument not found");
- EXPECT_THROW_MSG(format("{0:.{", 0), format_error, "invalid format string");
- EXPECT_THROW_MSG(format("{0:.{}", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{"), 0), format_error,
+ "invalid format string");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{}"), 0), format_error,
"cannot switch from manual to automatic argument indexing");
- EXPECT_THROW_MSG(format("{0:.{?}}", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{?}}"), 0), format_error,
"invalid format string");
- EXPECT_THROW_MSG(format("{0:.{1}", 0, 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}"), 0, 0), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}}", 0), format_error, "argument not found");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0), format_error,
+ "argument not found");
- EXPECT_THROW_MSG(format("{0:.{0:}}", 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{0:}}"), 0), format_error,
"invalid format string");
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, -1), format_error,
"negative precision");
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1u)), format_error,
- "number is too big");
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, (INT_MAX + 1u)),
+ format_error, "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, -1l), format_error,
"negative precision");
- if (const_check(sizeof(long) > sizeof(int))) {
+ if (fmt::detail::const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)), format_error,
- "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, (value + 1)),
+ format_error, "number is too big");
}
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1ul)), format_error,
- "number is too big");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, (INT_MAX + 1ul)),
+ format_error, "number is too big");
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, '0'), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, '0'), format_error,
"precision is not integer");
- EXPECT_THROW_MSG(format("{0:.{1}}", 0, 0.0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 0, 0.0), format_error,
"precision is not integer");
- EXPECT_THROW_MSG(format("{0:.{1}}", 42, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 42, 2), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", 42, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"), 42, 2), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}}", 42u, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 42u, 2), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", 42u, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"), 42u, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}}", 42l, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 42l, 2), format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", 42l, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"), 42l, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}}", 42ul, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 42ul, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", 42ul, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"), 42ul, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}}", 42ll, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 42ll, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", 42ll, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"), 42ll, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}}", 42ull, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"), 42ull, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", 42ull, 2), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"), 42ull, 2),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:3.{1}}", 'x', 0), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:3.{1}}"), 'x', 0),
+ format_error,
"precision not allowed for this argument type");
- EXPECT_EQ("1.2", format("{0:.{1}}", 1.2345, 2));
- EXPECT_EQ("1.2", format("{1:.{0}}", 2, 1.2345l));
+ EXPECT_EQ("1.2", fmt::format("{0:.{1}}", 1.2345, 2));
+ EXPECT_EQ("1.2", fmt::format("{1:.{0}}", 2, 1.2345l));
- EXPECT_THROW_MSG(format("{0:.{1}}", reinterpret_cast<void*>(0xcafe), 2),
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}}"),
+ reinterpret_cast<void*>(0xcafe), 2),
format_error,
"precision not allowed for this argument type");
- EXPECT_THROW_MSG(format("{0:.{1}f}", reinterpret_cast<void*>(0xcafe), 2),
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:.{1}f}"),
+ reinterpret_cast<void*>(0xcafe), 2),
format_error,
"precision not allowed for this argument type");
- EXPECT_EQ("st", format("{0:.{1}}", "str", 2));
+ EXPECT_EQ("st", fmt::format("{0:.{1}}", "str", 2));
+}
+
+TEST(format_test, format_bool) {
+ EXPECT_EQ("true", fmt::format("{}", true));
+ EXPECT_EQ("false", fmt::format("{}", false));
+ EXPECT_EQ("1", fmt::format("{:d}", true));
+ EXPECT_EQ("true ", fmt::format("{:5}", true));
+ EXPECT_EQ("true", fmt::format("{:s}", true));
+ EXPECT_EQ("false", fmt::format("{:s}", false));
+ EXPECT_EQ("false ", fmt::format("{:6s}", false));
+}
+
+TEST(format_test, format_short) {
+ short s = 42;
+ EXPECT_EQ("42", fmt::format("{0:d}", s));
+ unsigned short us = 42;
+ EXPECT_EQ("42", fmt::format("{0:d}", us));
}
template <typename T>
void check_unknown_types(const T& value, const char* types, const char*) {
- char format_str[BUFFER_SIZE];
- const char* special = ".0123456789}";
+ char format_str[buffer_size];
+ const char* special = ".0123456789L}";
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
char c = static_cast<char>(i);
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
safe_sprintf(format_str, "{0:10%c}", c);
const char* message = "invalid type specifier";
- EXPECT_THROW_MSG(format(format_str, value), format_error, message)
+ EXPECT_THROW_MSG((void)fmt::format(runtime(format_str), value),
+ format_error, message)
<< format_str << " " << message;
}
}
-TEST(BoolTest, FormatBool) {
- EXPECT_EQ("true", format("{}", true));
- EXPECT_EQ("false", format("{}", false));
- EXPECT_EQ("1", format("{:d}", true));
- EXPECT_EQ("true ", format("{:5}", true));
- EXPECT_EQ(L"true", format(L"{}", true));
-}
-
-TEST(FormatterTest, FormatShort) {
- short s = 42;
- EXPECT_EQ("42", format("{0:d}", s));
- unsigned short us = 42;
- EXPECT_EQ("42", format("{0:d}", us));
-}
-
-TEST(FormatterTest, FormatInt) {
- EXPECT_THROW_MSG(format("{0:v", 42), format_error,
- "missing '}' in format string");
+TEST(format_test, format_int) {
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:v"), 42), format_error,
+ "invalid type specifier");
check_unknown_types(42, "bBdoxXnLc", "integer");
- EXPECT_EQ("x", format("{:c}", static_cast<int>('x')));
-}
-
-TEST(FormatterTest, FormatBin) {
- EXPECT_EQ("0", format("{0:b}", 0));
- EXPECT_EQ("101010", format("{0:b}", 42));
- EXPECT_EQ("101010", format("{0:b}", 42u));
- EXPECT_EQ("-101010", format("{0:b}", -42));
- EXPECT_EQ("11000000111001", format("{0:b}", 12345));
- EXPECT_EQ("10010001101000101011001111000", format("{0:b}", 0x12345678));
- EXPECT_EQ("10010000101010111100110111101111", format("{0:b}", 0x90ABCDEF));
+ EXPECT_EQ("x", fmt::format("{:c}", static_cast<int>('x')));
+}
+
+TEST(format_test, format_bin) {
+ EXPECT_EQ("0", fmt::format("{0:b}", 0));
+ EXPECT_EQ("101010", fmt::format("{0:b}", 42));
+ EXPECT_EQ("101010", fmt::format("{0:b}", 42u));
+ EXPECT_EQ("-101010", fmt::format("{0:b}", -42));
+ EXPECT_EQ("11000000111001", fmt::format("{0:b}", 12345));
+ EXPECT_EQ("10010001101000101011001111000", fmt::format("{0:b}", 0x12345678));
+ EXPECT_EQ("10010000101010111100110111101111",
+ fmt::format("{0:b}", 0x90ABCDEF));
EXPECT_EQ("11111111111111111111111111111111",
- format("{0:b}", max_value<uint32_t>()));
+ fmt::format("{0:b}", max_value<uint32_t>()));
}
#if FMT_USE_INT128
@@ -1114,177 +1100,174 @@ constexpr auto int128_min = -int128_max - 1;
constexpr auto uint128_max = ~static_cast<__uint128_t>(0);
#endif
-TEST(FormatterTest, FormatDec) {
- EXPECT_EQ("0", format("{0}", 0));
- EXPECT_EQ("42", format("{0}", 42));
- EXPECT_EQ("42", format("{0:d}", 42));
- EXPECT_EQ("42", format("{0}", 42u));
- EXPECT_EQ("-42", format("{0}", -42));
- EXPECT_EQ("12345", format("{0}", 12345));
- EXPECT_EQ("67890", format("{0}", 67890));
+TEST(format_test, format_dec) {
+ EXPECT_EQ("0", fmt::format("{0}", 0));
+ EXPECT_EQ("42", fmt::format("{0}", 42));
+ EXPECT_EQ("42", fmt::format("{0:d}", 42));
+ EXPECT_EQ("42", fmt::format("{0}", 42u));
+ EXPECT_EQ("-42", fmt::format("{0}", -42));
+ EXPECT_EQ("12345", fmt::format("{0}", 12345));
+ EXPECT_EQ("67890", fmt::format("{0}", 67890));
#if FMT_USE_INT128
- EXPECT_EQ("0", format("{0}", static_cast<__int128_t>(0)));
- EXPECT_EQ("0", format("{0}", static_cast<__uint128_t>(0)));
+ EXPECT_EQ("0", fmt::format("{0}", static_cast<__int128_t>(0)));
+ EXPECT_EQ("0", fmt::format("{0}", static_cast<__uint128_t>(0)));
EXPECT_EQ("9223372036854775808",
- format("{0}", static_cast<__int128_t>(INT64_MAX) + 1));
+ fmt::format("{0}", static_cast<__int128_t>(INT64_MAX) + 1));
EXPECT_EQ("-9223372036854775809",
- format("{0}", static_cast<__int128_t>(INT64_MIN) - 1));
+ fmt::format("{0}", static_cast<__int128_t>(INT64_MIN) - 1));
EXPECT_EQ("18446744073709551616",
- format("{0}", static_cast<__int128_t>(UINT64_MAX) + 1));
+ fmt::format("{0}", static_cast<__int128_t>(UINT64_MAX) + 1));
EXPECT_EQ("170141183460469231731687303715884105727",
- format("{0}", int128_max));
+ fmt::format("{0}", int128_max));
EXPECT_EQ("-170141183460469231731687303715884105728",
- format("{0}", int128_min));
+ fmt::format("{0}", int128_min));
EXPECT_EQ("340282366920938463463374607431768211455",
- format("{0}", uint128_max));
+ fmt::format("{0}", uint128_max));
#endif
- char buffer[BUFFER_SIZE];
+ char buffer[buffer_size];
safe_sprintf(buffer, "%d", INT_MIN);
- EXPECT_EQ(buffer, format("{0}", INT_MIN));
+ EXPECT_EQ(buffer, fmt::format("{0}", INT_MIN));
safe_sprintf(buffer, "%d", INT_MAX);
- EXPECT_EQ(buffer, format("{0}", INT_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0}", INT_MAX));
safe_sprintf(buffer, "%u", UINT_MAX);
- EXPECT_EQ(buffer, format("{0}", UINT_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0}", UINT_MAX));
safe_sprintf(buffer, "%ld", 0 - static_cast<unsigned long>(LONG_MIN));
- EXPECT_EQ(buffer, format("{0}", LONG_MIN));
+ EXPECT_EQ(buffer, fmt::format("{0}", LONG_MIN));
safe_sprintf(buffer, "%ld", LONG_MAX);
- EXPECT_EQ(buffer, format("{0}", LONG_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0}", LONG_MAX));
safe_sprintf(buffer, "%lu", ULONG_MAX);
- EXPECT_EQ(buffer, format("{0}", ULONG_MAX));
-}
-
-TEST(FormatterTest, FormatHex) {
- EXPECT_EQ("0", format("{0:x}", 0));
- EXPECT_EQ("42", format("{0:x}", 0x42));
- EXPECT_EQ("42", format("{0:x}", 0x42u));
- EXPECT_EQ("-42", format("{0:x}", -0x42));
- EXPECT_EQ("12345678", format("{0:x}", 0x12345678));
- EXPECT_EQ("90abcdef", format("{0:x}", 0x90abcdef));
- EXPECT_EQ("12345678", format("{0:X}", 0x12345678));
- EXPECT_EQ("90ABCDEF", format("{0:X}", 0x90ABCDEF));
+ EXPECT_EQ(buffer, fmt::format("{0}", ULONG_MAX));
+}
+
+TEST(format_test, format_hex) {
+ EXPECT_EQ("0", fmt::format("{0:x}", 0));
+ EXPECT_EQ("42", fmt::format("{0:x}", 0x42));
+ EXPECT_EQ("42", fmt::format("{0:x}", 0x42u));
+ EXPECT_EQ("-42", fmt::format("{0:x}", -0x42));
+ EXPECT_EQ("12345678", fmt::format("{0:x}", 0x12345678));
+ EXPECT_EQ("90abcdef", fmt::format("{0:x}", 0x90abcdef));
+ EXPECT_EQ("12345678", fmt::format("{0:X}", 0x12345678));
+ EXPECT_EQ("90ABCDEF", fmt::format("{0:X}", 0x90ABCDEF));
#if FMT_USE_INT128
- EXPECT_EQ("0", format("{0:x}", static_cast<__int128_t>(0)));
- EXPECT_EQ("0", format("{0:x}", static_cast<__uint128_t>(0)));
+ EXPECT_EQ("0", fmt::format("{0:x}", static_cast<__int128_t>(0)));
+ EXPECT_EQ("0", fmt::format("{0:x}", static_cast<__uint128_t>(0)));
EXPECT_EQ("8000000000000000",
- format("{0:x}", static_cast<__int128_t>(INT64_MAX) + 1));
+ fmt::format("{0:x}", static_cast<__int128_t>(INT64_MAX) + 1));
EXPECT_EQ("-8000000000000001",
- format("{0:x}", static_cast<__int128_t>(INT64_MIN) - 1));
+ fmt::format("{0:x}", static_cast<__int128_t>(INT64_MIN) - 1));
EXPECT_EQ("10000000000000000",
- format("{0:x}", static_cast<__int128_t>(UINT64_MAX) + 1));
- EXPECT_EQ("7fffffffffffffffffffffffffffffff", format("{0:x}", int128_max));
- EXPECT_EQ("-80000000000000000000000000000000", format("{0:x}", int128_min));
- EXPECT_EQ("ffffffffffffffffffffffffffffffff", format("{0:x}", uint128_max));
+ fmt::format("{0:x}", static_cast<__int128_t>(UINT64_MAX) + 1));
+ EXPECT_EQ("7fffffffffffffffffffffffffffffff",
+ fmt::format("{0:x}", int128_max));
+ EXPECT_EQ("-80000000000000000000000000000000",
+ fmt::format("{0:x}", int128_min));
+ EXPECT_EQ("ffffffffffffffffffffffffffffffff",
+ fmt::format("{0:x}", uint128_max));
#endif
- char buffer[BUFFER_SIZE];
+ char buffer[buffer_size];
safe_sprintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN));
- EXPECT_EQ(buffer, format("{0:x}", INT_MIN));
+ EXPECT_EQ(buffer, fmt::format("{0:x}", INT_MIN));
safe_sprintf(buffer, "%x", INT_MAX);
- EXPECT_EQ(buffer, format("{0:x}", INT_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:x}", INT_MAX));
safe_sprintf(buffer, "%x", UINT_MAX);
- EXPECT_EQ(buffer, format("{0:x}", UINT_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:x}", UINT_MAX));
safe_sprintf(buffer, "-%lx", 0 - static_cast<unsigned long>(LONG_MIN));
- EXPECT_EQ(buffer, format("{0:x}", LONG_MIN));
+ EXPECT_EQ(buffer, fmt::format("{0:x}", LONG_MIN));
safe_sprintf(buffer, "%lx", LONG_MAX);
- EXPECT_EQ(buffer, format("{0:x}", LONG_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:x}", LONG_MAX));
safe_sprintf(buffer, "%lx", ULONG_MAX);
- EXPECT_EQ(buffer, format("{0:x}", ULONG_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:x}", ULONG_MAX));
}
-TEST(FormatterTest, FormatOct) {
- EXPECT_EQ("0", format("{0:o}", 0));
- EXPECT_EQ("42", format("{0:o}", 042));
- EXPECT_EQ("42", format("{0:o}", 042u));
- EXPECT_EQ("-42", format("{0:o}", -042));
- EXPECT_EQ("12345670", format("{0:o}", 012345670));
+TEST(format_test, format_oct) {
+ EXPECT_EQ("0", fmt::format("{0:o}", 0));
+ EXPECT_EQ("42", fmt::format("{0:o}", 042));
+ EXPECT_EQ("42", fmt::format("{0:o}", 042u));
+ EXPECT_EQ("-42", fmt::format("{0:o}", -042));
+ EXPECT_EQ("12345670", fmt::format("{0:o}", 012345670));
#if FMT_USE_INT128
- EXPECT_EQ("0", format("{0:o}", static_cast<__int128_t>(0)));
- EXPECT_EQ("0", format("{0:o}", static_cast<__uint128_t>(0)));
+ EXPECT_EQ("0", fmt::format("{0:o}", static_cast<__int128_t>(0)));
+ EXPECT_EQ("0", fmt::format("{0:o}", static_cast<__uint128_t>(0)));
EXPECT_EQ("1000000000000000000000",
- format("{0:o}", static_cast<__int128_t>(INT64_MAX) + 1));
+ fmt::format("{0:o}", static_cast<__int128_t>(INT64_MAX) + 1));
EXPECT_EQ("-1000000000000000000001",
- format("{0:o}", static_cast<__int128_t>(INT64_MIN) - 1));
+ fmt::format("{0:o}", static_cast<__int128_t>(INT64_MIN) - 1));
EXPECT_EQ("2000000000000000000000",
- format("{0:o}", static_cast<__int128_t>(UINT64_MAX) + 1));
+ fmt::format("{0:o}", static_cast<__int128_t>(UINT64_MAX) + 1));
EXPECT_EQ("1777777777777777777777777777777777777777777",
- format("{0:o}", int128_max));
+ fmt::format("{0:o}", int128_max));
EXPECT_EQ("-2000000000000000000000000000000000000000000",
- format("{0:o}", int128_min));
+ fmt::format("{0:o}", int128_min));
EXPECT_EQ("3777777777777777777777777777777777777777777",
- format("{0:o}", uint128_max));
+ fmt::format("{0:o}", uint128_max));
#endif
- char buffer[BUFFER_SIZE];
+ char buffer[buffer_size];
safe_sprintf(buffer, "-%o", 0 - static_cast<unsigned>(INT_MIN));
- EXPECT_EQ(buffer, format("{0:o}", INT_MIN));
+ EXPECT_EQ(buffer, fmt::format("{0:o}", INT_MIN));
safe_sprintf(buffer, "%o", INT_MAX);
- EXPECT_EQ(buffer, format("{0:o}", INT_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:o}", INT_MAX));
safe_sprintf(buffer, "%o", UINT_MAX);
- EXPECT_EQ(buffer, format("{0:o}", UINT_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:o}", UINT_MAX));
safe_sprintf(buffer, "-%lo", 0 - static_cast<unsigned long>(LONG_MIN));
- EXPECT_EQ(buffer, format("{0:o}", LONG_MIN));
+ EXPECT_EQ(buffer, fmt::format("{0:o}", LONG_MIN));
safe_sprintf(buffer, "%lo", LONG_MAX);
- EXPECT_EQ(buffer, format("{0:o}", LONG_MAX));
+ EXPECT_EQ(buffer, fmt::format("{0:o}", LONG_MAX));
safe_sprintf(buffer, "%lo", ULONG_MAX);
- EXPECT_EQ(buffer, format("{0:o}", ULONG_MAX));
-}
-
-TEST(FormatterTest, FormatIntLocale) {
- EXPECT_EQ("1234", format("{:L}", 1234));
+ EXPECT_EQ(buffer, fmt::format("{0:o}", ULONG_MAX));
}
-struct ConvertibleToLongLong {
- operator long long() const { return 1LL << 32; }
-};
-
-TEST(FormatterTest, FormatConvertibleToLongLong) {
- EXPECT_EQ("100000000", format("{:x}", ConvertibleToLongLong()));
+TEST(format_test, format_int_locale) {
+ EXPECT_EQ("1234", fmt::format("{:L}", 1234));
}
-TEST(FormatterTest, FormatFloat) {
- EXPECT_EQ("0", format("{}", 0.0f));
- EXPECT_EQ("392.500000", format("{0:f}", 392.5f));
+TEST(format_test, format_float) {
+ EXPECT_EQ("0", fmt::format("{}", 0.0f));
+ EXPECT_EQ("392.500000", fmt::format("{0:f}", 392.5f));
}
-TEST(FormatterTest, FormatDouble) {
- EXPECT_EQ("0", format("{}", 0.0));
+TEST(format_test, format_double) {
+ EXPECT_EQ("0", fmt::format("{}", 0.0));
check_unknown_types(1.2, "eEfFgGaAnL%", "double");
- EXPECT_EQ("0", format("{:}", 0.0));
- EXPECT_EQ("0.000000", format("{:f}", 0.0));
- EXPECT_EQ("0", format("{:g}", 0.0));
- EXPECT_EQ("392.65", format("{:}", 392.65));
- EXPECT_EQ("392.65", format("{:g}", 392.65));
- EXPECT_EQ("392.65", format("{:G}", 392.65));
- EXPECT_EQ("4.9014e+06", format("{:g}", 4.9014e6));
- EXPECT_EQ("392.650000", format("{:f}", 392.65));
- EXPECT_EQ("392.650000", format("{:F}", 392.65));
- EXPECT_EQ("42", format("{:L}", 42.0));
- char buffer[BUFFER_SIZE];
+ EXPECT_EQ("0", fmt::format("{:}", 0.0));
+ EXPECT_EQ("0.000000", fmt::format("{:f}", 0.0));
+ EXPECT_EQ("0", fmt::format("{:g}", 0.0));
+ EXPECT_EQ("392.65", fmt::format("{:}", 392.65));
+ EXPECT_EQ("392.65", fmt::format("{:g}", 392.65));
+ EXPECT_EQ("392.65", fmt::format("{:G}", 392.65));
+ EXPECT_EQ("4.9014e+06", fmt::format("{:g}", 4.9014e6));
+ EXPECT_EQ("392.650000", fmt::format("{:f}", 392.65));
+ EXPECT_EQ("392.650000", fmt::format("{:F}", 392.65));
+ EXPECT_EQ("42", fmt::format("{:L}", 42.0));
+ EXPECT_EQ(" 0x1.0cccccccccccdp+2", fmt::format("{:24a}", 4.2));
+ EXPECT_EQ("0x1.0cccccccccccdp+2 ", fmt::format("{:<24a}", 4.2));
+ char buffer[buffer_size];
safe_sprintf(buffer, "%e", 392.65);
- EXPECT_EQ(buffer, format("{0:e}", 392.65));
+ EXPECT_EQ(buffer, fmt::format("{0:e}", 392.65));
safe_sprintf(buffer, "%E", 392.65);
- EXPECT_EQ(buffer, format("{0:E}", 392.65));
- EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.65));
+ EXPECT_EQ(buffer, fmt::format("{0:E}", 392.65));
+ EXPECT_EQ("+0000392.6", fmt::format("{0:+010.4g}", 392.65));
safe_sprintf(buffer, "%a", -42.0);
- EXPECT_EQ(buffer, format("{:a}", -42.0));
+ EXPECT_EQ(buffer, fmt::format("{:a}", -42.0));
safe_sprintf(buffer, "%A", -42.0);
- EXPECT_EQ(buffer, format("{:A}", -42.0));
+ EXPECT_EQ(buffer, fmt::format("{:A}", -42.0));
EXPECT_EQ("9223372036854775808.000000",
- format("{:f}", 9223372036854775807.0));
-}
-
-TEST(FormatterTest, PrecisionRounding) {
- EXPECT_EQ("0", format("{:.0f}", 0.0));
- EXPECT_EQ("0", format("{:.0f}", 0.01));
- EXPECT_EQ("0", format("{:.0f}", 0.1));
- EXPECT_EQ("0.000", format("{:.3f}", 0.00049));
- EXPECT_EQ("0.001", format("{:.3f}", 0.0005));
- EXPECT_EQ("0.001", format("{:.3f}", 0.00149));
- EXPECT_EQ("0.002", format("{:.3f}", 0.0015));
- EXPECT_EQ("1.000", format("{:.3f}", 0.9999));
- EXPECT_EQ("0.00123", format("{:.3}", 0.00123));
- EXPECT_EQ("0.1", format("{:.16g}", 0.1));
+ fmt::format("{:f}", 9223372036854775807.0));
+}
+
+TEST(format_test, precision_rounding) {
+ EXPECT_EQ("0", fmt::format("{:.0f}", 0.0));
+ EXPECT_EQ("0", fmt::format("{:.0f}", 0.01));
+ EXPECT_EQ("0", fmt::format("{:.0f}", 0.1));
+ EXPECT_EQ("0.000", fmt::format("{:.3f}", 0.00049));
+ EXPECT_EQ("0.001", fmt::format("{:.3f}", 0.0005));
+ EXPECT_EQ("0.001", fmt::format("{:.3f}", 0.00149));
+ EXPECT_EQ("0.002", fmt::format("{:.3f}", 0.0015));
+ EXPECT_EQ("1.000", fmt::format("{:.3f}", 0.9999));
+ EXPECT_EQ("0.00123", fmt::format("{:.3}", 0.00123));
+ EXPECT_EQ("0.1", fmt::format("{:.16g}", 0.1));
EXPECT_EQ("1", fmt::format("{:.0}", 1.0));
EXPECT_EQ("225.51575035152063720",
fmt::format("{:.17f}", 225.51575035152064));
@@ -1294,10 +1277,10 @@ TEST(FormatterTest, PrecisionRounding) {
EXPECT_EQ("0.0000", fmt::format("{:.4f}", 7.2809479766055470e-15));
// Trigger a rounding error in Grisu by a specially chosen number.
- EXPECT_EQ("3788512123356.985352", format("{:f}", 3788512123356.985352));
+ EXPECT_EQ("3788512123356.985352", fmt::format("{:f}", 3788512123356.985352));
}
-TEST(FormatterTest, PrettifyFloat) {
+TEST(format_test, prettify_float) {
EXPECT_EQ("0.0001", fmt::format("{}", 1e-4));
EXPECT_EQ("1e-05", fmt::format("{}", 1e-5));
EXPECT_EQ("1000000000000000", fmt::format("{}", 1e15));
@@ -1313,127 +1296,128 @@ TEST(FormatterTest, PrettifyFloat) {
EXPECT_EQ("1.3563156e-19", fmt::format("{}", 1.35631564e-19f));
}
-TEST(FormatterTest, FormatNaN) {
+TEST(format_test, format_nan) {
double nan = std::numeric_limits<double>::quiet_NaN();
- EXPECT_EQ("nan", format("{}", nan));
- EXPECT_EQ("+nan", format("{:+}", nan));
- if (std::signbit(-nan))
- EXPECT_EQ("-nan", format("{}", -nan));
- else
+ EXPECT_EQ("nan", fmt::format("{}", nan));
+ EXPECT_EQ("+nan", fmt::format("{:+}", nan));
+ EXPECT_EQ(" +nan", fmt::format("{:+06}", nan));
+ EXPECT_EQ("+nan ", fmt::format("{:<+06}", nan));
+ EXPECT_EQ(" +nan ", fmt::format("{:^+06}", nan));
+ EXPECT_EQ(" +nan", fmt::format("{:>+06}", nan));
+ if (std::signbit(-nan)) {
+ EXPECT_EQ("-nan", fmt::format("{}", -nan));
+ EXPECT_EQ(" -nan", fmt::format("{:+06}", -nan));
+ } else {
fmt::print("Warning: compiler doesn't handle negative NaN correctly");
- EXPECT_EQ(" nan", format("{: }", nan));
- EXPECT_EQ("NAN", format("{:F}", nan));
- EXPECT_EQ("nan ", format("{:<7}", nan));
- EXPECT_EQ(" nan ", format("{:^7}", nan));
- EXPECT_EQ(" nan", format("{:>7}", nan));
+ }
+ EXPECT_EQ(" nan", fmt::format("{: }", nan));
+ EXPECT_EQ("NAN", fmt::format("{:F}", nan));
+ EXPECT_EQ("nan ", fmt::format("{:<7}", nan));
+ EXPECT_EQ(" nan ", fmt::format("{:^7}", nan));
+ EXPECT_EQ(" nan", fmt::format("{:>7}", nan));
}
-TEST(FormatterTest, FormatInfinity) {
+TEST(format_test, format_infinity) {
double inf = std::numeric_limits<double>::infinity();
- EXPECT_EQ("inf", format("{}", inf));
- EXPECT_EQ("+inf", format("{:+}", inf));
- EXPECT_EQ("-inf", format("{}", -inf));
- EXPECT_EQ(" inf", format("{: }", inf));
- EXPECT_EQ("INF", format("{:F}", inf));
- EXPECT_EQ("inf ", format("{:<7}", inf));
- EXPECT_EQ(" inf ", format("{:^7}", inf));
- EXPECT_EQ(" inf", format("{:>7}", inf));
-}
-
-TEST(FormatterTest, FormatLongDouble) {
- EXPECT_EQ("0", format("{0:}", 0.0l));
- EXPECT_EQ("0.000000", format("{0:f}", 0.0l));
- EXPECT_EQ("392.65", format("{0:}", 392.65l));
- EXPECT_EQ("392.65", format("{0:g}", 392.65l));
- EXPECT_EQ("392.65", format("{0:G}", 392.65l));
- EXPECT_EQ("392.650000", format("{0:f}", 392.65l));
- EXPECT_EQ("392.650000", format("{0:F}", 392.65l));
- char buffer[BUFFER_SIZE];
+ EXPECT_EQ("inf", fmt::format("{}", inf));
+ EXPECT_EQ("+inf", fmt::format("{:+}", inf));
+ EXPECT_EQ("-inf", fmt::format("{}", -inf));
+ EXPECT_EQ(" +inf", fmt::format("{:+06}", inf));
+ EXPECT_EQ(" -inf", fmt::format("{:+06}", -inf));
+ EXPECT_EQ("+inf ", fmt::format("{:<+06}", inf));
+ EXPECT_EQ(" +inf ", fmt::format("{:^+06}", inf));
+ EXPECT_EQ(" +inf", fmt::format("{:>+06}", inf));
+ EXPECT_EQ(" inf", fmt::format("{: }", inf));
+ EXPECT_EQ("INF", fmt::format("{:F}", inf));
+ EXPECT_EQ("inf ", fmt::format("{:<7}", inf));
+ EXPECT_EQ(" inf ", fmt::format("{:^7}", inf));
+ EXPECT_EQ(" inf", fmt::format("{:>7}", inf));
+}
+
+TEST(format_test, format_long_double) {
+ EXPECT_EQ("0", fmt::format("{0:}", 0.0l));
+ EXPECT_EQ("0.000000", fmt::format("{0:f}", 0.0l));
+ EXPECT_EQ("392.65", fmt::format("{0:}", 392.65l));
+ EXPECT_EQ("392.65", fmt::format("{0:g}", 392.65l));
+ EXPECT_EQ("392.65", fmt::format("{0:G}", 392.65l));
+ EXPECT_EQ("392.650000", fmt::format("{0:f}", 392.65l));
+ EXPECT_EQ("392.650000", fmt::format("{0:F}", 392.65l));
+ char buffer[buffer_size];
safe_sprintf(buffer, "%Le", 392.65l);
- EXPECT_EQ(buffer, format("{0:e}", 392.65l));
- EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.64l));
+ EXPECT_EQ(buffer, fmt::format("{0:e}", 392.65l));
+ EXPECT_EQ("+0000392.6", fmt::format("{0:+010.4g}", 392.64l));
safe_sprintf(buffer, "%La", 3.31l);
- EXPECT_EQ(buffer, format("{:a}", 3.31l));
+ EXPECT_EQ(buffer, fmt::format("{:a}", 3.31l));
}
-TEST(FormatterTest, FormatChar) {
- const char types[] = "cbBdoxXL";
+TEST(format_test, format_char) {
+ const char types[] = "cbBdoxX";
check_unknown_types('a', types, "char");
- EXPECT_EQ("a", format("{0}", 'a'));
- EXPECT_EQ("z", format("{0:c}", 'z'));
- EXPECT_EQ(L"a", format(L"{0}", 'a'));
+ EXPECT_EQ("a", fmt::format("{0}", 'a'));
+ EXPECT_EQ("z", fmt::format("{0:c}", 'z'));
int n = 'x';
for (const char* type = types + 1; *type; ++type) {
std::string format_str = fmt::format("{{:{}}}", *type);
- EXPECT_EQ(fmt::format(format_str, n), fmt::format(format_str, 'x'));
+ EXPECT_EQ(fmt::format(runtime(format_str), n),
+ fmt::format(runtime(format_str), 'x'))
+ << format_str;
}
EXPECT_EQ(fmt::format("{:02X}", n), fmt::format("{:02X}", 'x'));
}
-TEST(FormatterTest, FormatVolatileChar) {
+TEST(format_test, format_volatile_char) {
volatile char c = 'x';
- EXPECT_EQ("x", format("{}", c));
-}
-
-TEST(FormatterTest, FormatUnsignedChar) {
- EXPECT_EQ("42", format("{}", static_cast<unsigned char>(42)));
- EXPECT_EQ("42", format("{}", static_cast<uint8_t>(42)));
+ EXPECT_EQ("x", fmt::format("{}", c));
}
-TEST(FormatterTest, FormatWChar) {
- EXPECT_EQ(L"a", format(L"{0}", L'a'));
- // This shouldn't compile:
- // format("{}", L'a');
+TEST(format_test, format_unsigned_char) {
+ EXPECT_EQ("42", fmt::format("{}", static_cast<unsigned char>(42)));
+ EXPECT_EQ("42", fmt::format("{}", static_cast<uint8_t>(42)));
}
-TEST(FormatterTest, FormatCString) {
+TEST(format_test, format_cstring) {
check_unknown_types("test", "sp", "string");
- EXPECT_EQ("test", format("{0}", "test"));
- EXPECT_EQ("test", format("{0:s}", "test"));
+ EXPECT_EQ("test", fmt::format("{0}", "test"));
+ EXPECT_EQ("test", fmt::format("{0:s}", "test"));
char nonconst[] = "nonconst";
- EXPECT_EQ("nonconst", format("{0}", nonconst));
- EXPECT_THROW_MSG(format("{0}", static_cast<const char*>(nullptr)),
- format_error, "string pointer is null");
-}
-
-TEST(FormatterTest, FormatSCharString) {
- signed char str[] = "test";
- EXPECT_EQ("test", format("{0:s}", str));
- const signed char* const_str = str;
- EXPECT_EQ("test", format("{0:s}", const_str));
+ EXPECT_EQ("nonconst", fmt::format("{0}", nonconst));
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("{0}"), static_cast<const char*>(nullptr)),
+ format_error, "string pointer is null");
}
-TEST(FormatterTest, FormatUCharString) {
- unsigned char str[] = "test";
- EXPECT_EQ("test", format("{0:s}", str));
- const unsigned char* const_str = str;
- EXPECT_EQ("test", format("{0:s}", const_str));
- unsigned char* ptr = str;
- EXPECT_EQ("test", format("{0:s}", ptr));
-}
+void function_pointer_test(int, double, std::string) {}
-TEST(FormatterTest, FormatPointer) {
+TEST(format_test, format_pointer) {
check_unknown_types(reinterpret_cast<void*>(0x1234), "p", "pointer");
- EXPECT_EQ("0x0", format("{0}", static_cast<void*>(nullptr)));
- EXPECT_EQ("0x1234", format("{0}", reinterpret_cast<void*>(0x1234)));
- EXPECT_EQ("0x1234", format("{0:p}", reinterpret_cast<void*>(0x1234)));
+ EXPECT_EQ("0x0", fmt::format("{0}", static_cast<void*>(nullptr)));
+ EXPECT_EQ("0x1234", fmt::format("{0}", reinterpret_cast<void*>(0x1234)));
+ EXPECT_EQ("0x1234", fmt::format("{0:p}", reinterpret_cast<void*>(0x1234)));
EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'),
- format("{0}", reinterpret_cast<void*>(~uintptr_t())));
- EXPECT_EQ("0x1234", format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234))));
+ fmt::format("{0}", reinterpret_cast<void*>(~uintptr_t())));
+ EXPECT_EQ("0x1234",
+ fmt::format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234))));
std::unique_ptr<int> up(new int(1));
- EXPECT_EQ(format("{}", fmt::ptr(up.get())), format("{}", fmt::ptr(up)));
+ EXPECT_EQ(fmt::format("{}", fmt::ptr(up.get())),
+ fmt::format("{}", fmt::ptr(up)));
std::shared_ptr<int> sp(new int(1));
- EXPECT_EQ(format("{}", fmt::ptr(sp.get())), format("{}", fmt::ptr(sp)));
- EXPECT_EQ("0x0", format("{}", nullptr));
+ EXPECT_EQ(fmt::format("{}", fmt::ptr(sp.get())),
+ fmt::format("{}", fmt::ptr(sp)));
+ EXPECT_EQ(fmt::format("{}", fmt::detail::bit_cast<const void*>(
+ &function_pointer_test)),
+ fmt::format("{}", fmt::ptr(function_pointer_test)));
+ EXPECT_EQ("0x0", fmt::format("{}", nullptr));
}
-TEST(FormatterTest, FormatString) {
- EXPECT_EQ("test", format("{0}", std::string("test")));
+TEST(format_test, format_string) {
+ EXPECT_EQ("test", fmt::format("{0}", std::string("test")));
+ EXPECT_THROW((void)fmt::format(fmt::runtime("{:x}"), std::string("test")),
+ fmt::format_error);
}
-TEST(FormatterTest, FormatStringView) {
- EXPECT_EQ("test", format("{}", string_view("test")));
- EXPECT_EQ("", format("{}", string_view()));
+TEST(format_test, format_string_view) {
+ EXPECT_EQ("test", fmt::format("{}", string_view("test")));
+ EXPECT_EQ("", fmt::format("{}", string_view()));
}
#ifdef FMT_USE_STRING_VIEW
@@ -1447,68 +1431,55 @@ template <> struct formatter<string_viewable> : formatter<std::string_view> {
};
FMT_END_NAMESPACE
-TEST(FormatterTest, FormatStdStringView) {
- EXPECT_EQ("test", format("{}", std::string_view("test")));
- EXPECT_EQ("foo", format("{}", string_viewable()));
+TEST(format_test, format_std_string_view) {
+ EXPECT_EQ("test", fmt::format("{}", std::string_view("test")));
+ EXPECT_EQ("foo", fmt::format("{}", string_viewable()));
}
struct explicitly_convertible_to_std_string_view {
explicit operator std::string_view() const { return "foo"; }
};
-namespace fmt {
template <>
-struct formatter<explicitly_convertible_to_std_string_view>
+struct fmt::formatter<explicitly_convertible_to_std_string_view>
: formatter<std::string_view> {
- auto format(const explicitly_convertible_to_std_string_view& v,
- format_context& ctx) -> decltype(ctx.out()) {
+ auto format(explicitly_convertible_to_std_string_view v, format_context& ctx)
+ -> decltype(ctx.out()) {
return format_to(ctx.out(), "'{}'", std::string_view(v));
}
};
-} // namespace fmt
-TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) {
+TEST(format_test, format_explicitly_convertible_to_std_string_view) {
EXPECT_EQ("'foo'",
fmt::format("{}", explicitly_convertible_to_std_string_view()));
}
#endif
-// std::is_constructible is broken in MSVC until version 2015.
-#if !FMT_MSC_VER || FMT_MSC_VER >= 1900
-struct explicitly_convertible_to_wstring_view {
- explicit operator fmt::wstring_view() const { return L"foo"; }
+struct converible_to_anything {
+ template <typename T> operator T() const { return T(); }
};
-TEST(FormatTest, FormatExplicitlyConvertibleToWStringView) {
- EXPECT_EQ(L"foo",
- fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
-}
-#endif
-
-namespace fake_qt {
-class QString {
- public:
- QString(const wchar_t* s) : s_(std::make_shared<std::wstring>(s)) {}
- const wchar_t* utf16() const FMT_NOEXCEPT { return s_->data(); }
- int size() const FMT_NOEXCEPT { return static_cast<int>(s_->size()); }
+FMT_BEGIN_NAMESPACE
+template <> struct formatter<converible_to_anything> {
+ FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
+ return ctx.begin();
+ }
- private:
- std::shared_ptr<std::wstring> s_;
+ auto format(converible_to_anything, format_context& ctx)
+ -> decltype(ctx.out()) {
+ return format_to(ctx.out(), "foo");
+ }
};
+FMT_END_NAMESPACE
-fmt::basic_string_view<wchar_t> to_string_view(const QString& s) FMT_NOEXCEPT {
- return {s.utf16(), static_cast<size_t>(s.size())};
+TEST(format_test, format_convertible_to_anything) {
+ EXPECT_EQ("foo", fmt::format("{}", converible_to_anything()));
}
-} // namespace fake_qt
-TEST(FormatTest, FormatForeignStrings) {
- using fake_qt::QString;
- EXPECT_EQ(fmt::format(QString(L"{}"), 42), L"42");
- EXPECT_EQ(fmt::format(QString(L"{}"), QString(L"42")), L"42");
-}
+class Answer {};
FMT_BEGIN_NAMESPACE
-template <> struct formatter<Date> {
+template <> struct formatter<date> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin();
@@ -1516,22 +1487,12 @@ template <> struct formatter<Date> {
return it;
}
- auto format(const Date& d, format_context& ctx) -> decltype(ctx.out()) {
+ auto format(const date& d, format_context& ctx) -> decltype(ctx.out()) {
format_to(ctx.out(), "{}-{}-{}", d.year(), d.month(), d.day());
return ctx.out();
}
};
-FMT_END_NAMESPACE
-
-TEST(FormatterTest, FormatCustom) {
- Date date(2012, 12, 9);
- EXPECT_THROW_MSG(fmt::format("{:s}", date), format_error,
- "unknown format specifier");
-}
-class Answer {};
-
-FMT_BEGIN_NAMESPACE
template <> struct formatter<Answer> : formatter<int> {
template <typename FormatContext>
auto format(Answer, FormatContext& ctx) -> decltype(ctx.out()) {
@@ -1540,12 +1501,14 @@ template <> struct formatter<Answer> : formatter<int> {
};
FMT_END_NAMESPACE
-TEST(FormatterTest, CustomFormat) {
- EXPECT_EQ("42", format("{0}", Answer()));
- EXPECT_EQ("0042", format("{:04}", Answer()));
+TEST(format_test, format_custom) {
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:s}"), date(2012, 12, 9)),
+ format_error, "unknown format specifier");
+ EXPECT_EQ("42", fmt::format("{0}", Answer()));
+ EXPECT_EQ("0042", fmt::format("{:04}", Answer()));
}
-TEST(FormatterTest, CustomFormatTo) {
+TEST(format_test, format_to_custom) {
char buf[10] = {};
auto end =
&*fmt::format_to(fmt::detail::make_checked(buf, 10), "{}", Answer());
@@ -1553,29 +1516,20 @@ TEST(FormatterTest, CustomFormatTo) {
EXPECT_STREQ(buf, "42");
}
-TEST(FormatterTest, WideFormatString) {
- EXPECT_EQ(L"42", format(L"{}", 42));
- EXPECT_EQ(L"4.2", format(L"{}", 4.2));
- EXPECT_EQ(L"abc", format(L"{}", L"abc"));
- EXPECT_EQ(L"z", format(L"{}", L'z'));
- EXPECT_THROW(fmt::format(L"{:*\x343E}", 42), fmt::format_error);
-}
-
-TEST(FormatterTest, FormatStringFromSpeedTest) {
+TEST(format_test, format_string_from_speed_test) {
EXPECT_EQ("1.2340000000:0042:+3.13:str:0x3e8:X:%",
- format("{0:0.10f}:{1:04}:{2:+g}:{3}:{4}:{5}:%", 1.234, 42, 3.13,
- "str", reinterpret_cast<void*>(1000), 'X'));
+ fmt::format("{0:0.10f}:{1:04}:{2:+g}:{3}:{4}:{5}:%", 1.234, 42,
+ 3.13, "str", reinterpret_cast<void*>(1000), 'X'));
}
-TEST(FormatterTest, FormatExamples) {
- std::string message = format("The answer is {}", 42);
+TEST(format_test, format_examples) {
+ std::string message = fmt::format("The answer is {}", 42);
EXPECT_EQ("The answer is 42", message);
- EXPECT_EQ("42", format("{}", 42));
- EXPECT_EQ("42", format(std::string("{}"), 42));
+ EXPECT_EQ("42", fmt::format("{}", 42));
memory_buffer out;
- format_to(out, "The answer is {}.", 42);
+ format_to(std::back_inserter(out), "The answer is {}.", 42);
EXPECT_EQ("The answer is 42.", to_string(out));
const char* filename = "nonexistent";
@@ -1591,143 +1545,123 @@ TEST(FormatterTest, FormatExamples) {
fclose(f);
},
error_code, "Cannot open file 'nonexistent'");
-}
-TEST(FormatterTest, Examples) {
EXPECT_EQ("First, thou shalt count to three",
- format("First, thou shalt count to {0}", "three"));
- EXPECT_EQ("Bring me a shrubbery", format("Bring me a {}", "shrubbery"));
- EXPECT_EQ("From 1 to 3", format("From {} to {}", 1, 3));
+ fmt::format("First, thou shalt count to {0}", "three"));
+ EXPECT_EQ("Bring me a shrubbery", fmt::format("Bring me a {}", "shrubbery"));
+ EXPECT_EQ("From 1 to 3", fmt::format("From {} to {}", 1, 3));
- char buffer[BUFFER_SIZE];
+ char buffer[buffer_size];
safe_sprintf(buffer, "%03.2f", -1.2);
- EXPECT_EQ(buffer, format("{:03.2f}", -1.2));
+ EXPECT_EQ(buffer, fmt::format("{:03.2f}", -1.2));
- EXPECT_EQ("a, b, c", format("{0}, {1}, {2}", 'a', 'b', 'c'));
- EXPECT_EQ("a, b, c", format("{}, {}, {}", 'a', 'b', 'c'));
- EXPECT_EQ("c, b, a", format("{2}, {1}, {0}", 'a', 'b', 'c'));
- EXPECT_EQ("abracadabra", format("{0}{1}{0}", "abra", "cad"));
+ EXPECT_EQ("a, b, c", fmt::format("{0}, {1}, {2}", 'a', 'b', 'c'));
+ EXPECT_EQ("a, b, c", fmt::format("{}, {}, {}", 'a', 'b', 'c'));
+ EXPECT_EQ("c, b, a", fmt::format("{2}, {1}, {0}", 'a', 'b', 'c'));
+ EXPECT_EQ("abracadabra", fmt::format("{0}{1}{0}", "abra", "cad"));
- EXPECT_EQ("left aligned ", format("{:<30}", "left aligned"));
+ EXPECT_EQ("left aligned ",
+ fmt::format("{:<30}", "left aligned"));
EXPECT_EQ(" right aligned",
- format("{:>30}", "right aligned"));
- EXPECT_EQ(" centered ", format("{:^30}", "centered"));
- EXPECT_EQ("***********centered***********", format("{:*^30}", "centered"));
+ fmt::format("{:>30}", "right aligned"));
+ EXPECT_EQ(" centered ",
+ fmt::format("{:^30}", "centered"));
+ EXPECT_EQ("***********centered***********",
+ fmt::format("{:*^30}", "centered"));
- EXPECT_EQ("+3.140000; -3.140000", format("{:+f}; {:+f}", 3.14, -3.14));
- EXPECT_EQ(" 3.140000; -3.140000", format("{: f}; {: f}", 3.14, -3.14));
- EXPECT_EQ("3.140000; -3.140000", format("{:-f}; {:-f}", 3.14, -3.14));
+ EXPECT_EQ("+3.140000; -3.140000", fmt::format("{:+f}; {:+f}", 3.14, -3.14));
+ EXPECT_EQ(" 3.140000; -3.140000", fmt::format("{: f}; {: f}", 3.14, -3.14));
+ EXPECT_EQ("3.140000; -3.140000", fmt::format("{:-f}; {:-f}", 3.14, -3.14));
EXPECT_EQ("int: 42; hex: 2a; oct: 52",
- format("int: {0:d}; hex: {0:x}; oct: {0:o}", 42));
+ fmt::format("int: {0:d}; hex: {0:x}; oct: {0:o}", 42));
EXPECT_EQ("int: 42; hex: 0x2a; oct: 052",
- format("int: {0:d}; hex: {0:#x}; oct: {0:#o}", 42));
-
- EXPECT_EQ("The answer is 42", format("The answer is {}", 42));
- EXPECT_THROW_MSG(format("The answer is {:d}", "forty-two"), format_error,
- "invalid type specifier");
+ fmt::format("int: {0:d}; hex: {0:#x}; oct: {0:#o}", 42));
- EXPECT_EQ(L"Cyrillic letter \x42e", format(L"Cyrillic letter {}", L'\x42e'));
+ EXPECT_EQ("The answer is 42", fmt::format("The answer is {}", 42));
+ EXPECT_THROW_MSG(
+ (void)fmt::format(runtime("The answer is {:d}"), "forty-two"),
+ format_error, "invalid type specifier");
EXPECT_WRITE(
stdout, fmt::print("{}", std::numeric_limits<double>::infinity()), "inf");
}
-TEST(FormatIntTest, Data) {
- fmt::format_int format_int(42);
- EXPECT_EQ("42", std::string(format_int.data(), format_int.size()));
-}
-
-TEST(FormatIntTest, FormatInt) {
- EXPECT_EQ("42", fmt::format_int(42).str());
- EXPECT_EQ(2u, fmt::format_int(42).size());
- EXPECT_EQ("-42", fmt::format_int(-42).str());
- EXPECT_EQ(3u, fmt::format_int(-42).size());
- EXPECT_EQ("42", fmt::format_int(42ul).str());
- EXPECT_EQ("-42", fmt::format_int(-42l).str());
- EXPECT_EQ("42", fmt::format_int(42ull).str());
- EXPECT_EQ("-42", fmt::format_int(-42ll).str());
- std::ostringstream os;
- os << max_value<int64_t>();
- EXPECT_EQ(os.str(), fmt::format_int(max_value<int64_t>()).str());
-}
-
-TEST(FormatTest, Print) {
-#if FMT_USE_FCNTL
+TEST(format_test, print) {
EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!");
EXPECT_WRITE(stderr, fmt::print(stderr, "Don't {}!", "panic"),
"Don't panic!");
-#endif
- // Check that the wide print overload compiles.
- if (fmt::detail::const_check(false)) fmt::print(L"test");
}
-TEST(FormatTest, Variadic) {
- EXPECT_EQ("abc1", format("{}c{}", "ab", 1));
- EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1));
+TEST(format_test, variadic) {
+ EXPECT_EQ("abc1", fmt::format("{}c{}", "ab", 1));
}
-TEST(FormatTest, Dynamic) {
- typedef fmt::format_context ctx;
- std::vector<fmt::basic_format_arg<ctx>> args;
+TEST(format_test, dynamic) {
+ using ctx = fmt::format_context;
+ auto args = std::vector<fmt::basic_format_arg<ctx>>();
args.emplace_back(fmt::detail::make_arg<ctx>(42));
args.emplace_back(fmt::detail::make_arg<ctx>("abc1"));
args.emplace_back(fmt::detail::make_arg<ctx>(1.5f));
std::string result = fmt::vformat(
"{} and {} and {}",
- fmt::basic_format_args<ctx>(args.data(), static_cast<int>(args.size())));
+ fmt::format_args(args.data(), static_cast<int>(args.size())));
EXPECT_EQ("42 and abc1 and 1.5", result);
}
-TEST(FormatTest, Bytes) {
+TEST(format_test, bytes) {
auto s = fmt::format("{:10}", fmt::bytes("ёжик"));
EXPECT_EQ("ёжик ", s);
EXPECT_EQ(10, s.size());
}
-TEST(FormatTest, JoinArg) {
+TEST(format_test, group_digits_view) {
+ EXPECT_EQ(fmt::format("{}", fmt::group_digits(10000000)), "10,000,000");
+ EXPECT_EQ(fmt::format("{:8}", fmt::group_digits(1000)), " 1,000");
+}
+
+enum test_enum { foo, bar };
+
+TEST(format_test, join) {
using fmt::join;
int v1[3] = {1, 2, 3};
- std::vector<float> v2;
+ auto v2 = std::vector<float>();
v2.push_back(1.2f);
v2.push_back(3.4f);
void* v3[2] = {&v1[0], &v1[1]};
- EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, v1 + 3, ", ")));
- EXPECT_EQ("(1)", format("({})", join(v1, v1 + 1, ", ")));
- EXPECT_EQ("()", format("({})", join(v1, v1, ", ")));
- EXPECT_EQ("(001, 002, 003)", format("({:03})", join(v1, v1 + 3, ", ")));
+ EXPECT_EQ("(1, 2, 3)", fmt::format("({})", join(v1, v1 + 3, ", ")));
+ EXPECT_EQ("(1)", fmt::format("({})", join(v1, v1 + 1, ", ")));
+ EXPECT_EQ("()", fmt::format("({})", join(v1, v1, ", ")));
+ EXPECT_EQ("(001, 002, 003)", fmt::format("({:03})", join(v1, v1 + 3, ", ")));
EXPECT_EQ("(+01.20, +03.40)",
- format("({:+06.2f})", join(v2.begin(), v2.end(), ", ")));
+ fmt::format("({:+06.2f})", join(v2.begin(), v2.end(), ", ")));
- EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1, v1 + 3, L", ")));
- EXPECT_EQ("1, 2, 3", format("{0:{1}}", join(v1, v1 + 3, ", "), 1));
+ EXPECT_EQ("1, 2, 3", fmt::format("{0:{1}}", join(v1, v1 + 3, ", "), 1));
- EXPECT_EQ(format("{}, {}", v3[0], v3[1]),
- format("{}", join(v3, v3 + 2, ", ")));
+ EXPECT_EQ(fmt::format("{}, {}", v3[0], v3[1]),
+ fmt::format("{}", join(v3, v3 + 2, ", ")));
-#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 405
- EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", ")));
- EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", ")));
-#endif
-}
+ EXPECT_EQ("(1, 2, 3)", fmt::format("({})", join(v1, ", ")));
+ EXPECT_EQ("(+01.20, +03.40)", fmt::format("({:+06.2f})", join(v2, ", ")));
-template <typename T> std::string str(const T& value) {
- return fmt::format("{}", value);
+ auto v4 = std::vector<test_enum>{foo, bar, foo};
+ EXPECT_EQ("0 1 0", fmt::format("{}", join(v4, " ")));
}
-TEST(StrTest, Convert) {
- EXPECT_EQ("42", str(42));
- std::string s = str(Date(2012, 12, 9));
- EXPECT_EQ("2012-12-9", s);
+#ifdef __cpp_lib_byte
+TEST(format_test, join_bytes) {
+ auto v = std::vector<std::byte>{std::byte(1), std::byte(2), std::byte(3)};
+ EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join(v, ", ")));
}
+#endif
std::string vformat_message(int id, const char* format, fmt::format_args args) {
- fmt::memory_buffer buffer;
- format_to(buffer, "[{}] ", id);
- vformat_to(buffer, format, args);
+ auto buffer = fmt::memory_buffer();
+ format_to(fmt::appender(buffer), "[{}] ", id);
+ vformat_to(fmt::appender(buffer), format, args);
return to_string(buffer);
}
@@ -1737,7 +1671,7 @@ std::string format_message(int id, const char* format, const Args&... args) {
return vformat_message(id, format, va);
}
-TEST(FormatTest, FormatMessageExample) {
+TEST(format_test, format_message_example) {
EXPECT_EQ("[42] something happened",
format_message(42, "{} happened", "something"));
}
@@ -1749,7 +1683,7 @@ void print_error(const char* file, int line, const char* format,
fmt::print(format, args...);
}
-TEST(FormatTest, UnpackedArgs) {
+TEST(format_test, unpacked_args) {
EXPECT_EQ("0123456789abcdefg",
fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g'));
@@ -1760,11 +1694,29 @@ fmt::string_view to_string_view(string_like) { return "foo"; }
constexpr char with_null[3] = {'{', '}', '\0'};
constexpr char no_null[2] = {'{', '}'};
+static FMT_CONSTEXPR_DECL const char static_with_null[3] = {'{', '}', '\0'};
+static FMT_CONSTEXPR_DECL const char static_no_null[2] = {'{', '}'};
-TEST(FormatTest, CompileTimeString) {
+TEST(format_test, compile_time_string) {
+ EXPECT_EQ("foo", fmt::format(FMT_STRING("foo")));
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
- EXPECT_EQ(L"42", fmt::format(FMT_STRING(L"{}"), 42));
EXPECT_EQ("foo", fmt::format(FMT_STRING("{}"), string_like()));
+
+#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+ using namespace fmt::literals;
+ EXPECT_EQ("foobar", fmt::format(FMT_STRING("{foo}{bar}"), "bar"_a = "bar",
+ "foo"_a = "foo"));
+ EXPECT_EQ("", fmt::format(FMT_STRING("")));
+ EXPECT_EQ("", fmt::format(FMT_STRING(""), "arg"_a = 42));
+#endif
+
+ (void)static_with_null;
+ (void)static_no_null;
+#ifndef _MSC_VER
+ EXPECT_EQ("42", fmt::format(FMT_STRING(static_with_null), 42));
+ EXPECT_EQ("42", fmt::format(FMT_STRING(static_no_null), 42));
+#endif
+
(void)with_null;
(void)no_null;
#if __cplusplus >= 201703L
@@ -1773,13 +1725,12 @@ TEST(FormatTest, CompileTimeString) {
#endif
#if defined(FMT_USE_STRING_VIEW) && __cplusplus >= 201703L
EXPECT_EQ("42", fmt::format(FMT_STRING(std::string_view("{}")), 42));
- EXPECT_EQ(L"42", fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42));
#endif
}
-TEST(FormatTest, CustomFormatCompileTimeString) {
+TEST(format_test, custom_format_compile_time_string) {
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), Answer()));
- Answer answer;
+ auto answer = Answer();
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), answer));
char buf[10] = {};
fmt::format_to(buf, FMT_STRING("{}"), answer);
@@ -1794,100 +1745,98 @@ TEST(FormatTest, CustomFormatCompileTimeString) {
using namespace fmt::literals;
-TEST(LiteralsTest, Format) {
- auto udl_format = "{}c{}"_format("ab", 1);
- EXPECT_EQ(format("{}c{}", "ab", 1), udl_format);
- auto udl_format_w = L"{}c{}"_format(L"ab", 1);
- EXPECT_EQ(format(L"{}c{}", L"ab", 1), udl_format_w);
-}
-
-TEST(LiteralsTest, NamedArg) {
- auto udl_a = format("{first}{second}{first}{third}", "first"_a = "abra",
- "second"_a = "cad", "third"_a = 99);
- EXPECT_EQ(format("{first}{second}{first}{third}", fmt::arg("first", "abra"),
- fmt::arg("second", "cad"), fmt::arg("third", 99)),
- udl_a);
- auto udl_a_w = format(L"{first}{second}{first}{third}", L"first"_a = L"abra",
- L"second"_a = L"cad", L"third"_a = 99);
- EXPECT_EQ(
- format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"),
- fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)),
- udl_a_w);
-}
+# if FMT_GCC_VERSION
+# define FMT_CHECK_DEPRECATED_UDL_FORMAT 1
+# elif FMT_CLANG_VERSION && defined(__has_warning)
+# if __has_warning("-Wdeprecated-declarations")
+# define FMT_CHECK_DEPRECATED_UDL_FORMAT 1
+# endif
+# endif
+# ifndef FMT_CHECK_DEPRECATED_UDL_FORMAT
+# define FMT_CHECK_DEPRECATED_UDL_FORMAT 0
+# endif
-TEST(FormatTest, UdlTemplate) {
- EXPECT_EQ("foo", "foo"_format());
- EXPECT_EQ(" 42", "{0:10}"_format(42));
+# if FMT_CHECK_DEPRECATED_UDL_FORMAT
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+TEST(format_test, format_udl) {
+ EXPECT_EQ("{}c{}"_format("ab", 1), fmt::format("{}c{}", "ab", 1));
+ EXPECT_EQ("foo"_format(), "foo");
+ EXPECT_EQ("{0:10}"_format(42), " 42");
+ EXPECT_EQ("{}"_format(date(2015, 10, 21)), "2015-10-21");
}
-TEST(FormatTest, UdlPassUserDefinedObjectAsLvalue) {
- Date date(2015, 10, 21);
- EXPECT_EQ("2015-10-21", "{}"_format(date));
+# pragma GCC diagnostic pop
+# endif
+
+TEST(format_test, named_arg_udl) {
+ auto udl_a = fmt::format("{first}{second}{first}{third}", "first"_a = "abra",
+ "second"_a = "cad", "third"_a = 99);
+ EXPECT_EQ(
+ fmt::format("{first}{second}{first}{third}", fmt::arg("first", "abra"),
+ fmt::arg("second", "cad"), fmt::arg("third", 99)),
+ udl_a);
}
#endif // FMT_USE_USER_DEFINED_LITERALS
-enum TestEnum { A };
+TEST(format_test, enum) { EXPECT_EQ("0", fmt::format("{}", foo)); }
-TEST(FormatTest, Enum) { EXPECT_EQ("0", fmt::format("{}", A)); }
-
-TEST(FormatTest, FormatterNotSpecialized) {
- static_assert(
- !fmt::has_formatter<fmt::formatter<TestEnum>, fmt::format_context>::value,
- "");
+TEST(format_test, formatter_not_specialized) {
+ static_assert(!fmt::has_formatter<fmt::formatter<test_enum>,
+ fmt::format_context>::value,
+ "");
}
#if FMT_HAS_FEATURE(cxx_strong_enums)
enum big_enum : unsigned long long { big_enum_value = 5000000000ULL };
-TEST(FormatTest, StrongEnum) {
+TEST(format_test, strong_enum) {
EXPECT_EQ("5000000000", fmt::format("{}", big_enum_value));
}
#endif
-TEST(FormatTest, NonNullTerminatedFormatString) {
- EXPECT_EQ("42", format(string_view("{}foo", 2), 42));
+TEST(format_test, non_null_terminated_format_string) {
+ EXPECT_EQ("42", fmt::format(string_view("{}foo", 2), 42));
}
struct variant {
- enum { INT, STRING } type;
- explicit variant(int) : type(INT) {}
- explicit variant(const char*) : type(STRING) {}
+ enum { int_type, string_type } type;
+ explicit variant(int) : type(int_type) {}
+ explicit variant(const char*) : type(string_type) {}
};
FMT_BEGIN_NAMESPACE
template <> struct formatter<variant> : dynamic_formatter<> {
auto format(variant value, format_context& ctx) -> decltype(ctx.out()) {
- if (value.type == variant::INT) return dynamic_formatter<>::format(42, ctx);
+ if (value.type == variant::int_type)
+ return dynamic_formatter<>::format(42, ctx);
return dynamic_formatter<>::format("foo", ctx);
}
};
FMT_END_NAMESPACE
-TEST(FormatTest, DynamicFormatter) {
+TEST(format_test, dynamic_formatter) {
auto num = variant(42);
auto str = variant("foo");
- EXPECT_EQ("42", format("{:d}", num));
- EXPECT_EQ("foo", format("{:s}", str));
- EXPECT_EQ(" 42 foo ", format("{:{}} {:{}}", num, 3, str, 4));
- EXPECT_THROW_MSG(format("{0:{}}", num), format_error,
+ EXPECT_EQ("42", fmt::format("{:d}", num));
+ EXPECT_EQ("foo", fmt::format("{:s}", str));
+ EXPECT_EQ(" 42 foo ", fmt::format("{:{}} {:{}}", num, 3, str, 4));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:{}}"), num), format_error,
"cannot switch from manual to automatic argument indexing");
- EXPECT_THROW_MSG(format("{:{0}}", num), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:{0}}"), num), format_error,
"cannot switch from automatic to manual argument indexing");
-#if FMT_DEPRECATED_NUMERIC_ALIGN
- EXPECT_THROW_MSG(format("{:=}", str), format_error,
- "format specifier requires numeric argument");
-#endif
- EXPECT_THROW_MSG(format("{:+}", str), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:+}"), str), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{:-}", str), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:-}"), str), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{: }", str), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{: }"), str), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{:#}", str), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:#}"), str), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{:0}", str), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:0}"), str), format_error,
"format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{:.2}", num), format_error,
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{:.2}"), num), format_error,
"precision not allowed for this argument type");
}
@@ -1911,15 +1860,23 @@ struct formatter<adl_test::fmt::detail::foo> : formatter<std::string> {
};
FMT_END_NAMESPACE
-TEST(FormatTest, ToString) {
- EXPECT_EQ("42", fmt::to_string(42));
- EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234)));
- EXPECT_EQ("foo", fmt::to_string(adl_test::fmt::detail::foo()));
-}
+struct convertible_to_int {
+ operator int() const { return value; }
+
+ int value = 42;
+};
+
+TEST(format_test, to_string) {
+ EXPECT_EQ(fmt::to_string(42), "42");
+ EXPECT_EQ(fmt::to_string(reinterpret_cast<void*>(0x1234)), "0x1234");
+ EXPECT_EQ(fmt::to_string(adl_test::fmt::detail::foo()), "foo");
+ EXPECT_EQ(fmt::to_string(convertible_to_int()), "42");
-TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
+ enum foo : unsigned char { zero };
+ EXPECT_EQ(fmt::to_string(zero), "0");
+}
-TEST(FormatTest, OutputIterators) {
+TEST(format_test, output_iterators) {
std::list<char> out;
fmt::format_to(std::back_inserter(out), "{}", 42);
EXPECT_EQ("42", std::string(out.begin(), out.end()));
@@ -1928,17 +1885,48 @@ TEST(FormatTest, OutputIterators) {
EXPECT_EQ("42", s.str());
}
-TEST(FormatTest, FormattedSize) {
+TEST(format_test, formatted_size) {
EXPECT_EQ(2u, fmt::formatted_size("{}", 42));
}
-TEST(FormatTest, FormatTo) {
+TEST(format_test, format_to_no_args) {
+ std::string s;
+ fmt::format_to(std::back_inserter(s), "test");
+ EXPECT_EQ("test", s);
+}
+
+TEST(format_test, format_to) {
+ std::string s;
+ fmt::format_to(std::back_inserter(s), "part{0}", 1);
+ EXPECT_EQ("part1", s);
+ fmt::format_to(std::back_inserter(s), "part{0}", 2);
+ EXPECT_EQ("part1part2", s);
+}
+
+TEST(format_test, format_to_memory_buffer) {
+ auto buf = fmt::basic_memory_buffer<char, 100>();
+ fmt::format_to(fmt::appender(buf), "{}", "foo");
+ EXPECT_EQ("foo", to_string(buf));
+}
+
+TEST(format_test, format_to_vector) {
std::vector<char> v;
fmt::format_to(std::back_inserter(v), "{}", "foo");
EXPECT_EQ(string_view(v.data(), v.size()), "foo");
}
-TEST(FormatTest, FormatToN) {
+struct nongrowing_container {
+ using value_type = char;
+ void push_back(char) { throw std::runtime_error("can't take it any more"); }
+};
+
+TEST(format_test, format_to_propagates_exceptions) {
+ auto c = nongrowing_container();
+ EXPECT_THROW(fmt::format_to(std::back_inserter(c), "{}", 42),
+ std::runtime_error);
+}
+
+TEST(format_test, format_to_n) {
char buffer[4];
buffer[3] = 'x';
auto result = fmt::format_to_n(buffer, 3, "{}", 12345);
@@ -1974,26 +1962,6 @@ TEST(FormatTest, FormatToN) {
EXPECT_EQ("***x", fmt::string_view(buffer, 4));
}
-TEST(FormatTest, WideFormatToN) {
- wchar_t buffer[4];
- buffer[3] = L'x';
- auto result = fmt::format_to_n(buffer, 3, L"{}", 12345);
- EXPECT_EQ(5u, result.size);
- EXPECT_EQ(buffer + 3, result.out);
- EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4));
- buffer[0] = L'x';
- buffer[1] = L'x';
- buffer[2] = L'x';
- result = fmt::format_to_n(buffer, 3, L"{}", L'A');
- EXPECT_EQ(1u, result.size);
- EXPECT_EQ(buffer + 1, result.out);
- EXPECT_EQ(L"Axxx", fmt::wstring_view(buffer, 4));
- result = fmt::format_to_n(buffer, 3, L"{}{} ", L'B', L'C');
- EXPECT_EQ(3u, result.size);
- EXPECT_EQ(buffer + 3, result.out);
- EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4));
-}
-
struct test_output_iterator {
char* data;
@@ -2015,269 +1983,13 @@ struct test_output_iterator {
char& operator*() { return *data; }
};
-TEST(FormatTest, FormatToNOutputIterator) {
+TEST(format_test, format_to_n_output_iterator) {
char buf[10] = {};
fmt::format_to_n(test_output_iterator{buf}, 10, "{}", 42);
EXPECT_STREQ(buf, "42");
}
#if FMT_USE_CONSTEXPR
-struct test_arg_id_handler {
- enum result { NONE, EMPTY, INDEX, NAME, ERROR };
- result res = NONE;
- int index = 0;
- string_view name;
-
- FMT_CONSTEXPR void operator()() { res = EMPTY; }
-
- FMT_CONSTEXPR void operator()(int i) {
- res = INDEX;
- index = i;
- }
-
- FMT_CONSTEXPR void operator()(string_view n) {
- res = NAME;
- name = n;
- }
-
- FMT_CONSTEXPR void on_error(const char*) { res = ERROR; }
-};
-
-template <size_t N>
-FMT_CONSTEXPR test_arg_id_handler parse_arg_id(const char (&s)[N]) {
- test_arg_id_handler h;
- fmt::detail::parse_arg_id(s, s + N, h);
- return h;
-}
-
-TEST(FormatTest, ConstexprParseArgID) {
- static_assert(parse_arg_id(":").res == test_arg_id_handler::EMPTY, "");
- static_assert(parse_arg_id("}").res == test_arg_id_handler::EMPTY, "");
- static_assert(parse_arg_id("42:").res == test_arg_id_handler::INDEX, "");
- static_assert(parse_arg_id("42:").index == 42, "");
- static_assert(parse_arg_id("foo:").res == test_arg_id_handler::NAME, "");
- static_assert(parse_arg_id("foo:").name.size() == 3, "");
- static_assert(parse_arg_id("!").res == test_arg_id_handler::ERROR, "");
-}
-
-struct test_format_specs_handler {
- enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR };
- Result res = NONE;
-
- fmt::align_t align = fmt::align::none;
- char fill = 0;
- int width = 0;
- fmt::detail::arg_ref<char> width_ref;
- int precision = 0;
- fmt::detail::arg_ref<char> precision_ref;
- char type = 0;
-
- // Workaround for MSVC2017 bug that results in "expression did not evaluate
- // to a constant" with compiler-generated copy ctor.
- FMT_CONSTEXPR test_format_specs_handler() {}
- FMT_CONSTEXPR test_format_specs_handler(
- const test_format_specs_handler& other)
- : res(other.res),
- align(other.align),
- fill(other.fill),
- width(other.width),
- width_ref(other.width_ref),
- precision(other.precision),
- precision_ref(other.precision_ref),
- type(other.type) {}
-
- FMT_CONSTEXPR void on_align(fmt::align_t a) { align = a; }
- FMT_CONSTEXPR void on_fill(fmt::string_view f) { fill = f[0]; }
- FMT_CONSTEXPR void on_plus() { res = PLUS; }
- FMT_CONSTEXPR void on_minus() { res = MINUS; }
- FMT_CONSTEXPR void on_space() { res = SPACE; }
- FMT_CONSTEXPR void on_hash() { res = HASH; }
- FMT_CONSTEXPR void on_zero() { res = ZERO; }
-
- FMT_CONSTEXPR void on_width(int w) { width = w; }
- FMT_CONSTEXPR void on_dynamic_width(fmt::detail::auto_id) {}
- FMT_CONSTEXPR void on_dynamic_width(int index) { width_ref = index; }
- FMT_CONSTEXPR void on_dynamic_width(string_view) {}
-
- FMT_CONSTEXPR void on_precision(int p) { precision = p; }
- FMT_CONSTEXPR void on_dynamic_precision(fmt::detail::auto_id) {}
- FMT_CONSTEXPR void on_dynamic_precision(int index) { precision_ref = index; }
- FMT_CONSTEXPR void on_dynamic_precision(string_view) {}
-
- FMT_CONSTEXPR void end_precision() {}
- FMT_CONSTEXPR void on_type(char t) { type = t; }
- FMT_CONSTEXPR void on_error(const char*) { res = ERROR; }
-};
-
-template <size_t N>
-FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char (&s)[N]) {
- test_format_specs_handler h;
- fmt::detail::parse_format_specs(s, s + N, h);
- return h;
-}
-
-TEST(FormatTest, ConstexprParseFormatSpecs) {
- typedef test_format_specs_handler handler;
- static_assert(parse_test_specs("<").align == fmt::align::left, "");
- static_assert(parse_test_specs("*^").fill == '*', "");
- static_assert(parse_test_specs("+").res == handler::PLUS, "");
- static_assert(parse_test_specs("-").res == handler::MINUS, "");
- static_assert(parse_test_specs(" ").res == handler::SPACE, "");
- static_assert(parse_test_specs("#").res == handler::HASH, "");
- static_assert(parse_test_specs("0").res == handler::ZERO, "");
- static_assert(parse_test_specs("42").width == 42, "");
- static_assert(parse_test_specs("{42}").width_ref.val.index == 42, "");
- static_assert(parse_test_specs(".42").precision == 42, "");
- static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, "");
- static_assert(parse_test_specs("d").type == 'd', "");
- static_assert(parse_test_specs("{<").res == handler::ERROR, "");
-}
-
-struct test_parse_context {
- typedef char char_type;
-
- FMT_CONSTEXPR int next_arg_id() { return 11; }
- template <typename Id> FMT_CONSTEXPR void check_arg_id(Id) {}
-
- FMT_CONSTEXPR const char* begin() { return nullptr; }
- FMT_CONSTEXPR const char* end() { return nullptr; }
-
- void on_error(const char*) {}
-};
-
-struct test_context {
- using char_type = char;
- using format_arg = fmt::basic_format_arg<test_context>;
- using parse_context_type = fmt::format_parse_context;
-
- template <typename T> struct formatter_type {
- typedef fmt::formatter<T, char_type> type;
- };
-
- template <typename Id>
- FMT_CONSTEXPR fmt::basic_format_arg<test_context> arg(Id id) {
- return fmt::detail::make_arg<test_context>(id);
- }
-
- void on_error(const char*) {}
-
- FMT_CONSTEXPR test_context error_handler() { return *this; }
-};
-
-template <size_t N>
-FMT_CONSTEXPR fmt::format_specs parse_specs(const char (&s)[N]) {
- auto specs = fmt::format_specs();
- auto parse_ctx = test_parse_context();
- auto ctx = test_context();
- fmt::detail::specs_handler<test_parse_context, test_context> h(
- specs, parse_ctx, ctx);
- parse_format_specs(s, s + N, h);
- return specs;
-}
-
-TEST(FormatTest, ConstexprSpecsHandler) {
- static_assert(parse_specs("<").align == fmt::align::left, "");
- static_assert(parse_specs("*^").fill[0] == '*', "");
- static_assert(parse_specs("+").sign == fmt::sign::plus, "");
- static_assert(parse_specs("-").sign == fmt::sign::minus, "");
- static_assert(parse_specs(" ").sign == fmt::sign::space, "");
- static_assert(parse_specs("#").alt, "");
- static_assert(parse_specs("0").align == fmt::align::numeric, "");
- static_assert(parse_specs("42").width == 42, "");
- static_assert(parse_specs("{}").width == 11, "");
- static_assert(parse_specs("{22}").width == 22, "");
- static_assert(parse_specs(".42").precision == 42, "");
- static_assert(parse_specs(".{}").precision == 11, "");
- static_assert(parse_specs(".{22}").precision == 22, "");
- static_assert(parse_specs("d").type == 'd', "");
-}
-
-template <size_t N>
-FMT_CONSTEXPR fmt::detail::dynamic_format_specs<char> parse_dynamic_specs(
- const char (&s)[N]) {
- fmt::detail::dynamic_format_specs<char> specs;
- test_parse_context ctx{};
- fmt::detail::dynamic_specs_handler<test_parse_context> h(specs, ctx);
- parse_format_specs(s, s + N, h);
- return specs;
-}
-
-TEST(FormatTest, ConstexprDynamicSpecsHandler) {
- static_assert(parse_dynamic_specs("<").align == fmt::align::left, "");
- static_assert(parse_dynamic_specs("*^").fill[0] == '*', "");
- static_assert(parse_dynamic_specs("+").sign == fmt::sign::plus, "");
- static_assert(parse_dynamic_specs("-").sign == fmt::sign::minus, "");
- static_assert(parse_dynamic_specs(" ").sign == fmt::sign::space, "");
- static_assert(parse_dynamic_specs("#").alt, "");
- static_assert(parse_dynamic_specs("0").align == fmt::align::numeric, "");
- static_assert(parse_dynamic_specs("42").width == 42, "");
- static_assert(parse_dynamic_specs("{}").width_ref.val.index == 11, "");
- static_assert(parse_dynamic_specs("{42}").width_ref.val.index == 42, "");
- static_assert(parse_dynamic_specs(".42").precision == 42, "");
- static_assert(parse_dynamic_specs(".{}").precision_ref.val.index == 11, "");
- static_assert(parse_dynamic_specs(".{42}").precision_ref.val.index == 42, "");
- static_assert(parse_dynamic_specs("d").type == 'd', "");
-}
-
-template <size_t N>
-FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) {
- fmt::detail::specs_checker<test_format_specs_handler> checker(
- test_format_specs_handler(), fmt::detail::type::double_type);
- parse_format_specs(s, s + N, checker);
- return checker;
-}
-
-TEST(FormatTest, ConstexprSpecsChecker) {
- typedef test_format_specs_handler handler;
- static_assert(check_specs("<").align == fmt::align::left, "");
- static_assert(check_specs("*^").fill == '*', "");
- static_assert(check_specs("+").res == handler::PLUS, "");
- static_assert(check_specs("-").res == handler::MINUS, "");
- static_assert(check_specs(" ").res == handler::SPACE, "");
- static_assert(check_specs("#").res == handler::HASH, "");
- static_assert(check_specs("0").res == handler::ZERO, "");
- static_assert(check_specs("42").width == 42, "");
- static_assert(check_specs("{42}").width_ref.val.index == 42, "");
- static_assert(check_specs(".42").precision == 42, "");
- static_assert(check_specs(".{42}").precision_ref.val.index == 42, "");
- static_assert(check_specs("d").type == 'd', "");
- static_assert(check_specs("{<").res == handler::ERROR, "");
-}
-
-struct test_format_string_handler {
- FMT_CONSTEXPR void on_text(const char*, const char*) {}
-
- FMT_CONSTEXPR int on_arg_id() { return 0; }
-
- template <typename T> FMT_CONSTEXPR int on_arg_id(T) { return 0; }
-
- FMT_CONSTEXPR void on_replacement_field(int, const char*) {}
-
- FMT_CONSTEXPR const char* on_format_specs(int, const char* begin,
- const char*) {
- return begin;
- }
-
- FMT_CONSTEXPR void on_error(const char*) { error = true; }
-
- bool error = false;
-};
-
-template <size_t N> FMT_CONSTEXPR bool parse_string(const char (&s)[N]) {
- test_format_string_handler h;
- fmt::detail::parse_format_string<true>(fmt::string_view(s, N - 1), h);
- return !h.error;
-}
-
-TEST(FormatTest, ConstexprParseFormatString) {
- static_assert(parse_string("foo"), "");
- static_assert(!parse_string("}"), "");
- static_assert(parse_string("{}"), "");
- static_assert(parse_string("{42}"), "");
- static_assert(parse_string("{foo}"), "");
- static_assert(parse_string("{:}"), "");
-}
-
struct test_error_handler {
const char*& error;
@@ -2309,9 +2021,10 @@ FMT_CONSTEXPR bool equal(const char* s1, const char* s2) {
template <typename... Args>
FMT_CONSTEXPR bool test_error(const char* fmt, const char* expected_error) {
const char* actual_error = nullptr;
- string_view s(fmt, len(fmt));
- fmt::detail::format_string_checker<char, test_error_handler, Args...> checker(
- s, test_error_handler(actual_error));
+ auto s = string_view(fmt, len(fmt));
+ auto checker =
+ fmt::detail::format_string_checker<char, test_error_handler, Args...>(
+ s, test_error_handler(actual_error));
fmt::detail::parse_format_string<true>(s, checker);
return equal(actual_error, expected_error);
}
@@ -2321,21 +2034,16 @@ FMT_CONSTEXPR bool test_error(const char* fmt, const char* expected_error) {
# define EXPECT_ERROR(fmt, error, ...) \
static_assert(test_error<__VA_ARGS__>(fmt, error), "")
-TEST(FormatTest, FormatStringErrors) {
+TEST(format_test, format_string_errors) {
EXPECT_ERROR_NOARGS("foo", nullptr);
EXPECT_ERROR_NOARGS("}", "unmatched '}' in format string");
- EXPECT_ERROR("{0:s", "unknown format specifier", Date);
+ EXPECT_ERROR("{0:s", "unknown format specifier", date);
# if !FMT_MSC_VER || FMT_MSC_VER >= 1916
// This causes an detail compiler error in MSVC2017.
EXPECT_ERROR("{:{<}", "invalid fill character '{'", int);
EXPECT_ERROR("{:10000000000}", "number is too big", int);
EXPECT_ERROR("{:.10000000000}", "number is too big", int);
EXPECT_ERROR_NOARGS("{:x}", "argument not found");
-# if FMT_DEPRECATED_NUMERIC_ALIGN
- EXPECT_ERROR("{0:=5", "unknown format specifier", int);
- EXPECT_ERROR("{:=}", "format specifier requires numeric argument",
- const char*);
-# endif
EXPECT_ERROR("{:+}", "format specifier requires numeric argument",
const char*);
EXPECT_ERROR("{:-}", "format specifier requires numeric argument",
@@ -2353,7 +2061,6 @@ TEST(FormatTest, FormatStringErrors) {
EXPECT_ERROR("{:.{}}", "argument not found", double);
EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int);
EXPECT_ERROR("{:s}", "invalid type specifier", int);
- EXPECT_ERROR("{:s}", "invalid type specifier", bool);
EXPECT_ERROR("{:s}", "invalid type specifier", char);
EXPECT_ERROR("{:+}", "invalid format specifier for char", char);
EXPECT_ERROR("{:s}", "invalid type specifier", double);
@@ -2363,9 +2070,16 @@ TEST(FormatTest, FormatStringErrors) {
# else
fmt::print("warning: constexpr is broken in this version of MSVC\n");
# endif
- EXPECT_ERROR("{foo", "compile-time checks don't support named arguments",
+# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+ EXPECT_ERROR("{foo}", "named argument is not found", decltype("bar"_a = 42));
+ EXPECT_ERROR("{foo}", "named argument is not found",
+ decltype(fmt::arg("foo", 42)));
+# else
+ EXPECT_ERROR("{foo}",
+ "compile-time checks for named arguments require C++20 support",
int);
- EXPECT_ERROR_NOARGS("{10000000000}", "number is too big");
+# endif
+ EXPECT_ERROR_NOARGS("{10000000000}", "argument not found");
EXPECT_ERROR_NOARGS("{0x}", "invalid format string");
EXPECT_ERROR_NOARGS("{-}", "invalid format string");
EXPECT_ERROR("{:{0x}}", "invalid format string", int);
@@ -2383,99 +2097,37 @@ TEST(FormatTest, FormatStringErrors) {
int);
}
-TEST(FormatTest, VFormatTo) {
- typedef fmt::format_context context;
+TEST(format_test, vformat_to) {
+ using context = fmt::format_context;
fmt::basic_format_arg<context> arg = fmt::detail::make_arg<context>(42);
- fmt::basic_format_args<context> args(&arg, 1);
- std::string s;
+ auto args = fmt::basic_format_args<context>(&arg, 1);
+ auto s = std::string();
fmt::vformat_to(std::back_inserter(s), "{}", args);
EXPECT_EQ("42", s);
s.clear();
fmt::vformat_to(std::back_inserter(s), FMT_STRING("{}"), args);
EXPECT_EQ("42", s);
-
- typedef fmt::wformat_context wcontext;
- fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42);
- fmt::basic_format_args<wcontext> wargs(&warg, 1);
- std::wstring w;
- fmt::vformat_to(std::back_inserter(w), L"{}", wargs);
- EXPECT_EQ(L"42", w);
- w.clear();
- fmt::vformat_to(std::back_inserter(w), FMT_STRING(L"{}"), wargs);
- EXPECT_EQ(L"42", w);
-}
-
-template <typename T> static std::string FmtToString(const T& t) {
- return fmt::format(FMT_STRING("{}"), t);
-}
-
-TEST(FormatTest, FmtStringInTemplate) {
- EXPECT_EQ(FmtToString(1), "1");
- EXPECT_EQ(FmtToString(0), "0");
}
#endif // FMT_USE_CONSTEXPR
-TEST(FormatTest, CharTraitsIsNotAmbiguous) {
+TEST(format_test, char_traits_is_not_ambiguous) {
// Test that we don't inject detail names into the std namespace.
using namespace std;
- char_traits<char>::char_type c;
+ auto c = char_traits<char>::char_type();
(void)c;
#if __cplusplus >= 201103L
- std::string s;
+ auto s = std::string();
auto lval = begin(s);
(void)lval;
#endif
}
-#if __cplusplus > 201103L
-struct custom_char {
- int value;
- custom_char() = default;
-
- template <typename T>
- constexpr custom_char(T val) : value(static_cast<int>(val)) {}
-
- operator int() const { return value; }
-};
-
-int to_ascii(custom_char c) { return c; }
-
-FMT_BEGIN_NAMESPACE
-template <> struct is_char<custom_char> : std::true_type {};
-FMT_END_NAMESPACE
-
-TEST(FormatTest, FormatCustomChar) {
- const custom_char format[] = {'{', '}', 0};
- auto result = fmt::format(format, custom_char('x'));
- EXPECT_EQ(result.size(), 1);
- EXPECT_EQ(result[0], custom_char('x'));
-}
-#endif
-
-// Convert a char8_t string to std::string. Otherwise GTest will insist on
-// inserting `char8_t` NTBS into a `char` stream which is disabled by P1423.
-template <typename S> std::string from_u8str(const S& str) {
- return std::string(str.begin(), str.end());
-}
-
-TEST(FormatTest, FormatUTF8Precision) {
- using str_type = std::basic_string<fmt::detail::char8_type>;
- str_type format(reinterpret_cast<const fmt::detail::char8_type*>(u8"{:.4}"));
- str_type str(reinterpret_cast<const fmt::detail::char8_type*>(
- u8"caf\u00e9s")); // cafés
- auto result = fmt::format(format, str);
- EXPECT_EQ(fmt::detail::count_code_points(result), 4);
- EXPECT_EQ(result.size(), 5);
- EXPECT_EQ(from_u8str(result), from_u8str(str.substr(0, 5)));
-}
-
struct check_back_appender {};
FMT_BEGIN_NAMESPACE
template <> struct formatter<check_back_appender> {
- template <typename ParseContext>
- auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
@@ -2490,6 +2142,49 @@ template <> struct formatter<check_back_appender> {
};
FMT_END_NAMESPACE
-TEST(FormatTest, BackInsertSlicing) {
+TEST(format_test, back_insert_slicing) {
EXPECT_EQ(fmt::format("{}", check_back_appender{}), "y");
}
+
+template <typename Char, typename T> bool check_enabled_formatter() {
+ static_assert(std::is_default_constructible<fmt::formatter<T, Char>>::value,
+ "");
+ return true;
+}
+
+template <typename Char, typename... T> void check_enabled_formatters() {
+ auto dummy = {check_enabled_formatter<Char, T>()...};
+ (void)dummy;
+}
+
+TEST(format_test, test_formatters_enabled) {
+ check_enabled_formatters<char, bool, char, signed char, unsigned char, short,
+ unsigned short, int, unsigned, long, unsigned long,
+ long long, unsigned long long, float, double,
+ long double, void*, const void*, char*, const char*,
+ std::string, std::nullptr_t>();
+ check_enabled_formatters<wchar_t, bool, wchar_t, signed char, unsigned char,
+ short, unsigned short, int, unsigned, long,
+ unsigned long, long long, unsigned long long, float,
+ double, long double, void*, const void*, wchar_t*,
+ const wchar_t*, std::wstring, std::nullptr_t>();
+}
+
+TEST(format_int_test, data) {
+ fmt::format_int format_int(42);
+ EXPECT_EQ("42", std::string(format_int.data(), format_int.size()));
+}
+
+TEST(format_int_test, format_int) {
+ EXPECT_EQ("42", fmt::format_int(42).str());
+ EXPECT_EQ(2u, fmt::format_int(42).size());
+ EXPECT_EQ("-42", fmt::format_int(-42).str());
+ EXPECT_EQ(3u, fmt::format_int(-42).size());
+ EXPECT_EQ("42", fmt::format_int(42ul).str());
+ EXPECT_EQ("-42", fmt::format_int(-42l).str());
+ EXPECT_EQ("42", fmt::format_int(42ull).str());
+ EXPECT_EQ("-42", fmt::format_int(-42ll).str());
+ std::ostringstream os;
+ os << max_value<int64_t>();
+ EXPECT_EQ(os.str(), fmt::format_int(max_value<int64_t>()).str());
+}
diff --git a/contrib/libs/fmt/test/gtest-extra-test.cc b/contrib/libs/fmt/test/gtest-extra-test.cc
index ea728607e8..0d86206c93 100644
--- a/contrib/libs/fmt/test/gtest-extra-test.cc
+++ b/contrib/libs/fmt/test/gtest-extra-test.cc
@@ -9,31 +9,18 @@
#include <gtest/gtest-spi.h>
-#include <algorithm>
#include <cstring>
#include <memory>
#include <stdexcept>
-#if defined(_WIN32) && !defined(__MINGW32__)
-# include <crtdbg.h> // for _CrtSetReportMode
-#endif // _WIN32
-
+#include "fmt/os.h"
#include "util.h"
-namespace {
-
-// This is used to suppress coverity warnings about untrusted values.
-std::string sanitize(const std::string& s) {
- std::string result;
- for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i)
- result.push_back(static_cast<char>(*i & 0xff));
- return result;
-}
-
// Tests that assertion macros evaluate their arguments exactly once.
-class SingleEvaluationTest : public ::testing::Test {
+namespace {
+class single_evaluation_test : public ::testing::Test {
protected:
- SingleEvaluationTest() {
+ single_evaluation_test() {
p_ = s_;
a_ = 0;
b_ = 0;
@@ -45,11 +32,12 @@ class SingleEvaluationTest : public ::testing::Test {
static int a_;
static int b_;
};
+} // namespace
-const char* const SingleEvaluationTest::s_ = "01234";
-const char* SingleEvaluationTest::p_;
-int SingleEvaluationTest::a_;
-int SingleEvaluationTest::b_;
+const char* const single_evaluation_test::s_ = "01234";
+const char* single_evaluation_test::p_;
+int single_evaluation_test::a_;
+int single_evaluation_test::b_;
void do_nothing() {}
@@ -61,7 +49,7 @@ FMT_NORETURN void throw_system_error() {
// Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument
// exactly once.
-TEST_F(SingleEvaluationTest, FailedEXPECT_THROW_MSG) {
+TEST_F(single_evaluation_test, failed_expect_throw_msg) {
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::exception, p_++), "01234");
EXPECT_EQ(s_ + 1, p_);
@@ -69,14 +57,14 @@ TEST_F(SingleEvaluationTest, FailedEXPECT_THROW_MSG) {
// Tests that when EXPECT_SYSTEM_ERROR fails, it evaluates its message argument
// exactly once.
-TEST_F(SingleEvaluationTest, FailedEXPECT_SYSTEM_ERROR) {
+TEST_F(single_evaluation_test, failed_expect_system_error) {
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, p_++),
"01234");
EXPECT_EQ(s_ + 1, p_);
}
// Tests that assertion arguments are evaluated exactly once.
-TEST_F(SingleEvaluationTest, ExceptionTests) {
+TEST_F(single_evaluation_test, exception_tests) {
// successful EXPECT_THROW_MSG
EXPECT_THROW_MSG(
{ // NOLINT
@@ -116,7 +104,7 @@ TEST_F(SingleEvaluationTest, ExceptionTests) {
EXPECT_EQ(4, b_);
}
-TEST_F(SingleEvaluationTest, SystemErrorTests) {
+TEST_F(single_evaluation_test, system_error_tests) {
// successful EXPECT_SYSTEM_ERROR
EXPECT_SYSTEM_ERROR(
{ // NOLINT
@@ -159,14 +147,14 @@ TEST_F(SingleEvaluationTest, SystemErrorTests) {
#if FMT_USE_FCNTL
// Tests that when EXPECT_WRITE fails, it evaluates its message argument
// exactly once.
-TEST_F(SingleEvaluationTest, FailedEXPECT_WRITE) {
+TEST_F(single_evaluation_test, failed_expect_write) {
EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("test"), p_++),
"01234");
EXPECT_EQ(s_ + 1, p_);
}
// Tests that assertion arguments are evaluated exactly once.
-TEST_F(SingleEvaluationTest, WriteTests) {
+TEST_F(single_evaluation_test, write_tests) {
// successful EXPECT_WRITE
EXPECT_WRITE(
stdout,
@@ -192,7 +180,7 @@ TEST_F(SingleEvaluationTest, WriteTests) {
}
// Tests EXPECT_WRITE.
-TEST(ExpectTest, EXPECT_WRITE) {
+TEST(gtest_extra_test, expect_write) {
EXPECT_WRITE(stdout, do_nothing(), "");
EXPECT_WRITE(stdout, std::printf("test"), "test");
EXPECT_WRITE(stderr, std::fprintf(stderr, "test"), "test");
@@ -201,7 +189,7 @@ TEST(ExpectTest, EXPECT_WRITE) {
" Actual: that");
}
-TEST(StreamingAssertionsTest, EXPECT_WRITE) {
+TEST(gtest_extra_test, expect_write_streaming) {
EXPECT_WRITE(stdout, std::printf("test"), "test") << "unexpected failure";
EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, std::printf("test"), "other")
<< "expected failure",
@@ -211,7 +199,7 @@ TEST(StreamingAssertionsTest, EXPECT_WRITE) {
// Tests that the compiler will not complain about unreachable code in the
// EXPECT_THROW_MSG macro.
-TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
+TEST(gtest_extra_test, expect_throw_no_unreachable_code_warning) {
int n = 0;
using std::runtime_error;
EXPECT_THROW_MSG(throw runtime_error(""), runtime_error, "");
@@ -223,7 +211,7 @@ TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
// Tests that the compiler will not complain about unreachable code in the
// EXPECT_SYSTEM_ERROR macro.
-TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
+TEST(gtest_extra_test, expect_system_error_no_unreachable_code_warning) {
int n = 0;
EXPECT_SYSTEM_ERROR(throw fmt::system_error(EDOM, "test"), EDOM, "test");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");
@@ -233,7 +221,7 @@ TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
"");
}
-TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
+TEST(gtest_extra_test, expect_throw_behaves_like_single_statement) {
if (::testing::internal::AlwaysFalse())
EXPECT_THROW_MSG(do_nothing(), std::exception, "");
@@ -243,7 +231,7 @@ TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
do_nothing();
}
-TEST(AssertionSyntaxTest, SystemErrorAssertionBehavesLikeSingleStatement) {
+TEST(gtest_extra_test, expect_system_error_behaves_like_single_statement) {
if (::testing::internal::AlwaysFalse())
EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "");
@@ -253,7 +241,7 @@ TEST(AssertionSyntaxTest, SystemErrorAssertionBehavesLikeSingleStatement) {
do_nothing();
}
-TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) {
+TEST(gtest_extra_test, expect_write_behaves_like_single_statement) {
if (::testing::internal::AlwaysFalse())
EXPECT_WRITE(stdout, std::printf("x"), "x");
@@ -264,7 +252,7 @@ TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) {
}
// Tests EXPECT_THROW_MSG.
-TEST(ExpectTest, EXPECT_THROW_MSG) {
+TEST(gtest_extra_test, expect_throw_msg) {
EXPECT_THROW_MSG(throw_exception(), std::exception, "test");
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::logic_error, "test"),
@@ -282,15 +270,15 @@ TEST(ExpectTest, EXPECT_THROW_MSG) {
}
// Tests EXPECT_SYSTEM_ERROR.
-TEST(ExpectTest, EXPECT_SYSTEM_ERROR) {
+TEST(gtest_extra_test, expect_system_error) {
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_exception(), EDOM, "test"),
"Expected: throw_exception() throws an exception of "
- "type fmt::system_error.\n Actual: it throws a different type.");
+ "type std::system_error.\n Actual: it throws a different type.");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "test"),
- "Expected: do_nothing() throws an exception of type fmt::system_error.\n"
+ "Expected: do_nothing() throws an exception of type std::system_error.\n"
" Actual: it throws nothing.");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other"),
@@ -298,11 +286,11 @@ TEST(ExpectTest, EXPECT_SYSTEM_ERROR) {
"throw_system_error() throws an exception with a different message.\n"
"Expected: {}\n"
" Actual: {}",
- format_system_error(EDOM, "other"),
- format_system_error(EDOM, "test")));
+ system_error_message(EDOM, "other"),
+ system_error_message(EDOM, "test")));
}
-TEST(StreamingAssertionsTest, EXPECT_THROW_MSG) {
+TEST(gtest_extra_test, expect_throw_msg_streaming) {
EXPECT_THROW_MSG(throw_exception(), std::exception, "test")
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
@@ -311,7 +299,7 @@ TEST(StreamingAssertionsTest, EXPECT_THROW_MSG) {
"expected failure");
}
-TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
+TEST(gtest_extra_test, expect_system_error_streaming) {
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test")
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
@@ -320,31 +308,19 @@ TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
"expected failure");
}
-TEST(UtilTest, FormatSystemError) {
- fmt::memory_buffer out;
- fmt::format_system_error(out, EDOM, "test message");
- EXPECT_EQ(to_string(out), format_system_error(EDOM, "test message"));
-}
-
#if FMT_USE_FCNTL
using fmt::buffered_file;
-using fmt::error_code;
using fmt::file;
-TEST(ErrorCodeTest, Ctor) {
- EXPECT_EQ(error_code().get(), 0);
- EXPECT_EQ(error_code(42).get(), 42);
-}
-
-TEST(OutputRedirectTest, ScopedRedirect) {
+TEST(output_redirect_test, scoped_redirect) {
file read_end, write_end;
file::pipe(read_end, write_end);
{
buffered_file file(write_end.fdopen("w"));
std::fprintf(file.get(), "[[[");
{
- OutputRedirect redir(file.get());
+ output_redirect redir(file.get());
std::fprintf(file.get(), "censored");
}
std::fprintf(file.get(), "]]]");
@@ -352,8 +328,8 @@ TEST(OutputRedirectTest, ScopedRedirect) {
EXPECT_READ(read_end, "[[[]]]");
}
-// Test that OutputRedirect handles errors in flush correctly.
-TEST(OutputRedirectTest, FlushErrorInCtor) {
+// Test that output_redirect handles errors in flush correctly.
+TEST(output_redirect_test, flush_error_in_ctor) {
file read_end, write_end;
file::pipe(read_end, write_end);
int write_fd = write_end.descriptor();
@@ -362,47 +338,47 @@ TEST(OutputRedirectTest, FlushErrorInCtor) {
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
- std::unique_ptr<OutputRedirect> redir{nullptr};
- EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new OutputRedirect(f.get())), EBADF,
+ std::unique_ptr<output_redirect> redir{nullptr};
+ EXPECT_SYSTEM_ERROR_NOASSERT(redir.reset(new output_redirect(f.get())), EBADF,
"cannot flush stream");
redir.reset(nullptr);
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
-TEST(OutputRedirectTest, DupErrorInCtor) {
+TEST(output_redirect_test, dup_error_in_ctor) {
buffered_file f = open_buffered_file();
int fd = (f.fileno)();
file copy = file::dup(fd);
FMT_POSIX(close(fd));
- std::unique_ptr<OutputRedirect> redir{nullptr};
+ std::unique_ptr<output_redirect> redir{nullptr};
EXPECT_SYSTEM_ERROR_NOASSERT(
- redir.reset(new OutputRedirect(f.get())), EBADF,
+ redir.reset(new output_redirect(f.get())), EBADF,
fmt::format("cannot duplicate file descriptor {}", fd));
copy.dup2(fd); // "undo" close or dtor will fail
}
-TEST(OutputRedirectTest, RestoreAndRead) {
+TEST(output_redirect_test, restore_and_read) {
file read_end, write_end;
file::pipe(read_end, write_end);
buffered_file file(write_end.fdopen("w"));
std::fprintf(file.get(), "[[[");
- OutputRedirect redir(file.get());
+ output_redirect redir(file.get());
std::fprintf(file.get(), "censored");
- EXPECT_EQ("censored", sanitize(redir.restore_and_read()));
- EXPECT_EQ("", sanitize(redir.restore_and_read()));
+ EXPECT_EQ("censored", redir.restore_and_read());
+ EXPECT_EQ("", redir.restore_and_read());
std::fprintf(file.get(), "]]]");
file = buffered_file();
EXPECT_READ(read_end, "[[[]]]");
}
// Test that OutputRedirect handles errors in flush correctly.
-TEST(OutputRedirectTest, FlushErrorInRestoreAndRead) {
+TEST(output_redirect_test, flush_error_in_restore_and_read) {
file read_end, write_end;
file::pipe(read_end, write_end);
int write_fd = write_end.descriptor();
file write_copy = write_end.dup(write_fd);
buffered_file f = write_end.fdopen("w");
- OutputRedirect redir(f.get());
+ output_redirect redir(f.get());
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
@@ -411,13 +387,13 @@ TEST(OutputRedirectTest, FlushErrorInRestoreAndRead) {
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
-TEST(OutputRedirectTest, ErrorInDtor) {
+TEST(output_redirect_test, error_in_dtor) {
file read_end, write_end;
file::pipe(read_end, write_end);
int write_fd = write_end.descriptor();
file write_copy = write_end.dup(write_fd);
buffered_file f = write_end.fdopen("w");
- std::unique_ptr<OutputRedirect> redir(new OutputRedirect(f.get()));
+ std::unique_ptr<output_redirect> redir(new output_redirect(f.get()));
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
EXPECT_WRITE(
@@ -430,10 +406,8 @@ TEST(OutputRedirectTest, ErrorInDtor) {
FMT_POSIX(close(write_fd));
SUPPRESS_ASSERT(redir.reset(nullptr));
},
- format_system_error(EBADF, "cannot flush stream"));
+ system_error_message(EBADF, "cannot flush stream"));
write_copy.dup2(write_fd); // "undo" close or dtor of buffered_file will fail
}
-#endif // FMT_USE_FILE_DESCRIPTORS
-
-} // namespace
+#endif // FMT_USE_FCNTL
diff --git a/contrib/libs/fmt/test/gtest-extra.cc b/contrib/libs/fmt/test/gtest-extra.cc
index 58628a8a98..1d48a1736d 100644
--- a/contrib/libs/fmt/test/gtest-extra.cc
+++ b/contrib/libs/fmt/test/gtest-extra.cc
@@ -11,24 +11,7 @@
using fmt::file;
-void OutputRedirect::flush() {
-# if EOF != -1
-# error "FMT_RETRY assumes return value of -1 indicating failure"
-# endif
- int result = 0;
- FMT_RETRY(result, fflush(file_));
- if (result != 0) throw fmt::system_error(errno, "cannot flush stream");
-}
-
-void OutputRedirect::restore() {
- if (original_.descriptor() == -1) return; // Already restored.
- flush();
- // Restore the original file.
- original_.dup2(FMT_POSIX(fileno(file_)));
- original_.close();
-}
-
-OutputRedirect::OutputRedirect(FILE* f) : file_(f) {
+output_redirect::output_redirect(FILE* f) : file_(f) {
flush();
int fd = FMT_POSIX(fileno(f));
// Create a file object referring to the original file.
@@ -40,7 +23,7 @@ OutputRedirect::OutputRedirect(FILE* f) : file_(f) {
write_end.dup2(fd);
}
-OutputRedirect::~OutputRedirect() FMT_NOEXCEPT {
+output_redirect::~output_redirect() FMT_NOEXCEPT {
try {
restore();
} catch (const std::exception& e) {
@@ -48,7 +31,23 @@ OutputRedirect::~OutputRedirect() FMT_NOEXCEPT {
}
}
-std::string OutputRedirect::restore_and_read() {
+void output_redirect::flush() {
+ int result = 0;
+ do {
+ result = fflush(file_);
+ } while (result == EOF && errno == EINTR);
+ if (result != 0) throw fmt::system_error(errno, "cannot flush stream");
+}
+
+void output_redirect::restore() {
+ if (original_.descriptor() == -1) return; // Already restored.
+ flush();
+ // Restore the original file.
+ original_.dup2(FMT_POSIX(fileno(file_)));
+ original_.close();
+}
+
+std::string output_redirect::restore_and_read() {
// Restore output.
restore();
@@ -79,9 +78,3 @@ std::string read(file& f, size_t count) {
}
#endif // FMT_USE_FCNTL
-
-std::string format_system_error(int error_code, fmt::string_view message) {
- fmt::memory_buffer out;
- format_system_error(out, error_code, message);
- return to_string(out);
-}
diff --git a/contrib/libs/fmt/test/gtest-extra.h b/contrib/libs/fmt/test/gtest-extra.h
index 010bde066b..f779731748 100644
--- a/contrib/libs/fmt/test/gtest-extra.h
+++ b/contrib/libs/fmt/test/gtest-extra.h
@@ -8,10 +8,17 @@
#ifndef FMT_GTEST_EXTRA_H_
#define FMT_GTEST_EXTRA_H_
+#include <stdlib.h> // _invalid_parameter_handler
+
#include <string>
-#include "fmt/os.h"
-#include <gmock/gmock.h>
+#ifdef FMT_MODULE_TEST
+import fmt;
+#else
+# include "fmt/os.h"
+#endif // FMG_MODULE_TEST
+
+#include "gmock/gmock.h"
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
@@ -51,31 +58,35 @@
FMT_TEST_THROW_(statement, expected_exception, expected_message, \
GTEST_NONFATAL_FAILURE_)
-std::string format_system_error(int error_code, fmt::string_view message);
+inline std::string system_error_message(int error_code,
+ const std::string& message) {
+ auto ec = std::error_code(error_code, std::generic_category());
+ return std::system_error(ec, message).what();
+}
#define EXPECT_SYSTEM_ERROR(statement, error_code, message) \
- EXPECT_THROW_MSG(statement, fmt::system_error, \
- format_system_error(error_code, message))
+ EXPECT_THROW_MSG(statement, std::system_error, \
+ system_error_message(error_code, message))
#if FMT_USE_FCNTL
// Captures file output by redirecting it to a pipe.
// The output it can handle is limited by the pipe capacity.
-class OutputRedirect {
+class output_redirect {
private:
FILE* file_;
fmt::file original_; // Original file passed to redirector.
fmt::file read_end_; // Read end of the pipe where the output is redirected.
- OutputRedirect(const OutputRedirect&) = delete;
- OutputRedirect& operator= (const OutputRedirect&) = delete;
-
void flush();
void restore();
public:
- explicit OutputRedirect(FILE* file);
- ~OutputRedirect() FMT_NOEXCEPT;
+ explicit output_redirect(FILE* file);
+ ~output_redirect() FMT_NOEXCEPT;
+
+ output_redirect(const output_redirect&) = delete;
+ void operator=(const output_redirect&) = delete;
// Restores the original file, reads output from the pipe into a string
// and returns it.
@@ -86,7 +97,7 @@ class OutputRedirect {
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
std::string gtest_expected_output = expected_output; \
- OutputRedirect gtest_redir(file); \
+ output_redirect gtest_redir(file); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
std::string gtest_output = gtest_redir.restore_and_read(); \
if (gtest_output != gtest_expected_output) { \
@@ -108,7 +119,7 @@ class OutputRedirect {
// Suppresses Windows assertions on invalid file descriptors, making
// POSIX functions return proper error codes instead of crashing on Windows.
-class SuppressAssert {
+class suppress_assert {
private:
_invalid_parameter_handler original_handler_;
int original_report_mode_;
@@ -117,19 +128,20 @@ class SuppressAssert {
const wchar_t*, unsigned, uintptr_t) {}
public:
- SuppressAssert()
+ suppress_assert()
: original_handler_(
_set_invalid_parameter_handler(handle_invalid_parameter)),
original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {}
- ~SuppressAssert() {
+ ~suppress_assert() {
_set_invalid_parameter_handler(original_handler_);
_CrtSetReportMode(_CRT_ASSERT, original_report_mode_);
+ (void)original_report_mode_;
}
};
# define SUPPRESS_ASSERT(statement) \
{ \
- SuppressAssert sa; \
+ suppress_assert sa; \
statement; \
}
# else
@@ -143,7 +155,7 @@ class SuppressAssert {
std::string read(fmt::file& f, size_t count);
# define EXPECT_READ(file, expected_content) \
- EXPECT_EQ(expected_content, \
+ EXPECT_EQ(expected_content, \
read(file, fmt::string_view(expected_content).size()))
#else
@@ -156,9 +168,4 @@ std::string read(fmt::file& f, size_t count);
} while (false)
#endif // FMT_USE_FCNTL
-template <typename Mock> struct ScopedMock : testing::StrictMock<Mock> {
- ScopedMock() { Mock::instance = this; }
- ~ScopedMock() { Mock::instance = nullptr; }
-};
-
#endif // FMT_GTEST_EXTRA_H_
diff --git a/contrib/libs/fmt/test/header-only-test.cc b/contrib/libs/fmt/test/header-only-test.cc
index 674dab993d..570f09a563 100644
--- a/contrib/libs/fmt/test/header-only-test.cc
+++ b/contrib/libs/fmt/test/header-only-test.cc
@@ -1,3 +1,11 @@
// Header-only configuration test
#include "fmt/core.h"
+#include "fmt/ostream.h"
+#include "gtest/gtest.h"
+
+#ifndef FMT_HEADER_ONLY
+# error "Not in the header-only mode."
+#endif
+
+TEST(header_only_test, format) { EXPECT_EQ(fmt::format("foo"), "foo"); }
diff --git a/contrib/libs/fmt/test/header-only-test2.cc b/contrib/libs/fmt/test/header-only-test2.cc
deleted file mode 100644
index ea90b604e4..0000000000
--- a/contrib/libs/fmt/test/header-only-test2.cc
+++ /dev/null
@@ -1,3 +0,0 @@
-// Additional translation unit for the header-only configuration test
-
-#include "fmt/core.h"
diff --git a/contrib/libs/fmt/test/locale-test.cc b/contrib/libs/fmt/test/locale-test.cc
deleted file mode 100644
index 7d776b4290..0000000000
--- a/contrib/libs/fmt/test/locale-test.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Formatting library for C++ - locale tests
-//
-// Copyright (c) 2012 - present, Victor Zverovich
-// All rights reserved.
-//
-// For the license information refer to format.h.
-
-#include "fmt/locale.h"
-
-#include <complex>
-
-#include <gmock/gmock.h>
-
-using fmt::detail::max_value;
-
-#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
-template <typename Char> struct numpunct : std::numpunct<Char> {
- protected:
- Char do_decimal_point() const FMT_OVERRIDE { return '?'; }
- std::string do_grouping() const FMT_OVERRIDE { return "\03"; }
- Char do_thousands_sep() const FMT_OVERRIDE { return '~'; }
-};
-
-template <typename Char> struct no_grouping : std::numpunct<Char> {
- protected:
- Char do_decimal_point() const FMT_OVERRIDE { return '.'; }
- std::string do_grouping() const FMT_OVERRIDE { return ""; }
- Char do_thousands_sep() const FMT_OVERRIDE { return ','; }
-};
-
-template <typename Char> struct special_grouping : std::numpunct<Char> {
- protected:
- Char do_decimal_point() const FMT_OVERRIDE { return '.'; }
- std::string do_grouping() const FMT_OVERRIDE { return "\03\02"; }
- Char do_thousands_sep() const FMT_OVERRIDE { return ','; }
-};
-
-template <typename Char> struct small_grouping : std::numpunct<Char> {
- protected:
- Char do_decimal_point() const FMT_OVERRIDE { return '.'; }
- std::string do_grouping() const FMT_OVERRIDE { return "\01"; }
- Char do_thousands_sep() const FMT_OVERRIDE { return ','; }
-};
-
-TEST(LocaleTest, DoubleDecimalPoint) {
- std::locale loc(std::locale(), new numpunct<char>());
- EXPECT_EQ("1?23", fmt::format(loc, "{:L}", 1.23));
-}
-
-TEST(LocaleTest, Format) {
- std::locale loc(std::locale(), new numpunct<char>());
- EXPECT_EQ("1234567", fmt::format(std::locale(), "{:L}", 1234567));
- EXPECT_EQ("1~234~567", fmt::format(loc, "{:L}", 1234567));
- EXPECT_EQ("-1~234~567", fmt::format(loc, "{:L}", -1234567));
- EXPECT_EQ("-256", fmt::format(loc, "{:L}", -256));
- fmt::format_arg_store<fmt::format_context, int> as{1234567};
- EXPECT_EQ("1~234~567", fmt::vformat(loc, "{:L}", fmt::format_args(as)));
- std::string s;
- fmt::format_to(std::back_inserter(s), loc, "{:L}", 1234567);
- EXPECT_EQ("1~234~567", s);
-
- std::locale no_grouping_loc(std::locale(), new no_grouping<char>());
- EXPECT_EQ("1234567", fmt::format(no_grouping_loc, "{:L}", 1234567));
-
- std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
- EXPECT_EQ("1,23,45,678", fmt::format(special_grouping_loc, "{:L}", 12345678));
- EXPECT_EQ("12,345", fmt::format(special_grouping_loc, "{:L}", 12345));
-
- std::locale small_grouping_loc(std::locale(), new small_grouping<char>());
- EXPECT_EQ("4,2,9,4,9,6,7,2,9,5",
- fmt::format(small_grouping_loc, "{:L}", max_value<uint32_t>()));
-}
-
-TEST(LocaleTest, FormatDetaultAlign) {
- std::locale special_grouping_loc(std::locale(), new special_grouping<char>());
- EXPECT_EQ(" 12,345", fmt::format(special_grouping_loc, "{:8L}", 12345));
-}
-
-TEST(LocaleTest, WFormat) {
- std::locale loc(std::locale(), new numpunct<wchar_t>());
- EXPECT_EQ(L"1234567", fmt::format(std::locale(), L"{:L}", 1234567));
- EXPECT_EQ(L"1~234~567", fmt::format(loc, L"{:L}", 1234567));
- fmt::format_arg_store<fmt::wformat_context, int> as{1234567};
- EXPECT_EQ(L"1~234~567", fmt::vformat(loc, L"{:L}", fmt::wformat_args(as)));
- EXPECT_EQ(L"1234567", fmt::format(std::locale("C"), L"{:L}", 1234567));
-
- std::locale no_grouping_loc(std::locale(), new no_grouping<wchar_t>());
- EXPECT_EQ(L"1234567", fmt::format(no_grouping_loc, L"{:L}", 1234567));
-
- std::locale special_grouping_loc(std::locale(),
- new special_grouping<wchar_t>());
- EXPECT_EQ(L"1,23,45,678",
- fmt::format(special_grouping_loc, L"{:L}", 12345678));
-
- std::locale small_grouping_loc(std::locale(), new small_grouping<wchar_t>());
- EXPECT_EQ(L"4,2,9,4,9,6,7,2,9,5",
- fmt::format(small_grouping_loc, L"{:L}", max_value<uint32_t>()));
-}
-
-TEST(LocaleTest, DoubleFormatter) {
- auto loc = std::locale(std::locale(), new special_grouping<char>());
- auto f = fmt::formatter<int>();
- auto parse_ctx = fmt::format_parse_context("L");
- f.parse(parse_ctx);
- char buf[10] = {};
- fmt::basic_format_context<char*, char> format_ctx(
- buf, {}, fmt::detail::locale_ref(loc));
- *f.format(12345, format_ctx) = 0;
- EXPECT_STREQ("12,345", buf);
-}
-
-FMT_BEGIN_NAMESPACE
-template <class charT> struct formatter<std::complex<double>, charT> {
- private:
- detail::dynamic_format_specs<char> specs_;
-
- public:
- typename basic_format_parse_context<charT>::iterator parse(
- basic_format_parse_context<charT>& ctx) {
- using handler_type =
- detail::dynamic_specs_handler<basic_format_parse_context<charT>>;
- detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
- detail::type::string_type);
- auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
- detail::parse_float_type_spec(specs_, ctx.error_handler());
- return it;
- }
-
- template <class FormatContext>
- typename FormatContext::iterator format(const std::complex<double>& c,
- FormatContext& ctx) {
- detail::handle_dynamic_spec<detail::precision_checker>(
- specs_.precision, specs_.precision_ref, ctx);
- auto format_specs = std::string();
- if (specs_.precision > 0)
- format_specs = fmt::format(".{}", specs_.precision);
- if (specs_.type)
- format_specs += specs_.type;
- auto real = fmt::format(ctx.locale().template get<std::locale>(),
- "{:" + format_specs + "}", c.real());
- auto imag = fmt::format(ctx.locale().template get<std::locale>(),
- "{:" + format_specs + "}", c.imag());
- auto fill_align_width = std::string();
- if (specs_.width > 0)
- fill_align_width = fmt::format(">{}", specs_.width);
- return format_to(
- ctx.out(), "{:" + fill_align_width + "}",
- fmt::format(c.real() != 0 ? "({0}+{1}i)" : "{1}i", real, imag));
- }
-};
-FMT_END_NAMESPACE
-
-TEST(FormatTest, Complex) {
- std::string s = fmt::format("{}", std::complex<double>(1, 2));
- EXPECT_EQ(s, "(1+2i)");
- EXPECT_EQ(fmt::format("{:.2f}", std::complex<double>(1, 2)), "(1.00+2.00i)");
- EXPECT_EQ(fmt::format("{:8}", std::complex<double>(1, 2)), " (1+2i)");
-}
-
-#endif // FMT_STATIC_THOUSANDS_SEPARATOR
diff --git a/contrib/libs/fmt/test/mock-allocator.h b/contrib/libs/fmt/test/mock-allocator.h
index dfc13feee7..6a67e08f4f 100644
--- a/contrib/libs/fmt/test/mock-allocator.h
+++ b/contrib/libs/fmt/test/mock-allocator.h
@@ -8,14 +8,18 @@
#ifndef FMT_MOCK_ALLOCATOR_H_
#define FMT_MOCK_ALLOCATOR_H_
-#include "fmt/format.h"
-#include <gmock/gmock.h>
+#include <assert.h> // assert
+#include <stddef.h> // size_t
+
+#include <memory> // std::allocator_traits
+
+#include "gmock/gmock.h"
template <typename T> class mock_allocator {
public:
mock_allocator() {}
mock_allocator(const mock_allocator&) {}
- typedef T value_type;
+ using value_type = T;
MOCK_METHOD1_T(allocate, T*(size_t n));
MOCK_METHOD2_T(deallocate, void(T* p, size_t n));
};
@@ -30,7 +34,7 @@ template <typename Allocator> class allocator_ref {
}
public:
- typedef typename Allocator::value_type value_type;
+ using value_type = typename Allocator::value_type;
explicit allocator_ref(Allocator* alloc = nullptr) : alloc_(alloc) {}
diff --git a/contrib/libs/fmt/test/os-test.cc b/contrib/libs/fmt/test/os-test.cc
index 359b5ff8ce..5b5ef76ed6 100644
--- a/contrib/libs/fmt/test/os-test.cc
+++ b/contrib/libs/fmt/test/os-test.cc
@@ -19,20 +19,21 @@
#endif
using fmt::buffered_file;
-using fmt::error_code;
+using testing::HasSubstr;
+using wstring_view = fmt::basic_string_view<wchar_t>;
#ifdef _WIN32
# include <windows.h>
-TEST(UtilTest, UTF16ToUTF8) {
- std::string s = "ёжик";
+TEST(util_test, utf16_to_utf8) {
+ auto s = std::string("ёжик");
fmt::detail::utf16_to_utf8 u(L"\x0451\x0436\x0438\x043A");
EXPECT_EQ(s, u.str());
EXPECT_EQ(s.size(), u.size());
}
-TEST(UtilTest, UTF16ToUTF8EmptyString) {
+TEST(util_test, utf16_to_utf8_empty_string) {
std::string s = "";
fmt::detail::utf16_to_utf8 u(L"");
EXPECT_EQ(s, u.str());
@@ -40,70 +41,78 @@ TEST(UtilTest, UTF16ToUTF8EmptyString) {
}
template <typename Converter, typename Char>
-void check_utf_conversion_error(
- const char* message,
- fmt::basic_string_view<Char> str = fmt::basic_string_view<Char>(0, 1)) {
+void check_utf_conversion_error(const char* message,
+ fmt::basic_string_view<Char> str =
+ fmt::basic_string_view<Char>(nullptr, 1)) {
fmt::memory_buffer out;
fmt::detail::format_windows_error(out, ERROR_INVALID_PARAMETER, message);
- fmt::system_error error(0, "");
+ auto error = std::system_error(std::error_code());
try {
(Converter)(str);
- } catch (const fmt::system_error& e) {
+ } catch (const std::system_error& e) {
error = e;
}
- EXPECT_EQ(ERROR_INVALID_PARAMETER, error.error_code());
- EXPECT_EQ(fmt::to_string(out), error.what());
+ EXPECT_EQ(ERROR_INVALID_PARAMETER, error.code().value());
+ EXPECT_THAT(error.what(), HasSubstr(fmt::to_string(out)));
}
-TEST(UtilTest, UTF16ToUTF8Error) {
+TEST(util_test, utf16_to_utf8_error) {
check_utf_conversion_error<fmt::detail::utf16_to_utf8, wchar_t>(
"cannot convert string from UTF-16 to UTF-8");
}
-TEST(UtilTest, UTF16ToUTF8Convert) {
+TEST(util_test, utf16_to_utf8_convert) {
fmt::detail::utf16_to_utf8 u;
- EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::wstring_view(0, 1)));
+ EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(wstring_view(nullptr, 1)));
EXPECT_EQ(ERROR_INVALID_PARAMETER,
- u.convert(fmt::wstring_view(L"foo", INT_MAX + 1u)));
-}
-
-TEST(UtilTest, FormatWindowsError) {
- LPWSTR message = 0;
- FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- 0, ERROR_FILE_EXISTS,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- reinterpret_cast<LPWSTR>(&message), 0, 0);
- fmt::detail::utf16_to_utf8 utf8_message(message);
+ u.convert(wstring_view(L"foo", INT_MAX + 1u)));
+}
+
+TEST(os_test, format_std_error_code) {
+ EXPECT_EQ("generic:42",
+ fmt::format(FMT_STRING("{0}"),
+ std::error_code(42, std::generic_category())));
+ EXPECT_EQ("system:42",
+ fmt::format(FMT_STRING("{0}"),
+ std::error_code(42, fmt::system_category())));
+ EXPECT_EQ("system:-42",
+ fmt::format(FMT_STRING("{0}"),
+ std::error_code(-42, fmt::system_category())));
+}
+
+TEST(os_test, format_windows_error) {
+ LPWSTR message = nullptr;
+ auto result = FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, ERROR_FILE_EXISTS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<LPWSTR>(&message), 0, nullptr);
+ fmt::detail::utf16_to_utf8 utf8_message(wstring_view(message, result - 2));
LocalFree(message);
fmt::memory_buffer actual_message;
fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS, "test");
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
fmt::to_string(actual_message));
actual_message.resize(0);
- auto max_size = fmt::detail::max_value<size_t>() / 2;
- fmt::detail::format_windows_error(actual_message, ERROR_FILE_EXISTS,
- fmt::string_view(nullptr, max_size));
- EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS),
- fmt::to_string(actual_message));
}
-TEST(UtilTest, FormatLongWindowsError) {
- LPWSTR message = 0;
+TEST(os_test, format_long_windows_error) {
+ LPWSTR message = nullptr;
// this error code is not available on all Windows platforms and
// Windows SDKs, so do not fail the test if the error string cannot
// be retrieved.
- const int provisioning_not_allowed =
- 0x80284013L /*TBS_E_PROVISIONING_NOT_ALLOWED*/;
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- 0, static_cast<DWORD>(provisioning_not_allowed),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- reinterpret_cast<LPWSTR>(&message), 0, 0) == 0) {
+ int provisioning_not_allowed = 0x80284013L; // TBS_E_PROVISIONING_NOT_ALLOWED
+ auto result = FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, static_cast<DWORD>(provisioning_not_allowed),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<LPWSTR>(&message), 0, nullptr);
+ if (result == 0) {
+ LocalFree(message);
return;
}
- fmt::detail::utf16_to_utf8 utf8_message(message);
+ fmt::detail::utf16_to_utf8 utf8_message(wstring_view(message, result - 2));
LocalFree(message);
fmt::memory_buffer actual_message;
fmt::detail::format_windows_error(actual_message, provisioning_not_allowed,
@@ -112,20 +121,20 @@ TEST(UtilTest, FormatLongWindowsError) {
fmt::to_string(actual_message));
}
-TEST(UtilTest, WindowsError) {
- fmt::system_error error(0, "");
+TEST(os_test, windows_error) {
+ auto error = std::system_error(std::error_code());
try {
throw fmt::windows_error(ERROR_FILE_EXISTS, "test {}", "error");
- } catch (const fmt::system_error& e) {
+ } catch (const std::system_error& e) {
error = e;
}
fmt::memory_buffer message;
fmt::detail::format_windows_error(message, ERROR_FILE_EXISTS, "test error");
- EXPECT_EQ(to_string(message), error.what());
- EXPECT_EQ(ERROR_FILE_EXISTS, error.error_code());
+ EXPECT_THAT(error.what(), HasSubstr(to_string(message)));
+ EXPECT_EQ(ERROR_FILE_EXISTS, error.code().value());
}
-TEST(UtilTest, ReportWindowsError) {
+TEST(os_test, report_windows_error) {
fmt::memory_buffer out;
fmt::detail::format_windows_error(out, ERROR_FILE_EXISTS, "test error");
out.push_back('\n');
@@ -140,30 +149,24 @@ TEST(UtilTest, ReportWindowsError) {
using fmt::file;
-// Checks if the file is open by reading one character from it.
-static bool isopen(int fd) {
- char buffer;
- return FMT_POSIX(read(fd, &buffer, 1)) == 1;
-}
-
-static bool isclosed(int fd) {
+bool isclosed(int fd) {
char buffer;
- std::streamsize result = 0;
+ auto result = std::streamsize();
SUPPRESS_ASSERT(result = FMT_POSIX(read(fd, &buffer, 1)));
return result == -1 && errno == EBADF;
}
// Opens a file for reading.
-static file open_file() {
+file open_file() {
file read_end, write_end;
file::pipe(read_end, write_end);
- write_end.write(FILE_CONTENT, std::strlen(FILE_CONTENT));
+ write_end.write(file_content, std::strlen(file_content));
write_end.close();
return read_end;
}
// Attempts to write a string to a file.
-static void write(file& f, fmt::string_view s) {
+void write(file& f, fmt::string_view s) {
size_t num_chars_left = s.size();
const char* ptr = s.data();
do {
@@ -175,12 +178,12 @@ static void write(file& f, fmt::string_view s) {
} while (num_chars_left != 0);
}
-TEST(BufferedFileTest, DefaultCtor) {
- buffered_file f;
+TEST(buffered_file_test, default_ctor) {
+ auto f = buffered_file();
EXPECT_TRUE(f.get() == nullptr);
}
-TEST(BufferedFileTest, MoveCtor) {
+TEST(buffered_file_test, move_ctor) {
buffered_file bf = open_buffered_file();
FILE* fp = bf.get();
EXPECT_TRUE(fp != nullptr);
@@ -189,7 +192,7 @@ TEST(BufferedFileTest, MoveCtor) {
EXPECT_TRUE(bf.get() == nullptr);
}
-TEST(BufferedFileTest, MoveAssignment) {
+TEST(buffered_file_test, move_assignment) {
buffered_file bf = open_buffered_file();
FILE* fp = bf.get();
EXPECT_TRUE(fp != nullptr);
@@ -199,7 +202,7 @@ TEST(BufferedFileTest, MoveAssignment) {
EXPECT_TRUE(bf.get() == nullptr);
}
-TEST(BufferedFileTest, MoveAssignmentClosesFile) {
+TEST(buffered_file_test, move_assignment_closes_file) {
buffered_file bf = open_buffered_file();
buffered_file bf2 = open_buffered_file();
int old_fd = bf2.fileno();
@@ -207,27 +210,27 @@ TEST(BufferedFileTest, MoveAssignmentClosesFile) {
EXPECT_TRUE(isclosed(old_fd));
}
-TEST(BufferedFileTest, MoveFromTemporaryInCtor) {
+TEST(buffered_file_test, move_from_temporary_in_ctor) {
FILE* fp = nullptr;
- buffered_file f(open_buffered_file(&fp));
+ buffered_file f = open_buffered_file(&fp);
EXPECT_EQ(fp, f.get());
}
-TEST(BufferedFileTest, MoveFromTemporaryInAssignment) {
+TEST(buffered_file_test, move_from_temporary_in_assignment) {
FILE* fp = nullptr;
- buffered_file f;
+ auto f = buffered_file();
f = open_buffered_file(&fp);
EXPECT_EQ(fp, f.get());
}
-TEST(BufferedFileTest, MoveFromTemporaryInAssignmentClosesFile) {
+TEST(buffered_file_test, move_from_temporary_in_assignment_closes_file) {
buffered_file f = open_buffered_file();
int old_fd = f.fileno();
f = open_buffered_file();
EXPECT_TRUE(isclosed(old_fd));
}
-TEST(BufferedFileTest, CloseFileInDtor) {
+TEST(buffered_file_test, close_file_in_dtor) {
int fd = 0;
{
buffered_file f = open_buffered_file();
@@ -236,8 +239,9 @@ TEST(BufferedFileTest, CloseFileInDtor) {
EXPECT_TRUE(isclosed(fd));
}
-TEST(BufferedFileTest, CloseErrorInDtor) {
- std::unique_ptr<buffered_file> f(new buffered_file(open_buffered_file()));
+TEST(buffered_file_test, close_error_in_dtor) {
+ auto f =
+ std::unique_ptr<buffered_file>(new buffered_file(open_buffered_file()));
EXPECT_WRITE(
stderr,
{
@@ -248,10 +252,10 @@ TEST(BufferedFileTest, CloseErrorInDtor) {
FMT_POSIX(close(f->fileno()));
SUPPRESS_ASSERT(f.reset(nullptr));
},
- format_system_error(EBADF, "cannot close file") + "\n");
+ system_error_message(EBADF, "cannot close file") + "\n");
}
-TEST(BufferedFileTest, Close) {
+TEST(buffered_file_test, close) {
buffered_file f = open_buffered_file();
int fd = f.fileno();
f.close();
@@ -259,49 +263,49 @@ TEST(BufferedFileTest, Close) {
EXPECT_TRUE(isclosed(fd));
}
-TEST(BufferedFileTest, CloseError) {
+TEST(buffered_file_test, close_error) {
buffered_file f = open_buffered_file();
FMT_POSIX(close(f.fileno()));
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
EXPECT_TRUE(f.get() == nullptr);
}
-TEST(BufferedFileTest, Fileno) {
- buffered_file f;
-# ifndef __COVERITY__
- // fileno on a null FILE pointer either crashes or returns an error.
- // Disable Coverity because this is intentional.
- EXPECT_DEATH_IF_SUPPORTED(
- {
- try {
- f.fileno();
- } catch (const fmt::system_error&) {
- std::exit(1);
- }
- },
- "");
-# endif
- f = open_buffered_file();
+TEST(buffered_file_test, fileno) {
+ auto f = open_buffered_file();
EXPECT_TRUE(f.fileno() != -1);
file copy = file::dup(f.fileno());
- EXPECT_READ(copy, FILE_CONTENT);
+ EXPECT_READ(copy, file_content);
}
-TEST(OStreamTest, Move) {
+TEST(ostream_test, move) {
fmt::ostream out = fmt::output_file("test-file");
fmt::ostream moved(std::move(out));
moved.print("hello");
}
-TEST(OStreamTest, Print) {
+TEST(ostream_test, move_while_holding_data) {
+ {
+ fmt::ostream out = fmt::output_file("test-file");
+ out.print("Hello, ");
+ fmt::ostream moved(std::move(out));
+ moved.print("world!\n");
+ }
+ {
+ file in("test-file", file::RDONLY);
+ EXPECT_READ(in, "Hello, world!\n");
+ }
+}
+
+TEST(ostream_test, print) {
fmt::ostream out = fmt::output_file("test-file");
- out.print("The answer is {}.\n", 42);
+ out.print("The answer is {}.\n",
+ fmt::join(std::initializer_list<int>{42}, ", "));
out.close();
file in("test-file", file::RDONLY);
EXPECT_READ(in, "The answer is 42.\n");
}
-TEST(OStreamTest, BufferBoundary) {
+TEST(ostream_test, buffer_boundary) {
auto str = std::string(4096, 'x');
fmt::ostream out = fmt::output_file("test-file");
out.print("{}", str);
@@ -311,33 +315,57 @@ TEST(OStreamTest, BufferBoundary) {
EXPECT_READ(in, str + str);
}
-TEST(OStreamTest, BufferSize) {
- fmt::ostream out = fmt::output_file("test-file", fmt::buffer_size=1);
+TEST(ostream_test, buffer_size) {
+ fmt::ostream out = fmt::output_file("test-file", fmt::buffer_size = 1);
out.print("{}", "foo");
out.close();
file in("test-file", file::RDONLY);
EXPECT_READ(in, "foo");
}
-TEST(FileTest, DefaultCtor) {
+TEST(ostream_test, truncate) {
+ {
+ fmt::ostream out = fmt::output_file("test-file");
+ out.print("0123456789");
+ }
+ {
+ fmt::ostream out = fmt::output_file("test-file");
+ out.print("foo");
+ }
+ file in("test-file", file::RDONLY);
+ EXPECT_EQ("foo", read(in, 4));
+}
+
+TEST(ostream_test, flush) {
+ auto out = fmt::output_file("test-file");
+ out.print("x");
+ out.flush();
+ auto in = fmt::file("test-file", file::RDONLY);
+ EXPECT_READ(in, "x");
+}
+
+TEST(file_test, default_ctor) {
file f;
EXPECT_EQ(-1, f.descriptor());
}
-TEST(FileTest, OpenBufferedFileInCtor) {
+TEST(file_test, open_buffered_file_in_ctor) {
FILE* fp = safe_fopen("test-file", "w");
- std::fputs(FILE_CONTENT, fp);
+ std::fputs(file_content, fp);
std::fclose(fp);
file f("test-file", file::RDONLY);
- ASSERT_TRUE(isopen(f.descriptor()));
+ // Check if the file is open by reading one character from it.
+ char buffer;
+ bool isopen = FMT_POSIX(read(f.descriptor(), &buffer, 1)) == 1;
+ ASSERT_TRUE(isopen);
}
-TEST(FileTest, OpenBufferedFileError) {
+TEST(file_test, open_buffered_file_error) {
EXPECT_SYSTEM_ERROR(file("nonexistent", file::RDONLY), ENOENT,
"cannot open file nonexistent");
}
-TEST(FileTest, MoveCtor) {
+TEST(file_test, move_ctor) {
file f = open_file();
int fd = f.descriptor();
EXPECT_NE(-1, fd);
@@ -346,7 +374,7 @@ TEST(FileTest, MoveCtor) {
EXPECT_EQ(-1, f.descriptor());
}
-TEST(FileTest, MoveAssignment) {
+TEST(file_test, move_assignment) {
file f = open_file();
int fd = f.descriptor();
EXPECT_NE(-1, fd);
@@ -356,7 +384,7 @@ TEST(FileTest, MoveAssignment) {
EXPECT_EQ(-1, f.descriptor());
}
-TEST(FileTest, MoveAssignmentClosesFile) {
+TEST(file_test, move_assignment_closes_file) {
file f = open_file();
file f2 = open_file();
int old_fd = f2.descriptor();
@@ -364,34 +392,34 @@ TEST(FileTest, MoveAssignmentClosesFile) {
EXPECT_TRUE(isclosed(old_fd));
}
-static file OpenBufferedFile(int& fd) {
+file open_buffered_file(int& fd) {
file f = open_file();
fd = f.descriptor();
return f;
}
-TEST(FileTest, MoveFromTemporaryInCtor) {
+TEST(file_test, move_from_temporary_in_ctor) {
int fd = 0xdead;
- file f(OpenBufferedFile(fd));
+ file f(open_buffered_file(fd));
EXPECT_EQ(fd, f.descriptor());
}
-TEST(FileTest, MoveFromTemporaryInAssignment) {
+TEST(file_test, move_from_temporary_in_assignment) {
int fd = 0xdead;
file f;
- f = OpenBufferedFile(fd);
+ f = open_buffered_file(fd);
EXPECT_EQ(fd, f.descriptor());
}
-TEST(FileTest, MoveFromTemporaryInAssignmentClosesFile) {
+TEST(file_test, move_from_temporary_in_assignment_closes_file) {
int fd = 0xdead;
file f = open_file();
int old_fd = f.descriptor();
- f = OpenBufferedFile(fd);
+ f = open_buffered_file(fd);
EXPECT_TRUE(isclosed(old_fd));
}
-TEST(FileTest, CloseFileInDtor) {
+TEST(file_test, close_file_in_dtor) {
int fd = 0;
{
file f = open_file();
@@ -400,7 +428,7 @@ TEST(FileTest, CloseFileInDtor) {
EXPECT_TRUE(isclosed(fd));
}
-TEST(FileTest, CloseErrorInDtor) {
+TEST(file_test, close_error_in_dtor) {
std::unique_ptr<file> f(new file(open_file()));
EXPECT_WRITE(
stderr,
@@ -412,10 +440,10 @@ TEST(FileTest, CloseErrorInDtor) {
FMT_POSIX(close(f->descriptor()));
SUPPRESS_ASSERT(f.reset(nullptr));
},
- format_system_error(EBADF, "cannot close file") + "\n");
+ system_error_message(EBADF, "cannot close file") + "\n");
}
-TEST(FileTest, Close) {
+TEST(file_test, close) {
file f = open_file();
int fd = f.descriptor();
f.close();
@@ -423,19 +451,19 @@ TEST(FileTest, Close) {
EXPECT_TRUE(isclosed(fd));
}
-TEST(FileTest, CloseError) {
+TEST(file_test, close_error) {
file f = open_file();
FMT_POSIX(close(f.descriptor()));
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
EXPECT_EQ(-1, f.descriptor());
}
-TEST(FileTest, Read) {
+TEST(file_test, read) {
file f = open_file();
- EXPECT_READ(f, FILE_CONTENT);
+ EXPECT_READ(f, file_content);
}
-TEST(FileTest, ReadError) {
+TEST(file_test, read_error) {
file f("test-file", file::WRONLY);
char buf;
// We intentionally read from a file opened in the write-only mode to
@@ -443,7 +471,7 @@ TEST(FileTest, ReadError) {
EXPECT_SYSTEM_ERROR(f.read(&buf, 1), EBADF, "cannot read from file");
}
-TEST(FileTest, Write) {
+TEST(file_test, write) {
file read_end, write_end;
file::pipe(read_end, write_end);
write(write_end, "test");
@@ -451,61 +479,61 @@ TEST(FileTest, Write) {
EXPECT_READ(read_end, "test");
}
-TEST(FileTest, WriteError) {
+TEST(file_test, write_error) {
file f("test-file", file::RDONLY);
// We intentionally write to a file opened in the read-only mode to
// cause error.
EXPECT_SYSTEM_ERROR(f.write(" ", 1), EBADF, "cannot write to file");
}
-TEST(FileTest, Dup) {
+TEST(file_test, dup) {
file f = open_file();
file copy = file::dup(f.descriptor());
EXPECT_NE(f.descriptor(), copy.descriptor());
- EXPECT_EQ(FILE_CONTENT, read(copy, std::strlen(FILE_CONTENT)));
+ EXPECT_EQ(file_content, read(copy, std::strlen(file_content)));
}
# ifndef __COVERITY__
-TEST(FileTest, DupError) {
+TEST(file_test, dup_error) {
int value = -1;
EXPECT_SYSTEM_ERROR_NOASSERT(file::dup(value), EBADF,
"cannot duplicate file descriptor -1");
}
# endif
-TEST(FileTest, Dup2) {
+TEST(file_test, dup2) {
file f = open_file();
file copy = open_file();
f.dup2(copy.descriptor());
EXPECT_NE(f.descriptor(), copy.descriptor());
- EXPECT_READ(copy, FILE_CONTENT);
+ EXPECT_READ(copy, file_content);
}
-TEST(FileTest, Dup2Error) {
+TEST(file_test, dup2_error) {
file f = open_file();
EXPECT_SYSTEM_ERROR_NOASSERT(
f.dup2(-1), EBADF,
fmt::format("cannot duplicate file descriptor {} to -1", f.descriptor()));
}
-TEST(FileTest, Dup2NoExcept) {
+TEST(file_test, dup2_noexcept) {
file f = open_file();
file copy = open_file();
- error_code ec;
+ std::error_code ec;
f.dup2(copy.descriptor(), ec);
- EXPECT_EQ(ec.get(), 0);
+ EXPECT_EQ(ec.value(), 0);
EXPECT_NE(f.descriptor(), copy.descriptor());
- EXPECT_READ(copy, FILE_CONTENT);
+ EXPECT_READ(copy, file_content);
}
-TEST(FileTest, Dup2NoExceptError) {
+TEST(file_test, dup2_noexcept_error) {
file f = open_file();
- error_code ec;
+ std::error_code ec;
SUPPRESS_ASSERT(f.dup2(-1, ec));
- EXPECT_EQ(EBADF, ec.get());
+ EXPECT_EQ(EBADF, ec.value());
}
-TEST(FileTest, Pipe) {
+TEST(file_test, pipe) {
file read_end, write_end;
file::pipe(read_end, write_end);
EXPECT_NE(-1, read_end.descriptor());
@@ -514,19 +542,10 @@ TEST(FileTest, Pipe) {
EXPECT_READ(read_end, "test");
}
-TEST(FileTest, Fdopen) {
+TEST(file_test, fdopen) {
file read_end, write_end;
file::pipe(read_end, write_end);
int read_fd = read_end.descriptor();
EXPECT_EQ(read_fd, FMT_POSIX(fileno(read_end.fdopen("r").get())));
}
-
-# ifdef FMT_LOCALE
-TEST(LocaleTest, Strtod) {
- fmt::locale loc;
- const char *start = "4.2", *ptr = start;
- EXPECT_EQ(4.2, loc.strtod(ptr));
- EXPECT_EQ(start + 3, ptr);
-}
-# endif
#endif // FMT_USE_FCNTL
diff --git a/contrib/libs/fmt/test/ostream-test.cc b/contrib/libs/fmt/test/ostream-test.cc
index 4cef5a78c4..f81039e5bb 100644
--- a/contrib/libs/fmt/test/ostream-test.cc
+++ b/contrib/libs/fmt/test/ostream-test.cc
@@ -7,14 +7,15 @@
#include "fmt/format.h"
+using fmt::runtime;
+
struct test {};
// Test that there is no issues with specializations when fmt/ostream.h is
// included after fmt/format.h.
namespace fmt {
template <> struct formatter<test> : formatter<int> {
- template <typename FormatContext>
- typename FormatContext::iterator format(const test&, FormatContext& ctx) {
+ auto format(const test&, format_context& ctx) -> decltype(ctx.out()) {
return formatter<int>::format(42, ctx);
}
};
@@ -22,21 +23,19 @@ template <> struct formatter<test> : formatter<int> {
#include <sstream>
+#include "fmt/compile.h"
#include "fmt/ostream.h"
#include "fmt/ranges.h"
-#include <gmock/gmock.h>
+#include "gmock/gmock.h"
#include "gtest-extra.h"
#include "util.h"
-using fmt::format;
-using fmt::format_error;
-
-static std::ostream& operator<<(std::ostream& os, const Date& d) {
+std::ostream& operator<<(std::ostream& os, const date& d) {
os << d.year() << '-' << d.month() << '-' << d.day();
return os;
}
-static std::wostream& operator<<(std::wostream& os, const Date& d) {
+std::wostream& operator<<(std::wostream& os, const date& d) {
os << d.year() << L'-' << d.month() << L'-' << d.day();
return os;
}
@@ -44,99 +43,63 @@ static std::wostream& operator<<(std::wostream& os, const Date& d) {
// Make sure that overloaded comma operators do no harm to is_streamable.
struct type_with_comma_op {};
template <typename T> void operator,(type_with_comma_op, const T&);
-template <typename T> type_with_comma_op operator<<(T&, const Date&);
+template <typename T> type_with_comma_op operator<<(T&, const date&);
enum streamable_enum {};
-static std::ostream& operator<<(std::ostream& os, streamable_enum) {
- return os << "streamable_enum";
-}
-static std::wostream& operator<<(std::wostream& os, streamable_enum) {
- return os << L"streamable_enum";
+std::ostream& operator<<(std::ostream& os, streamable_enum) {
+ return os << "streamable_enum";
}
enum unstreamable_enum {};
-TEST(OStreamTest, Enum) {
+TEST(ostream_test, enum) {
EXPECT_EQ("streamable_enum", fmt::format("{}", streamable_enum()));
EXPECT_EQ("0", fmt::format("{}", unstreamable_enum()));
- EXPECT_EQ(L"streamable_enum", fmt::format(L"{}", streamable_enum()));
- EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum()));
-}
-
-struct test_arg_formatter
- : fmt::detail::arg_formatter<fmt::format_context::iterator, char> {
- fmt::format_parse_context parse_ctx;
- test_arg_formatter(fmt::format_context& ctx, fmt::format_specs& s)
- : fmt::detail::arg_formatter<fmt::format_context::iterator, char>(
- ctx, &parse_ctx, &s),
- parse_ctx("") {}
-};
-
-TEST(OStreamTest, CustomArg) {
- fmt::memory_buffer buffer;
- fmt::format_context ctx(fmt::detail::buffer_appender<char>{buffer},
- fmt::format_args());
- fmt::format_specs spec;
- test_arg_formatter af(ctx, spec);
- fmt::visit_format_arg(
- af, fmt::detail::make_arg<fmt::format_context>(streamable_enum()));
- EXPECT_EQ("streamable_enum", std::string(buffer.data(), buffer.size()));
}
-TEST(OStreamTest, Format) {
- EXPECT_EQ("a string", format("{0}", TestString("a string")));
- std::string s = format("The date is {0}", Date(2012, 12, 9));
- EXPECT_EQ("The date is 2012-12-9", s);
- Date date(2012, 12, 9);
- EXPECT_EQ(L"The date is 2012-12-9",
- format(L"The date is {0}", Date(2012, 12, 9)));
+TEST(ostream_test, format) {
+ EXPECT_EQ("a string", fmt::format("{0}", test_string("a string")));
+ EXPECT_EQ("The date is 2012-12-9",
+ fmt::format("The date is {0}", date(2012, 12, 9)));
}
-TEST(OStreamTest, FormatSpecs) {
- EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
- EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
-#if FMT_DEPRECATED_NUMERIC_ALIGN
- EXPECT_THROW_MSG(format("{0:=5}", TestString("def")), format_error,
- "format specifier requires numeric argument");
-#endif
- EXPECT_EQ(" def ", format("{0:^5}", TestString("def")));
- EXPECT_EQ("def**", format("{0:*<5}", TestString("def")));
- EXPECT_THROW_MSG(format("{0:+}", TestString()), format_error,
- "format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:-}", TestString()), format_error,
- "format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0: }", TestString()), format_error,
- "format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:#}", TestString()), format_error,
- "format specifier requires numeric argument");
- EXPECT_THROW_MSG(format("{0:05}", TestString()), format_error,
- "format specifier requires numeric argument");
- EXPECT_EQ("test ", format("{0:13}", TestString("test")));
- EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13));
- EXPECT_EQ("te", format("{0:.2}", TestString("test")));
- EXPECT_EQ("te", format("{0:.{1}}", TestString("test"), 2));
+TEST(ostream_test, format_specs) {
+ using fmt::format_error;
+ EXPECT_EQ("def ", fmt::format("{0:<5}", test_string("def")));
+ EXPECT_EQ(" def", fmt::format("{0:>5}", test_string("def")));
+ EXPECT_EQ(" def ", fmt::format("{0:^5}", test_string("def")));
+ EXPECT_EQ("def**", fmt::format("{0:*<5}", test_string("def")));
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), test_string()),
+ format_error, "format specifier requires numeric argument");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), test_string()),
+ format_error, "format specifier requires numeric argument");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), test_string()),
+ format_error, "format specifier requires numeric argument");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:#}"), test_string()),
+ format_error, "format specifier requires numeric argument");
+ EXPECT_THROW_MSG((void)fmt::format(runtime("{0:05}"), test_string()),
+ format_error, "format specifier requires numeric argument");
+ EXPECT_EQ("test ", fmt::format("{0:13}", test_string("test")));
+ EXPECT_EQ("test ", fmt::format("{0:{1}}", test_string("test"), 13));
+ EXPECT_EQ("te", fmt::format("{0:.2}", test_string("test")));
+ EXPECT_EQ("te", fmt::format("{0:.{1}}", test_string("test"), 2));
}
-struct EmptyTest {};
-static std::ostream& operator<<(std::ostream& os, EmptyTest) {
- return os << "";
-}
+struct empty_test {};
+std::ostream& operator<<(std::ostream& os, empty_test) { return os << ""; }
-TEST(OStreamTest, EmptyCustomOutput) {
- EXPECT_EQ("", fmt::format("{}", EmptyTest()));
+TEST(ostream_test, empty_custom_output) {
+ EXPECT_EQ("", fmt::format("{}", empty_test()));
}
-TEST(OStreamTest, Print) {
+TEST(ostream_test, print) {
std::ostringstream os;
fmt::print(os, "Don't {}!", "panic");
EXPECT_EQ("Don't panic!", os.str());
- std::wostringstream wos;
- fmt::print(wos, L"Don't {}!", L"panic");
- EXPECT_EQ(L"Don't panic!", wos.str());
}
-TEST(OStreamTest, WriteToOStream) {
+TEST(ostream_test, write_to_ostream) {
std::ostringstream os;
fmt::memory_buffer buffer;
const char* foo = "foo";
@@ -145,32 +108,33 @@ TEST(OStreamTest, WriteToOStream) {
EXPECT_EQ("foo", os.str());
}
-TEST(OStreamTest, WriteToOStreamMaxSize) {
- size_t max_size = fmt::detail::max_value<size_t>();
- std::streamsize max_streamsize = fmt::detail::max_value<std::streamsize>();
+TEST(ostream_test, write_to_ostream_max_size) {
+ auto max_size = fmt::detail::max_value<size_t>();
+ auto max_streamsize = fmt::detail::max_value<std::streamsize>();
if (max_size <= fmt::detail::to_unsigned(max_streamsize)) return;
struct test_buffer final : fmt::detail::buffer<char> {
explicit test_buffer(size_t size)
- : fmt::detail::buffer<char>(nullptr, size, size) {}
- void grow(size_t) {}
+ : fmt::detail::buffer<char>(nullptr, size, size) {}
+ void grow(size_t) override {}
} buffer(max_size);
struct mock_streambuf : std::streambuf {
MOCK_METHOD2(xsputn, std::streamsize(const void* s, std::streamsize n));
- std::streamsize xsputn(const char* s, std::streamsize n) {
+ std::streamsize xsputn(const char* s, std::streamsize n) override {
const void* v = s;
return xsputn(v, n);
}
} streambuf;
struct test_ostream : std::ostream {
- explicit test_ostream(mock_streambuf& buffer) : std::ostream(&buffer) {}
+ explicit test_ostream(mock_streambuf& output_buffer)
+ : std::ostream(&output_buffer) {}
} os(streambuf);
testing::InSequence sequence;
const char* data = nullptr;
- typedef std::make_unsigned<std::streamsize>::type ustreamsize;
+ using ustreamsize = std::make_unsigned<std::streamsize>::type;
ustreamsize size = max_size;
do {
auto n = std::min(size, fmt::detail::to_unsigned(max_streamsize));
@@ -182,68 +146,62 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
fmt::detail::write_buffer(os, buffer);
}
-TEST(OStreamTest, Join) {
+TEST(ostream_test, join) {
int v[3] = {1, 2, 3};
EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join(v, v + 3, ", ")));
}
+TEST(ostream_test, join_fallback_formatter) {
+ auto strs = std::vector<test_string>{test_string("foo"), test_string("bar")};
+ EXPECT_EQ("foo, bar", fmt::format("{}", fmt::join(strs, ", ")));
+}
+
#if FMT_USE_CONSTEXPR
-TEST(OStreamTest, ConstexprString) {
+TEST(ostream_test, constexpr_string) {
EXPECT_EQ("42", format(FMT_STRING("{}"), std::string("42")));
- EXPECT_EQ("a string", format(FMT_STRING("{0}"), TestString("a string")));
+ EXPECT_EQ("a string", format(FMT_STRING("{0}"), test_string("a string")));
}
#endif
namespace fmt_test {
-struct ABC {};
+struct abc {};
-template <typename Output> Output& operator<<(Output& out, ABC) {
- out << "ABC";
- return out;
+template <typename Output> Output& operator<<(Output& out, abc) {
+ return out << "abc";
}
} // namespace fmt_test
-template <typename T> struct TestTemplate {};
+template <typename T> struct test_template {};
template <typename T>
-std::ostream& operator<<(std::ostream& os, TestTemplate<T>) {
+std::ostream& operator<<(std::ostream& os, test_template<T>) {
return os << 1;
}
namespace fmt {
-template <typename T> struct formatter<TestTemplate<T>> : formatter<int> {
- template <typename FormatContext>
- typename FormatContext::iterator format(TestTemplate<T>, FormatContext& ctx) {
+template <typename T> struct formatter<test_template<T>> : formatter<int> {
+ auto format(test_template<T>, format_context& ctx) -> decltype(ctx.out()) {
return formatter<int>::format(2, ctx);
}
};
} // namespace fmt
-#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 407
-TEST(OStreamTest, Template) {
- EXPECT_EQ("2", fmt::format("{}", TestTemplate<int>()));
+TEST(ostream_test, template) {
+ EXPECT_EQ("2", fmt::format("{}", test_template<int>()));
}
-TEST(FormatTest, FormatToN) {
+TEST(ostream_test, format_to_n) {
char buffer[4];
buffer[3] = 'x';
- auto result = fmt::format_to_n(buffer, 3, "{}", fmt_test::ABC());
+ auto result = fmt::format_to_n(buffer, 3, "{}", fmt_test::abc());
EXPECT_EQ(3u, result.size);
EXPECT_EQ(buffer + 3, result.out);
- EXPECT_EQ("ABCx", fmt::string_view(buffer, 4));
- result = fmt::format_to_n(buffer, 3, "x{}y", fmt_test::ABC());
+ EXPECT_EQ("abcx", fmt::string_view(buffer, 4));
+ result = fmt::format_to_n(buffer, 3, "x{}y", fmt_test::abc());
EXPECT_EQ(5u, result.size);
EXPECT_EQ(buffer + 3, result.out);
- EXPECT_EQ("xABx", fmt::string_view(buffer, 4));
-}
-#endif
-
-#if FMT_USE_USER_DEFINED_LITERALS
-TEST(FormatTest, UDL) {
- using namespace fmt::literals;
- EXPECT_EQ("{}"_format("test"), "test");
+ EXPECT_EQ("xabx", fmt::string_view(buffer, 4));
}
-#endif
template <typename T> struct convertible {
T value;
@@ -251,9 +209,8 @@ template <typename T> struct convertible {
operator T() const { return value; }
};
-TEST(OStreamTest, DisableBuiltinOStreamOperators) {
+TEST(ostream_test, disable_builtin_ostream_operators) {
EXPECT_EQ("42", fmt::format("{:d}", convertible<unsigned short>(42)));
- EXPECT_EQ(L"42", fmt::format(L"{:d}", convertible<unsigned short>(42)));
EXPECT_EQ("foo", fmt::format("{}", convertible<const char*>("foo")));
}
@@ -271,7 +228,7 @@ std::ostream& operator<<(std::ostream& os,
return os << "bar";
}
-TEST(OStreamTest, FormatExplicitlyConvertibleToStringLike) {
+TEST(ostream_test, format_explicitly_convertible_to_string_like) {
EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
}
@@ -287,7 +244,7 @@ std::ostream& operator<<(std::ostream& os,
return os << "bar";
}
-TEST(OStreamTest, FormatExplicitlyConvertibleToStdStringView) {
+TEST(ostream_test, format_explicitly_convertible_to_std_string_view) {
EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
}
#endif // FMT_USE_STRING_VIEW
@@ -300,8 +257,9 @@ std::ostream& operator<<(std::ostream& os, streamable_and_convertible_to_bool) {
return os << "foo";
}
-TEST(OStreamTest, FormatConvertibleToBool) {
- EXPECT_EQ("foo", fmt::format("{}", streamable_and_convertible_to_bool()));
+TEST(ostream_test, format_convertible_to_bool) {
+ // operator<< is intentionally not used because of potential ODR violations.
+ EXPECT_EQ(fmt::format("{}", streamable_and_convertible_to_bool()), "true");
}
struct copyfmt_test {};
@@ -312,19 +270,32 @@ std::ostream& operator<<(std::ostream& os, copyfmt_test) {
return os << "foo";
}
-TEST(OStreamTest, CopyFmt) {
+TEST(ostream_test, copyfmt) {
EXPECT_EQ("foo", fmt::format("{}", copyfmt_test()));
}
-TEST(OStreamTest, CompileTimeString) {
- EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
+TEST(ostream_test, to_string) {
+ EXPECT_EQ("abc", fmt::to_string(fmt_test::abc()));
}
-TEST(OStreamTest, ToString) {
- EXPECT_EQ("ABC", fmt::to_string(fmt_test::ABC()));
+TEST(ostream_test, range) {
+ auto strs = std::vector<test_string>{test_string("foo"), test_string("bar")};
+ EXPECT_EQ("[foo, bar]", fmt::format("{}", strs));
}
-TEST(OStreamTest, Range) {
- auto strs = std::vector<TestString>{TestString("foo"), TestString("bar")};
- EXPECT_EQ("{foo, bar}", format("{}", strs));
-} \ No newline at end of file
+struct abstract {
+ virtual ~abstract() = default;
+ virtual void f() = 0;
+ friend std::ostream& operator<<(std::ostream& os, const abstract&) {
+ return os;
+ }
+};
+
+void format_abstract_compiles(const abstract& a) {
+ fmt::format(FMT_COMPILE("{}"), a);
+}
+
+TEST(ostream_test, is_formattable) {
+ EXPECT_TRUE(fmt::is_formattable<std::string>());
+ EXPECT_TRUE(fmt::is_formattable<fmt::detail::std_string_view<char>>());
+}
diff --git a/contrib/libs/fmt/test/posix-mock-test.cc b/contrib/libs/fmt/test/posix-mock-test.cc
index 0ea1b9c6d5..3a20b269a4 100644
--- a/contrib/libs/fmt/test/posix-mock-test.cc
+++ b/contrib/libs/fmt/test/posix-mock-test.cc
@@ -23,20 +23,23 @@
#ifdef _WIN32
# include <io.h>
# undef max
-# undef ERROR
#endif
-#include <gmock/gmock.h>
+#include "gmock/gmock.h"
#include "gtest-extra.h"
#include "util.h"
using fmt::buffered_file;
-using fmt::error_code;
using testing::_;
using testing::Return;
using testing::StrEq;
+template <typename Mock> struct scoped_mock : testing::StrictMock<Mock> {
+ scoped_mock() { Mock::instance = this; }
+ ~scoped_mock() { Mock::instance = nullptr; }
+};
+
namespace {
int open_count;
int close_count;
@@ -53,7 +56,7 @@ size_t read_nbyte;
size_t write_nbyte;
bool sysconf_error;
-enum { NONE, MAX_SIZE, ERROR } fstat_sim;
+enum { none, max_size, error } fstat_sim;
} // namespace
#define EMULATE_EINTR(func, error_result) \
@@ -91,7 +94,7 @@ static off_t max_file_size() { return std::numeric_limits<off_t>::max(); }
int test::fstat(int fd, struct stat* buf) {
int result = ::fstat(fd, buf);
- if (fstat_sim == MAX_SIZE) buf->st_size = max_file_size();
+ if (fstat_sim == max_size) buf->st_size = max_file_size();
return result;
}
@@ -100,11 +103,11 @@ int test::fstat(int fd, struct stat* buf) {
static LONGLONG max_file_size() { return std::numeric_limits<LONGLONG>::max(); }
DWORD test::GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
- if (fstat_sim == ERROR) {
+ if (fstat_sim == error) {
SetLastError(ERROR_ACCESS_DENIED);
return INVALID_FILE_SIZE;
}
- if (fstat_sim == MAX_SIZE) {
+ if (fstat_sim == max_size) {
DWORD max = std::numeric_limits<DWORD>::max();
*lpFileSizeHigh = max >> 1;
return max;
@@ -194,15 +197,15 @@ int(test::fileno)(FILE* stream) {
# define EXPECT_EQ_POSIX(expected, actual)
#endif
-static void write_file(fmt::cstring_view filename, fmt::string_view content) {
+#if FMT_USE_FCNTL
+void write_file(fmt::cstring_view filename, fmt::string_view content) {
fmt::buffered_file f(filename, "w");
f.print("{}", content);
}
-#if FMT_USE_FCNTL
using fmt::file;
-TEST(UtilTest, GetPageSize) {
+TEST(os_test, getpagesize) {
# ifdef _WIN32
SYSTEM_INFO si = {};
GetSystemInfo(&si);
@@ -216,7 +219,7 @@ TEST(UtilTest, GetPageSize) {
# endif
}
-TEST(FileTest, OpenRetry) {
+TEST(file_test, open_retry) {
write_file("temp", "there must be something here");
std::unique_ptr<file> f{nullptr};
EXPECT_RETRY(f.reset(new file("temp", file::RDONLY)), open,
@@ -227,7 +230,7 @@ TEST(FileTest, OpenRetry) {
# endif
}
-TEST(FileTest, CloseNoRetryInDtor) {
+TEST(file_test, close_no_retry_in_dtor) {
file read_end, write_end;
file::pipe(read_end, write_end);
std::unique_ptr<file> f(new file(std::move(read_end)));
@@ -240,11 +243,11 @@ TEST(FileTest, CloseNoRetryInDtor) {
saved_close_count = close_count;
close_count = 0;
},
- format_system_error(EINTR, "cannot close file") + "\n");
+ system_error_message(EINTR, "cannot close file") + "\n");
EXPECT_EQ(2, saved_close_count);
}
-TEST(FileTest, CloseNoRetry) {
+TEST(file_test, close_no_retry) {
file read_end, write_end;
file::pipe(read_end, write_end);
close_count = 1;
@@ -253,35 +256,39 @@ TEST(FileTest, CloseNoRetry) {
close_count = 0;
}
-TEST(FileTest, Size) {
+TEST(file_test, size) {
std::string content = "top secret, destroy before reading";
write_file("temp", content);
file f("temp", file::RDONLY);
EXPECT_GE(f.size(), 0);
EXPECT_EQ(content.size(), static_cast<unsigned long long>(f.size()));
# ifdef _WIN32
- fmt::memory_buffer message;
- fmt::detail::format_windows_error(message, ERROR_ACCESS_DENIED,
- "cannot get file size");
- fstat_sim = ERROR;
- EXPECT_THROW_MSG(f.size(), fmt::windows_error, fmt::to_string(message));
- fstat_sim = NONE;
+ auto error_code = std::error_code();
+ fstat_sim = error;
+ try {
+ f.size();
+ } catch (const std::system_error& e) {
+ error_code = e.code();
+ }
+ fstat_sim = none;
+ EXPECT_EQ(error_code,
+ std::error_code(ERROR_ACCESS_DENIED, fmt::system_category()));
# else
f.close();
EXPECT_SYSTEM_ERROR(f.size(), EBADF, "cannot get file attributes");
# endif
}
-TEST(FileTest, MaxSize) {
+TEST(file_test, max_size) {
write_file("temp", "");
file f("temp", file::RDONLY);
- fstat_sim = MAX_SIZE;
+ fstat_sim = max_size;
EXPECT_GE(f.size(), 0);
EXPECT_EQ(max_file_size(), f.size());
- fstat_sim = NONE;
+ fstat_sim = none;
}
-TEST(FileTest, ReadRetry) {
+TEST(file_test, read_retry) {
file read_end, write_end;
file::pipe(read_end, write_end);
enum { SIZE = 4 };
@@ -294,7 +301,7 @@ TEST(FileTest, ReadRetry) {
EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
}
-TEST(FileTest, WriteRetry) {
+TEST(file_test, write_retry) {
file read_end, write_end;
file::pipe(read_end, write_end);
enum { SIZE = 4 };
@@ -312,7 +319,7 @@ TEST(FileTest, WriteRetry) {
}
# ifdef _WIN32
-TEST(FileTest, ConvertReadCount) {
+TEST(file_test, convert_read_count) {
file read_end, write_end;
file::pipe(read_end, write_end);
char c;
@@ -320,12 +327,12 @@ TEST(FileTest, ConvertReadCount) {
if (sizeof(unsigned) != sizeof(size_t)) ++size;
read_count = 1;
read_nbyte = 0;
- EXPECT_THROW(read_end.read(&c, size), fmt::system_error);
+ EXPECT_THROW(read_end.read(&c, size), std::system_error);
read_count = 0;
EXPECT_EQ(UINT_MAX, read_nbyte);
}
-TEST(FileTest, ConvertWriteCount) {
+TEST(file_test, convert_write_count) {
file read_end, write_end;
file::pipe(read_end, write_end);
char c;
@@ -333,13 +340,13 @@ TEST(FileTest, ConvertWriteCount) {
if (sizeof(unsigned) != sizeof(size_t)) ++size;
write_count = 1;
write_nbyte = 0;
- EXPECT_THROW(write_end.write(&c, size), fmt::system_error);
+ EXPECT_THROW(write_end.write(&c, size), std::system_error);
write_count = 0;
EXPECT_EQ(UINT_MAX, write_nbyte);
}
# endif
-TEST(FileTest, DupNoRetry) {
+TEST(file_test, dup_no_retry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
dup_count = 1;
EXPECT_SYSTEM_ERROR(
@@ -348,7 +355,7 @@ TEST(FileTest, DupNoRetry) {
dup_count = 0;
}
-TEST(FileTest, Dup2Retry) {
+TEST(file_test, dup2_retry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
file f1 = file::dup(stdout_fd), f2 = file::dup(stdout_fd);
EXPECT_RETRY(f1.dup2(f2.descriptor()), dup2,
@@ -356,21 +363,21 @@ TEST(FileTest, Dup2Retry) {
f1.descriptor(), f2.descriptor()));
}
-TEST(FileTest, Dup2NoExceptRetry) {
+TEST(file_test, dup2_no_except_retry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
file f1 = file::dup(stdout_fd), f2 = file::dup(stdout_fd);
- error_code ec;
+ std::error_code ec;
dup2_count = 1;
f1.dup2(f2.descriptor(), ec);
# ifndef _WIN32
EXPECT_EQ(4, dup2_count);
# else
- EXPECT_EQ(EINTR, ec.get());
+ EXPECT_EQ(EINTR, ec.value());
# endif
dup2_count = 0;
}
-TEST(FileTest, PipeNoRetry) {
+TEST(file_test, pipe_no_retry) {
file read_end, write_end;
pipe_count = 1;
EXPECT_SYSTEM_ERROR(file::pipe(read_end, write_end), EINTR,
@@ -378,7 +385,7 @@ TEST(FileTest, PipeNoRetry) {
pipe_count = 0;
}
-TEST(FileTest, FdopenNoRetry) {
+TEST(file_test, fdopen_no_retry) {
file read_end, write_end;
file::pipe(read_end, write_end);
fdopen_count = 1;
@@ -387,7 +394,7 @@ TEST(FileTest, FdopenNoRetry) {
fdopen_count = 0;
}
-TEST(BufferedFileTest, OpenRetry) {
+TEST(buffered_file_test, open_retry) {
write_file("temp", "there must be something here");
std::unique_ptr<buffered_file> f{nullptr};
EXPECT_RETRY(f.reset(new buffered_file("temp", "r")), fopen,
@@ -399,7 +406,7 @@ TEST(BufferedFileTest, OpenRetry) {
# endif
}
-TEST(BufferedFileTest, CloseNoRetryInDtor) {
+TEST(buffered_file_test, close_no_retry_in_dtor) {
file read_end, write_end;
file::pipe(read_end, write_end);
std::unique_ptr<buffered_file> f(new buffered_file(read_end.fdopen("r")));
@@ -412,11 +419,11 @@ TEST(BufferedFileTest, CloseNoRetryInDtor) {
saved_fclose_count = fclose_count;
fclose_count = 0;
},
- format_system_error(EINTR, "cannot close file") + "\n");
+ system_error_message(EINTR, "cannot close file") + "\n");
EXPECT_EQ(2, saved_fclose_count);
}
-TEST(BufferedFileTest, CloseNoRetry) {
+TEST(buffered_file_test, close_no_retry) {
file read_end, write_end;
file::pipe(read_end, write_end);
buffered_file f = read_end.fdopen("r");
@@ -426,7 +433,7 @@ TEST(BufferedFileTest, CloseNoRetry) {
fclose_count = 0;
}
-TEST(BufferedFileTest, FilenoNoRetry) {
+TEST(buffered_file_test, fileno_no_retry) {
file read_end, write_end;
file::pipe(read_end, write_end);
buffered_file f = read_end.fdopen("r");
@@ -441,9 +448,9 @@ struct test_mock {
static test_mock* instance;
} * test_mock::instance;
-TEST(ScopedMock, Scope) {
+TEST(scoped_mock, scope) {
{
- ScopedMock<test_mock> mock;
+ scoped_mock<test_mock> mock;
EXPECT_EQ(&mock, test_mock::instance);
test_mock& copy = mock;
static_cast<void>(copy);
@@ -453,16 +460,13 @@ TEST(ScopedMock, Scope) {
#if defined(FMT_LOCALE) && !defined(_LIBCPP_VERSION)
-typedef fmt::locale::type locale_type;
+using locale_type = fmt::locale::type;
struct locale_mock {
static locale_mock* instance;
MOCK_METHOD3(newlocale, locale_type(int category_mask, const char* locale,
locale_type base));
MOCK_METHOD1(freelocale, void(locale_type locale));
-
- MOCK_METHOD3(strtod_l,
- double(const char* nptr, char** endptr, locale_type locale));
} * locale_mock::instance;
# ifdef _MSC_VER
@@ -480,17 +484,14 @@ _locale_t _create_locale(int category, const char* locale) {
void _free_locale(_locale_t locale) {
locale_mock::instance->freelocale(locale);
}
-
-double _strtod_l(const char* nptr, char** endptr, _locale_t locale) {
- return locale_mock::instance->strtod_l(nptr, endptr, locale);
-}
# ifdef __clang__
# pragma clang diagnostic pop
# endif
# pragma warning(pop)
# endif
-# if defined(__THROW) && FMT_GCC_VERSION > 0 && FMT_GCC_VERSION <= 408
+# if defined(__THROW) && \
+ ((FMT_GCC_VERSION > 0 && FMT_GCC_VERSION <= 408) || defined(__e2k__))
# define FMT_LOCALE_THROW __THROW
# else
# define FMT_LOCALE_THROW
@@ -508,11 +509,6 @@ FreeLocaleResult freelocale(locale_type locale) FMT_LOCALE_THROW {
return FreeLocaleResult();
}
-double strtod_l(const char* nptr, char** endptr,
- locale_type locale) FMT_LOCALE_THROW {
- return locale_mock::instance->strtod_l(nptr, endptr, locale);
-}
-
# undef FMT_LOCALE_THROW
# if !defined(_WIN32) || defined(_LIBCPP_VERSION)
@@ -520,20 +516,20 @@ locale_t test::newlocale(int category_mask, const char* locale, locale_t base) {
return locale_mock::instance->newlocale(category_mask, locale, base);
}
-TEST(LocaleTest, LocaleMock) {
- ScopedMock<locale_mock> mock;
- locale_type locale = reinterpret_cast<locale_type>(11);
+TEST(locale_test, locale_mock) {
+ scoped_mock<locale_mock> mock;
+ auto locale = reinterpret_cast<locale_type>(11);
EXPECT_CALL(mock, newlocale(222, StrEq("foo"), locale));
FMT_SYSTEM(newlocale(222, "foo", locale));
}
# endif
-TEST(LocaleTest, Locale) {
+TEST(locale_test, locale) {
# ifndef LC_NUMERIC_MASK
enum { LC_NUMERIC_MASK = LC_NUMERIC };
# endif
- ScopedMock<locale_mock> mock;
- locale_type impl = reinterpret_cast<locale_type>(42);
+ scoped_mock<locale_mock> mock;
+ auto impl = reinterpret_cast<locale_type>(42);
EXPECT_CALL(mock, newlocale(LC_NUMERIC_MASK, StrEq("C"), nullptr))
.WillOnce(Return(impl));
EXPECT_CALL(mock, freelocale(impl));
@@ -541,18 +537,4 @@ TEST(LocaleTest, Locale) {
EXPECT_EQ(impl, loc.get());
}
-TEST(LocaleTest, Strtod) {
- ScopedMock<locale_mock> mock;
- EXPECT_CALL(mock, newlocale(_, _, _))
- .WillOnce(Return(reinterpret_cast<locale_type>(42)));
- EXPECT_CALL(mock, freelocale(_));
- fmt::locale loc;
- const char* str = "4.2";
- char end = 'x';
- EXPECT_CALL(mock, strtod_l(str, _, loc.get()))
- .WillOnce(testing::DoAll(testing::SetArgPointee<1>(&end), Return(777)));
- EXPECT_EQ(777, loc.strtod(str));
- EXPECT_EQ(&end, str);
-}
-
#endif // FMT_LOCALE
diff --git a/contrib/libs/fmt/test/printf-test.cc b/contrib/libs/fmt/test/printf-test.cc
index ccd72dcd75..0bb9ccdaf6 100644
--- a/contrib/libs/fmt/test/printf-test.cc
+++ b/contrib/libs/fmt/test/printf-test.cc
@@ -11,7 +11,8 @@
#include <climits>
#include <cstring>
-#include "fmt/core.h"
+#include "fmt/ostream.h"
+#include "fmt/xchar.h"
#include "gtest-extra.h"
#include "util.h"
@@ -19,7 +20,7 @@ using fmt::format;
using fmt::format_error;
using fmt::detail::max_value;
-const unsigned BIG_NUM = INT_MAX + 1u;
+const unsigned big_num = INT_MAX + 1u;
// Makes format string argument positional.
static std::string make_positional(fmt::string_view format) {
@@ -28,7 +29,7 @@ static std::string make_positional(fmt::string_view format) {
return s;
}
-static std::wstring make_positional(fmt::wstring_view format) {
+static std::wstring make_positional(fmt::basic_string_view<wchar_t> format) {
std::wstring s(format.data(), format.size());
s.replace(s.find(L'%'), 1, L"%1$");
return s;
@@ -41,7 +42,8 @@ std::string test_sprintf(fmt::string_view format, const Args&... args) {
return fmt::sprintf(format, args...);
}
template <typename... Args>
-std::wstring test_sprintf(fmt::wstring_view format, const Args&... args) {
+std::wstring test_sprintf(fmt::basic_string_view<wchar_t> format,
+ const Args&... args) {
return fmt::sprintf(format, args...);
}
@@ -50,12 +52,12 @@ std::wstring test_sprintf(fmt::wstring_view format, const Args&... args) {
<< "format: " << format; \
EXPECT_EQ(expected_output, fmt::sprintf(make_positional(format), arg))
-TEST(PrintfTest, NoArgs) {
+TEST(printf_test, no_args) {
EXPECT_EQ("test", test_sprintf("test"));
EXPECT_EQ(L"test", fmt::sprintf(L"test"));
}
-TEST(PrintfTest, Escape) {
+TEST(printf_test, escape) {
EXPECT_EQ("%", test_sprintf("%%"));
EXPECT_EQ("before %", test_sprintf("before %%"));
EXPECT_EQ("% after", test_sprintf("%% after"));
@@ -68,7 +70,7 @@ TEST(PrintfTest, Escape) {
EXPECT_EQ(L"%s", fmt::sprintf(L"%%s"));
}
-TEST(PrintfTest, PositionalArgs) {
+TEST(printf_test, positional_args) {
EXPECT_EQ("42", test_sprintf("%1$d", 42));
EXPECT_EQ("before 42", test_sprintf("before %1$d", 42));
EXPECT_EQ("42 after", test_sprintf("%1$d after", 42));
@@ -78,40 +80,40 @@ TEST(PrintfTest, PositionalArgs) {
EXPECT_EQ("abracadabra", test_sprintf("%1$s%2$s%1$s", "abra", "cad"));
}
-TEST(PrintfTest, AutomaticArgIndexing) {
+TEST(printf_test, automatic_arg_indexing) {
EXPECT_EQ("abc", test_sprintf("%c%c%c", 'a', 'b', 'c'));
}
-TEST(PrintfTest, NumberIsTooBigInArgIndex) {
- EXPECT_THROW_MSG(test_sprintf(format("%{}$", BIG_NUM)), format_error,
- "number is too big");
- EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM)), format_error,
- "number is too big");
+TEST(printf_test, number_is_too_big_in_arg_index) {
+ EXPECT_THROW_MSG(test_sprintf(format("%{}$", big_num)), format_error,
+ "argument not found");
+ EXPECT_THROW_MSG(test_sprintf(format("%{}$d", big_num)), format_error,
+ "argument not found");
}
-TEST(PrintfTest, SwitchArgIndexing) {
+TEST(printf_test, switch_arg_indexing) {
EXPECT_THROW_MSG(test_sprintf("%1$d%", 1, 2), format_error,
"cannot switch from manual to automatic argument indexing");
- EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
+ EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", big_num), 1, 2),
format_error, "number is too big");
EXPECT_THROW_MSG(test_sprintf("%1$d%d", 1, 2), format_error,
"cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(test_sprintf("%d%1$", 1, 2), format_error,
"cannot switch from automatic to manual argument indexing");
- EXPECT_THROW_MSG(test_sprintf(format("%d%{}$d", BIG_NUM), 1, 2), format_error,
- "number is too big");
+ EXPECT_THROW_MSG(test_sprintf(format("%d%{}$d", big_num), 1, 2), format_error,
+ "cannot switch from automatic to manual argument indexing");
EXPECT_THROW_MSG(test_sprintf("%d%1$d", 1, 2), format_error,
"cannot switch from automatic to manual argument indexing");
// Indexing errors override width errors.
- EXPECT_THROW_MSG(test_sprintf(format("%d%1${}d", BIG_NUM), 1, 2),
+ EXPECT_THROW_MSG(test_sprintf(format("%d%1${}d", big_num), 1, 2),
format_error, "number is too big");
- EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
+ EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", big_num), 1, 2),
format_error, "number is too big");
}
-TEST(PrintfTest, InvalidArgIndex) {
+TEST(printf_test, invalid_arg_index) {
EXPECT_THROW_MSG(test_sprintf("%0$d", 42), format_error,
"argument not found");
EXPECT_THROW_MSG(test_sprintf("%2$d", 42), format_error,
@@ -120,16 +122,16 @@ TEST(PrintfTest, InvalidArgIndex) {
"argument not found");
EXPECT_THROW_MSG(test_sprintf("%2$", 42), format_error, "argument not found");
- EXPECT_THROW_MSG(test_sprintf(format("%{}$d", BIG_NUM), 42), format_error,
- "number is too big");
+ EXPECT_THROW_MSG(test_sprintf(format("%{}$d", big_num), 42), format_error,
+ "argument not found");
}
-TEST(PrintfTest, DefaultAlignRight) {
+TEST(printf_test, default_align_right) {
EXPECT_PRINTF(" 42", "%5d", 42);
EXPECT_PRINTF(" abc", "%5s", "abc");
}
-TEST(PrintfTest, ZeroFlag) {
+TEST(printf_test, zero_flag) {
EXPECT_PRINTF("00042", "%05d", 42);
EXPECT_PRINTF("-0042", "%05d", -42);
@@ -146,7 +148,7 @@ TEST(PrintfTest, ZeroFlag) {
EXPECT_PRINTF(" x", "%05c", 'x');
}
-TEST(PrintfTest, PlusFlag) {
+TEST(printf_test, plus_flag) {
EXPECT_PRINTF("+42", "%+d", 42);
EXPECT_PRINTF("-42", "%+d", -42);
EXPECT_PRINTF("+0042", "%+05d", 42);
@@ -168,7 +170,7 @@ TEST(PrintfTest, PlusFlag) {
EXPECT_PRINTF("x", "% +c", 'x');
}
-TEST(PrintfTest, MinusFlag) {
+TEST(printf_test, minus_flag) {
EXPECT_PRINTF("abc ", "%-5s", "abc");
EXPECT_PRINTF("abc ", "%0--5s", "abc");
@@ -188,7 +190,7 @@ TEST(PrintfTest, MinusFlag) {
EXPECT_PRINTF(" 42", "%- d", 42);
}
-TEST(PrintfTest, SpaceFlag) {
+TEST(printf_test, space_flag) {
EXPECT_PRINTF(" 42", "% d", 42);
EXPECT_PRINTF("-42", "% d", -42);
EXPECT_PRINTF(" 0042", "% 05d", 42);
@@ -198,7 +200,7 @@ TEST(PrintfTest, SpaceFlag) {
EXPECT_PRINTF("x", "% c", 'x');
}
-TEST(PrintfTest, HashFlag) {
+TEST(printf_test, hash_flag) {
EXPECT_PRINTF("042", "%#o", 042);
EXPECT_PRINTF(fmt::format("0{:o}", static_cast<unsigned>(-042)), "%#o", -042);
EXPECT_PRINTF("0", "%#o", 0);
@@ -215,7 +217,7 @@ TEST(PrintfTest, HashFlag) {
EXPECT_PRINTF("-42.000000", "%#f", -42.0);
EXPECT_PRINTF("-42.000000", "%#F", -42.0);
- char buffer[BUFFER_SIZE];
+ char buffer[256];
safe_sprintf(buffer, "%#e", -42.0);
EXPECT_PRINTF(buffer, "%#e", -42.0);
safe_sprintf(buffer, "%#E", -42.0);
@@ -233,30 +235,30 @@ TEST(PrintfTest, HashFlag) {
EXPECT_PRINTF("x", "%#c", 'x');
}
-TEST(PrintfTest, Width) {
+TEST(printf_test, width) {
EXPECT_PRINTF(" abc", "%5s", "abc");
// Width cannot be specified twice.
EXPECT_THROW_MSG(test_sprintf("%5-5d", 42), format_error,
"invalid type specifier");
- EXPECT_THROW_MSG(test_sprintf(format("%{}d", BIG_NUM), 42), format_error,
+ EXPECT_THROW_MSG(test_sprintf(format("%{}d", big_num), 42), format_error,
"number is too big");
- EXPECT_THROW_MSG(test_sprintf(format("%1${}d", BIG_NUM), 42), format_error,
+ EXPECT_THROW_MSG(test_sprintf(format("%1${}d", big_num), 42), format_error,
"number is too big");
}
-TEST(PrintfTest, DynamicWidth) {
+TEST(printf_test, dynamic_width) {
EXPECT_EQ(" 42", test_sprintf("%*d", 5, 42));
EXPECT_EQ("42 ", test_sprintf("%*d", -5, 42));
EXPECT_THROW_MSG(test_sprintf("%*d", 5.0, 42), format_error,
"width is not integer");
EXPECT_THROW_MSG(test_sprintf("%*d"), format_error, "argument not found");
- EXPECT_THROW_MSG(test_sprintf("%*d", BIG_NUM, 42), format_error,
+ EXPECT_THROW_MSG(test_sprintf("%*d", big_num, 42), format_error,
"number is too big");
}
-TEST(PrintfTest, IntPrecision) {
+TEST(printf_test, int_precision) {
EXPECT_PRINTF("00042", "%.5d", 42);
EXPECT_PRINTF("-00042", "%.5d", -42);
EXPECT_PRINTF("00042", "%.5x", 0x42);
@@ -277,8 +279,8 @@ TEST(PrintfTest, IntPrecision) {
EXPECT_PRINTF("00042 ", "%-#10.5o", 042);
}
-TEST(PrintfTest, FloatPrecision) {
- char buffer[BUFFER_SIZE];
+TEST(printf_test, float_precision) {
+ char buffer[256];
safe_sprintf(buffer, "%.3e", 1234.5678);
EXPECT_PRINTF(buffer, "%.3e", 1234.5678);
EXPECT_PRINTF("1234.568", "%.3f", 1234.5678);
@@ -287,22 +289,22 @@ TEST(PrintfTest, FloatPrecision) {
EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
}
-TEST(PrintfTest, StringPrecision) {
+TEST(printf_test, string_precision) {
char test[] = {'H', 'e', 'l', 'l', 'o'};
EXPECT_EQ(fmt::sprintf("%.4s", test), "Hell");
}
-TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
+TEST(printf_test, ignore_precision_for_non_numeric_arg) {
EXPECT_PRINTF("abc", "%.5s", "abc");
}
-TEST(PrintfTest, DynamicPrecision) {
+TEST(printf_test, dynamic_precision) {
EXPECT_EQ("00042", test_sprintf("%.*d", 5, 42));
EXPECT_EQ("42", test_sprintf("%.*d", -5, 42));
EXPECT_THROW_MSG(test_sprintf("%.*d", 5.0, 42), format_error,
"precision is not integer");
EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error, "argument not found");
- EXPECT_THROW_MSG(test_sprintf("%.*d", BIG_NUM, 42), format_error,
+ EXPECT_THROW_MSG(test_sprintf("%.*d", big_num, 42), format_error,
"number is too big");
if (sizeof(long long) != sizeof(int)) {
long long prec = static_cast<long long>(INT_MIN) - 1;
@@ -325,7 +327,7 @@ SPECIALIZE_MAKE_SIGNED(unsigned long long, long long);
// Test length format specifier ``length_spec``.
template <typename T, typename U>
-void TestLength(const char* length_spec, U value) {
+void test_length(const char* length_spec, U value) {
long long signed_value = 0;
unsigned long long unsigned_value = 0;
// Apply integer promotion to the argument.
@@ -364,54 +366,54 @@ void TestLength(const char* length_spec, U value) {
EXPECT_PRINTF(os.str(), fmt::format("%{}X", length_spec), value);
}
-template <typename T> void TestLength(const char* length_spec) {
+template <typename T> void test_length(const char* length_spec) {
T min = std::numeric_limits<T>::min(), max = max_value<T>();
- TestLength<T>(length_spec, 42);
- TestLength<T>(length_spec, -42);
- TestLength<T>(length_spec, min);
- TestLength<T>(length_spec, max);
+ test_length<T>(length_spec, 42);
+ test_length<T>(length_spec, -42);
+ test_length<T>(length_spec, min);
+ test_length<T>(length_spec, max);
long long long_long_min = std::numeric_limits<long long>::min();
if (static_cast<long long>(min) > long_long_min)
- TestLength<T>(length_spec, static_cast<long long>(min) - 1);
+ test_length<T>(length_spec, static_cast<long long>(min) - 1);
unsigned long long long_long_max = max_value<long long>();
if (static_cast<unsigned long long>(max) < long_long_max)
- TestLength<T>(length_spec, static_cast<long long>(max) + 1);
- TestLength<T>(length_spec, std::numeric_limits<short>::min());
- TestLength<T>(length_spec, max_value<unsigned short>());
- TestLength<T>(length_spec, std::numeric_limits<int>::min());
- TestLength<T>(length_spec, max_value<int>());
- TestLength<T>(length_spec, std::numeric_limits<unsigned>::min());
- TestLength<T>(length_spec, max_value<unsigned>());
- TestLength<T>(length_spec, std::numeric_limits<long long>::min());
- TestLength<T>(length_spec, max_value<long long>());
- TestLength<T>(length_spec, std::numeric_limits<unsigned long long>::min());
- TestLength<T>(length_spec, max_value<unsigned long long>());
-}
-
-TEST(PrintfTest, Length) {
- TestLength<char>("hh");
- TestLength<signed char>("hh");
- TestLength<unsigned char>("hh");
- TestLength<short>("h");
- TestLength<unsigned short>("h");
- TestLength<long>("l");
- TestLength<unsigned long>("l");
- TestLength<long long>("ll");
- TestLength<unsigned long long>("ll");
- TestLength<intmax_t>("j");
- TestLength<size_t>("z");
- TestLength<std::ptrdiff_t>("t");
+ test_length<T>(length_spec, static_cast<long long>(max) + 1);
+ test_length<T>(length_spec, std::numeric_limits<short>::min());
+ test_length<T>(length_spec, max_value<unsigned short>());
+ test_length<T>(length_spec, std::numeric_limits<int>::min());
+ test_length<T>(length_spec, max_value<int>());
+ test_length<T>(length_spec, std::numeric_limits<unsigned>::min());
+ test_length<T>(length_spec, max_value<unsigned>());
+ test_length<T>(length_spec, std::numeric_limits<long long>::min());
+ test_length<T>(length_spec, max_value<long long>());
+ test_length<T>(length_spec, std::numeric_limits<unsigned long long>::min());
+ test_length<T>(length_spec, max_value<unsigned long long>());
+}
+
+TEST(printf_test, length) {
+ test_length<char>("hh");
+ test_length<signed char>("hh");
+ test_length<unsigned char>("hh");
+ test_length<short>("h");
+ test_length<unsigned short>("h");
+ test_length<long>("l");
+ test_length<unsigned long>("l");
+ test_length<long long>("ll");
+ test_length<unsigned long long>("ll");
+ test_length<intmax_t>("j");
+ test_length<size_t>("z");
+ test_length<std::ptrdiff_t>("t");
long double max = max_value<long double>();
EXPECT_PRINTF(fmt::format("{:.6}", max), "%g", max);
EXPECT_PRINTF(fmt::format("{:.6}", max), "%Lg", max);
}
-TEST(PrintfTest, Bool) {
+TEST(printf_test, bool) {
EXPECT_PRINTF("1", "%d", true);
EXPECT_PRINTF("true", "%s", true);
}
-TEST(PrintfTest, Int) {
+TEST(printf_test, int) {
EXPECT_PRINTF("-42", "%d", -42);
EXPECT_PRINTF("-42", "%i", -42);
unsigned u = 0 - 42u;
@@ -421,20 +423,20 @@ TEST(PrintfTest, Int) {
EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
}
-TEST(PrintfTest, long_long) {
+TEST(printf_test, long_long) {
// fmt::printf allows passing long long arguments to %d without length
// specifiers.
long long max = max_value<long long>();
EXPECT_PRINTF(fmt::format("{}", max), "%d", max);
}
-TEST(PrintfTest, Float) {
+TEST(printf_test, float) {
EXPECT_PRINTF("392.650000", "%f", 392.65);
EXPECT_PRINTF("392.65", "%.2f", 392.65);
EXPECT_PRINTF("392.6", "%.1f", 392.65);
EXPECT_PRINTF("393", "%.f", 392.65);
EXPECT_PRINTF("392.650000", "%F", 392.65);
- char buffer[BUFFER_SIZE];
+ char buffer[256];
safe_sprintf(buffer, "%e", 392.65);
EXPECT_PRINTF(buffer, "%e", 392.65);
safe_sprintf(buffer, "%E", 392.65);
@@ -450,7 +452,7 @@ TEST(PrintfTest, Float) {
EXPECT_EQ(buffer, format("{:A}", -392.65));
}
-TEST(PrintfTest, Inf) {
+TEST(printf_test, inf) {
double inf = std::numeric_limits<double>::infinity();
for (const char* type = "fega"; *type; ++type) {
EXPECT_PRINTF("inf", fmt::format("%{}", *type), inf);
@@ -459,7 +461,7 @@ TEST(PrintfTest, Inf) {
}
}
-TEST(PrintfTest, Char) {
+TEST(printf_test, char) {
EXPECT_PRINTF("x", "%c", 'x');
int max = max_value<int>();
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
@@ -468,7 +470,7 @@ TEST(PrintfTest, Char) {
EXPECT_PRINTF(fmt::format(L"{}", static_cast<wchar_t>(max)), L"%c", max);
}
-TEST(PrintfTest, String) {
+TEST(printf_test, string) {
EXPECT_PRINTF("abc", "%s", "abc");
const char* null_str = nullptr;
EXPECT_PRINTF("(null)", "%s", null_str);
@@ -479,13 +481,7 @@ TEST(PrintfTest, String) {
EXPECT_PRINTF(L" (null)", L"%10s", null_wstr);
}
-TEST(PrintfTest, UCharString) {
- unsigned char str[] = "test";
- unsigned char* pstr = str;
- EXPECT_EQ("test", fmt::sprintf("%s", pstr));
-}
-
-TEST(PrintfTest, Pointer) {
+TEST(printf_test, pointer) {
int n;
void* p = &n;
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
@@ -508,20 +504,16 @@ TEST(PrintfTest, Pointer) {
EXPECT_PRINTF(L"(nil)", L"%p", null_wstr);
}
-TEST(PrintfTest, Location) {
- // TODO: test %n
-}
-
enum test_enum { answer = 42 };
-TEST(PrintfTest, Enum) {
+TEST(printf_test, enum) {
EXPECT_PRINTF("42", "%d", answer);
volatile test_enum volatile_enum = answer;
EXPECT_PRINTF("42", "%d", volatile_enum);
}
#if FMT_USE_FCNTL
-TEST(PrintfTest, Examples) {
+TEST(printf_test, examples) {
const char* weekday = "Thursday";
const char* month = "August";
int day = 21;
@@ -529,7 +521,7 @@ TEST(PrintfTest, Examples) {
"Thursday, 21 August");
}
-TEST(PrintfTest, PrintfError) {
+TEST(printf_test, printf_error) {
fmt::file read_end, write_end;
fmt::file::pipe(read_end, write_end);
int result = fmt::fprintf(read_end.fdopen("r").get(), "test");
@@ -537,26 +529,20 @@ TEST(PrintfTest, PrintfError) {
}
#endif
-TEST(PrintfTest, WideString) { EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc")); }
-
-TEST(PrintfTest, PrintfCustom) {
- EXPECT_EQ("abc", test_sprintf("%s", TestString("abc")));
+TEST(printf_test, wide_string) {
+ EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
}
-TEST(PrintfTest, OStream) {
- std::ostringstream os;
- int ret = fmt::fprintf(os, "Don't %s!", "panic");
- EXPECT_EQ("Don't panic!", os.str());
- EXPECT_EQ(12, ret);
+TEST(printf_test, printf_custom) {
+ EXPECT_EQ("abc", test_sprintf("%s", test_string("abc")));
}
-TEST(PrintfTest, VPrintf) {
+TEST(printf_test, vprintf) {
fmt::format_arg_store<fmt::printf_context, int> as{42};
fmt::basic_format_args<fmt::printf_context> args(as);
EXPECT_EQ(fmt::vsprintf("%d", args), "42");
EXPECT_WRITE(stdout, fmt::vprintf("%d", args), "42");
EXPECT_WRITE(stdout, fmt::vfprintf(stdout, "%d", args), "42");
- EXPECT_WRITE(stdout, fmt::vfprintf(std::cout, "%d", args), "42");
}
template <typename... Args>
@@ -564,15 +550,15 @@ void check_format_string_regression(fmt::string_view s, const Args&... args) {
fmt::sprintf(s, args...);
}
-TEST(PrintfTest, CheckFormatStringRegression) {
+TEST(printf_test, check_format_string_regression) {
check_format_string_regression("%c%s", 'x', "");
}
-TEST(PrintfTest, FixedLargeExponent) {
+TEST(printf_test, fixed_large_exponent) {
EXPECT_EQ("1000000000000000000000", fmt::sprintf("%.*f", -13, 1e21));
}
-TEST(PrintfTest, VSPrintfMakeArgsExample) {
+TEST(printf_test, vsprintf_make_args_example) {
fmt::format_arg_store<fmt::printf_context, int, const char*> as{42,
"something"};
fmt::basic_format_args<fmt::printf_context> args(as);
@@ -581,15 +567,12 @@ TEST(PrintfTest, VSPrintfMakeArgsExample) {
fmt::basic_format_args<fmt::printf_context> args2(as2);
EXPECT_EQ("[42] something happened",
fmt::vsprintf("[%d] %s happened", args2));
- // The older gcc versions can't cast the return value.
-#if !defined(__GNUC__) || (__GNUC__ > 4)
EXPECT_EQ("[42] something happened",
fmt::vsprintf("[%d] %s happened",
{fmt::make_printf_args(42, "something")}));
-#endif
}
-TEST(PrintfTest, VSPrintfMakeWArgsExample) {
+TEST(printf_test, vsprintf_make_wargs_example) {
fmt::format_arg_store<fmt::wprintf_context, int, const wchar_t*> as{
42, L"something"};
fmt::basic_format_args<fmt::wprintf_context> args(as);
@@ -599,30 +582,7 @@ TEST(PrintfTest, VSPrintfMakeWArgsExample) {
fmt::basic_format_args<fmt::wprintf_context> args2(as2);
EXPECT_EQ(L"[42] something happened",
fmt::vsprintf(L"[%d] %s happened", args2));
- // the older gcc versions can't cast the return value
-#if !defined(__GNUC__) || (__GNUC__ > 4)
EXPECT_EQ(L"[42] something happened",
fmt::vsprintf(L"[%d] %s happened",
{fmt::make_wprintf_args(42, L"something")}));
-#endif
-}
-
-TEST(PrintfTest, PrintfDetermineOutputSize) {
- using backit = std::back_insert_iterator<std::vector<char>>;
- using truncated_printf_context =
- fmt::basic_printf_context<fmt::detail::truncating_iterator<backit>, char>;
-
- auto v = std::vector<char>{};
- auto it = std::back_inserter(v);
-
- const auto format_string = "%s";
- const auto format_arg = "Hello";
- const auto expected_size = fmt::sprintf(format_string, format_arg).size();
-
- EXPECT_EQ((truncated_printf_context(
- fmt::detail::truncating_iterator<backit>(it, 0), format_string,
- fmt::make_format_args<truncated_printf_context>(format_arg))
- .format()
- .count()),
- expected_size);
}
diff --git a/contrib/libs/fmt/test/ranges-odr-test.cc b/contrib/libs/fmt/test/ranges-odr-test.cc
new file mode 100644
index 0000000000..031354d3c2
--- /dev/null
+++ b/contrib/libs/fmt/test/ranges-odr-test.cc
@@ -0,0 +1,17 @@
+// Formatting library for C++ - the core API
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include <vector>
+
+#include "fmt/ranges.h"
+#include "gtest/gtest.h"
+
+// call fmt::format from another translation unit to test ODR
+TEST(ranges_odr_test, format_vector) {
+ auto v = std::vector<int>{1, 2, 3, 5, 7, 11};
+ EXPECT_EQ(fmt::format("{}", v), "[1, 2, 3, 5, 7, 11]");
+}
diff --git a/contrib/libs/fmt/test/ranges-test.cc b/contrib/libs/fmt/test/ranges-test.cc
index 394f7b81be..63cb8c8bca 100644
--- a/contrib/libs/fmt/test/ranges-test.cc
+++ b/contrib/libs/fmt/test/ranges-test.cc
@@ -11,106 +11,109 @@
#include "fmt/ranges.h"
-#include <gtest/gtest.h>
+#include <map>
+#include <string>
+#include <vector>
-// Check if 'if constexpr' is supported.
-#if (__cplusplus > 201402L) || \
- (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
+#include "gtest/gtest.h"
-# include <array>
-# include <map>
-# include <string>
-# include <vector>
+#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 601
+# define FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
+#endif
-TEST(RangesTest, FormatVector) {
- std::vector<int32_t> iv{1, 2, 3, 5, 7, 11};
- auto ivf = fmt::format("{}", iv);
- EXPECT_EQ("{1, 2, 3, 5, 7, 11}", ivf);
-}
+#if !FMT_MSC_VER || FMT_MSC_VER > 1910
+# define FMT_RANGES_TEST_ENABLE_JOIN
+# define FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT
+#endif
-TEST(RangesTest, FormatVector2) {
- std::vector<std::vector<int32_t>> ivv{{1, 2}, {3, 5}, {7, 11}};
- auto ivf = fmt::format("{}", ivv);
- EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf);
+#ifdef FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
+TEST(ranges_test, format_array) {
+ int arr[] = {1, 2, 3, 5, 7, 11};
+ EXPECT_EQ(fmt::format("{}", arr), "[1, 2, 3, 5, 7, 11]");
}
-TEST(RangesTest, FormatMap) {
- std::map<std::string, int32_t> simap{{"one", 1}, {"two", 2}};
- EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", fmt::format("{}", simap));
+TEST(ranges_test, format_2d_array) {
+ int arr[][2] = {{1, 2}, {3, 5}, {7, 11}};
+ EXPECT_EQ(fmt::format("{}", arr), "[[1, 2], [3, 5], [7, 11]]");
}
-TEST(RangesTest, FormatPair) {
- std::pair<int64_t, float> pa1{42, 1.5f};
- EXPECT_EQ("(42, 1.5)", fmt::format("{}", pa1));
+TEST(ranges_test, format_array_of_literals) {
+ const char* arr[] = {"1234", "abcd"};
+ EXPECT_EQ(fmt::format("{}", arr), "[\"1234\", \"abcd\"]");
}
+#endif // FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
-TEST(RangesTest, FormatTuple) {
- std::tuple<int64_t, float, std::string, char> t{42, 1.5f, "this is tuple",
- 'i'};
- EXPECT_EQ("(42, 1.5, \"this is tuple\", 'i')", fmt::format("{}", t));
- EXPECT_EQ("()", fmt::format("{}", std::tuple<>()));
+TEST(ranges_test, format_vector) {
+ auto v = std::vector<int>{1, 2, 3, 5, 7, 11};
+ EXPECT_EQ(fmt::format("{}", v), "[1, 2, 3, 5, 7, 11]");
}
-TEST(RangesTest, JoinTuple) {
- // Value tuple args
- std::tuple<char, int, float> t1 = std::make_tuple('a', 1, 2.0f);
- EXPECT_EQ("(a, 1, 2)", fmt::format("({})", fmt::join(t1, ", ")));
+TEST(ranges_test, format_vector2) {
+ auto v = std::vector<std::vector<int>>{{1, 2}, {3, 5}, {7, 11}};
+ EXPECT_EQ(fmt::format("{}", v), "[[1, 2], [3, 5], [7, 11]]");
+}
- // Testing lvalue tuple args
- int x = 4;
- std::tuple<char, int&> t2{'b', x};
- EXPECT_EQ("b + 4", fmt::format("{}", fmt::join(t2, " + ")));
+TEST(ranges_test, format_map) {
+ auto m = std::map<std::string, int>{{"one", 1}, {"two", 2}};
+ EXPECT_EQ(fmt::format("{}", m), "{\"one\": 1, \"two\": 2}");
+}
- // Empty tuple
- std::tuple<> t3;
- EXPECT_EQ("", fmt::format("{}", fmt::join(t3, "|")));
+TEST(ranges_test, format_set) {
+ EXPECT_EQ(fmt::format("{}", std::set<std::string>{"one", "two"}),
+ "{\"one\", \"two\"}");
+}
- // Single element tuple
- std::tuple<float> t4{4.0f};
- EXPECT_EQ("4", fmt::format("{}", fmt::join(t4, "/")));
+TEST(ranges_test, format_pair) {
+ auto p = std::pair<int, float>(42, 1.5f);
+ EXPECT_EQ(fmt::format("{}", p), "(42, 1.5)");
}
-TEST(RangesTest, JoinInitializerList) {
- EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join({1, 2, 3}, ", ")));
- EXPECT_EQ("fmt rocks !",
- fmt::format("{}", fmt::join({"fmt", "rocks", "!"}, " ")));
+TEST(ranges_test, format_tuple) {
+ auto t =
+ std::tuple<int, float, std::string, char>(42, 1.5f, "this is tuple", 'i');
+ EXPECT_EQ(fmt::format("{}", t), "(42, 1.5, \"this is tuple\", 'i')");
+ EXPECT_EQ(fmt::format("{}", std::tuple<>()), "()");
}
-struct my_struct {
- int32_t i;
- std::string str; // can throw
- template <size_t N> decltype(auto) get() const noexcept {
- if constexpr (N == 0)
- return i;
- else if constexpr (N == 1)
- return fmt::string_view{str};
+#ifdef FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT
+struct tuple_like {
+ int i;
+ std::string str;
+
+ template <size_t N> fmt::enable_if_t<N == 0, int> get() const noexcept {
+ return i;
+ }
+ template <size_t N>
+ fmt::enable_if_t<N == 1, fmt::string_view> get() const noexcept {
+ return str;
}
};
-template <size_t N> decltype(auto) get(const my_struct& s) noexcept {
- return s.get<N>();
+template <size_t N>
+auto get(const tuple_like& t) noexcept -> decltype(t.get<N>()) {
+ return t.get<N>();
}
namespace std {
+template <>
+struct tuple_size<tuple_like> : std::integral_constant<size_t, 2> {};
-template <> struct tuple_size<my_struct> : std::integral_constant<size_t, 2> {};
-
-template <size_t N> struct tuple_element<N, my_struct> {
- using type = decltype(std::declval<my_struct>().get<N>());
+template <size_t N> struct tuple_element<N, tuple_like> {
+ using type = decltype(std::declval<tuple_like>().get<N>());
};
-
} // namespace std
-TEST(RangesTest, FormatStruct) {
- my_struct mst{13, "my struct"};
- EXPECT_EQ("(13, \"my struct\")", fmt::format("{}", mst));
+TEST(ranges_test, format_struct) {
+ auto t = tuple_like{42, "foo"};
+ EXPECT_EQ(fmt::format("{}", t), "(42, \"foo\")");
}
+#endif // FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT
-TEST(RangesTest, FormatTo) {
+TEST(ranges_test, format_to) {
char buf[10];
- auto end = fmt::format_to(buf, "{}", std::vector{1, 2, 3});
+ auto end = fmt::format_to(buf, "{}", std::vector<int>{1, 2, 3});
*end = '\0';
- EXPECT_STREQ(buf, "{1, 2, 3}");
+ EXPECT_STREQ(buf, "[1, 2, 3]");
}
struct path_like {
@@ -120,13 +123,10 @@ struct path_like {
operator std::string() const;
};
-TEST(RangesTest, PathLike) {
+TEST(ranges_test, path_like) {
EXPECT_FALSE((fmt::is_range<path_like, char>::value));
}
-#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
- // 201402L && _MSC_VER >= 1910)
-
#ifdef FMT_USE_STRING_VIEW
struct string_like {
const char* begin();
@@ -135,32 +135,15 @@ struct string_like {
explicit operator std::string_view() const { return "foo"; }
};
-TEST(RangesTest, FormatStringLike) {
- EXPECT_EQ("foo", fmt::format("{}", string_like()));
+TEST(ranges_test, format_string_like) {
+ EXPECT_EQ(fmt::format("{}", string_like()), "foo");
}
#endif // FMT_USE_STRING_VIEW
-struct zstring_sentinel {};
-
-bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
-bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
-
-struct zstring {
- const char* p;
- const char* begin() const { return p; }
- zstring_sentinel end() const { return {}; }
-};
-
-TEST(RangesTest, JoinSentinel) {
- zstring hello{"hello"};
- EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
- EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_")));
-}
-
// A range that provides non-const only begin()/end() to test fmt::join handles
-// that
+// that.
//
-// Some ranges (eg those produced by range-v3's views::filter()) can cache
+// Some ranges (e.g. those produced by range-v3's views::filter()) can cache
// information during iteration so they only provide non-const begin()/end().
template <typename T> class non_const_only_range {
private:
@@ -171,33 +154,210 @@ template <typename T> class non_const_only_range {
template <typename... Args>
explicit non_const_only_range(Args&&... args)
- : vec(::std::forward<Args>(args)...) {}
+ : vec(std::forward<Args>(args)...) {}
const_iterator begin() { return vec.begin(); }
const_iterator end() { return vec.end(); }
};
-TEST(RangesTest, JoinRange) {
+template <typename T> class noncopyable_range {
+ private:
+ std::vector<T> vec;
+
+ public:
+ using const_iterator = typename ::std::vector<T>::const_iterator;
+
+ template <typename... Args>
+ explicit noncopyable_range(Args&&... args)
+ : vec(std::forward<Args>(args)...) {}
+
+ noncopyable_range(noncopyable_range const&) = delete;
+ noncopyable_range(noncopyable_range&) = delete;
+
+ const_iterator begin() const { return vec.begin(); }
+ const_iterator end() const { return vec.end(); }
+};
+
+TEST(ranges_test, range) {
+ noncopyable_range<int> w(3u, 0);
+ EXPECT_EQ(fmt::format("{}", w), "[0, 0, 0]");
+ EXPECT_EQ(fmt::format("{}", noncopyable_range<int>(3u, 0)), "[0, 0, 0]");
+
non_const_only_range<int> x(3u, 0);
- EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(x, ",")));
- EXPECT_EQ(
- "0,0,0",
- fmt::format("{}", fmt::join(non_const_only_range<int>(3u, 0), ",")));
+ EXPECT_EQ(fmt::format("{}", x), "[0, 0, 0]");
+ EXPECT_EQ(fmt::format("{}", non_const_only_range<int>(3u, 0)), "[0, 0, 0]");
+
+ auto y = std::vector<int>(3u, 0);
+ EXPECT_EQ(fmt::format("{}", y), "[0, 0, 0]");
+ EXPECT_EQ(fmt::format("{}", std::vector<int>(3u, 0)), "[0, 0, 0]");
+
+ const auto z = std::vector<int>(3u, 0);
+ EXPECT_EQ(fmt::format("{}", z), "[0, 0, 0]");
+}
- std::vector<int> y(3u, 0);
- EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ",")));
- EXPECT_EQ("0,0,0",
- fmt::format("{}", fmt::join(std::vector<int>(3u, 0), ",")));
+enum test_enum { foo };
- const std::vector<int> z(3u, 0);
- EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ",")));
+TEST(ranges_test, enum_range) {
+ auto v = std::vector<test_enum>{test_enum::foo};
+ EXPECT_EQ(fmt::format("{}", v), "[0]");
}
-#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
+#if !FMT_MSC_VER
struct unformattable {};
-TEST(RangesTest, UnformattableRange) {
+TEST(ranges_test, unformattable_range) {
EXPECT_FALSE((fmt::has_formatter<std::vector<unformattable>,
fmt::format_context>::value));
}
#endif
+
+#ifdef FMT_RANGES_TEST_ENABLE_JOIN
+TEST(ranges_test, join_tuple) {
+ // Value tuple args.
+ auto t1 = std::tuple<char, int, float>('a', 1, 2.0f);
+ EXPECT_EQ(fmt::format("({})", fmt::join(t1, ", ")), "(a, 1, 2)");
+
+ // Testing lvalue tuple args.
+ int x = 4;
+ auto t2 = std::tuple<char, int&>('b', x);
+ EXPECT_EQ(fmt::format("{}", fmt::join(t2, " + ")), "b + 4");
+
+ // Empty tuple.
+ auto t3 = std::tuple<>();
+ EXPECT_EQ(fmt::format("{}", fmt::join(t3, "|")), "");
+
+ // Single element tuple.
+ auto t4 = std::tuple<float>(4.0f);
+ EXPECT_EQ(fmt::format("{}", fmt::join(t4, "/")), "4");
+
+# if FMT_TUPLE_JOIN_SPECIFIERS
+ // Specs applied to each element.
+ auto t5 = std::tuple<int, int, long>(-3, 100, 1);
+ EXPECT_EQ(fmt::format("{:+03}", fmt::join(t5, ", ")), "-03, +100, +01");
+
+ auto t6 = std::tuple<float, double, long double>(3, 3.14, 3.1415);
+ EXPECT_EQ(fmt::format("{:5.5f}", fmt::join(t6, ", ")),
+ "3.00000, 3.14000, 3.14150");
+
+ // Testing lvalue tuple args.
+ int y = -1;
+ auto t7 = std::tuple<int, int&, const int&>(3, y, y);
+ EXPECT_EQ(fmt::format("{:03}", fmt::join(t7, ", ")), "003, -01, -01");
+# endif
+}
+
+TEST(ranges_test, join_initializer_list) {
+ EXPECT_EQ(fmt::format("{}", fmt::join({1, 2, 3}, ", ")), "1, 2, 3");
+ EXPECT_EQ(fmt::format("{}", fmt::join({"fmt", "rocks", "!"}, " ")),
+ "fmt rocks !");
+}
+
+struct zstring_sentinel {};
+
+bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
+bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
+
+struct zstring {
+ const char* p;
+ const char* begin() const { return p; }
+ zstring_sentinel end() const { return {}; }
+};
+
+# ifdef __cpp_lib_ranges
+struct cpp20_only_range {
+ struct iterator {
+ int val = 0;
+
+ using value_type = int;
+ using difference_type = std::ptrdiff_t;
+ using iterator_concept = std::input_iterator_tag;
+
+ iterator() = default;
+ iterator(int i) : val(i) {}
+ int operator*() const { return val; }
+ iterator& operator++() {
+ ++val;
+ return *this;
+ }
+ void operator++(int) { ++*this; }
+ bool operator==(const iterator& rhs) const { return val == rhs.val; }
+ };
+
+ int lo;
+ int hi;
+
+ iterator begin() const { return iterator(lo); }
+ iterator end() const { return iterator(hi); }
+};
+
+static_assert(std::input_iterator<cpp20_only_range::iterator>);
+# endif
+
+TEST(ranges_test, join_sentinel) {
+ auto hello = zstring{"hello"};
+ EXPECT_EQ(fmt::format("{}", hello), "['h', 'e', 'l', 'l', 'o']");
+ EXPECT_EQ(fmt::format("{}", fmt::join(hello, "_")), "h_e_l_l_o");
+}
+
+TEST(ranges_test, join_range) {
+ noncopyable_range<int> w(3u, 0);
+ EXPECT_EQ(fmt::format("{}", fmt::join(w, ",")), "0,0,0");
+ EXPECT_EQ(fmt::format("{}", fmt::join(noncopyable_range<int>(3u, 0), ",")),
+ "0,0,0");
+
+ non_const_only_range<int> x(3u, 0);
+ EXPECT_EQ(fmt::format("{}", fmt::join(x, ",")), "0,0,0");
+ EXPECT_EQ(fmt::format("{}", fmt::join(non_const_only_range<int>(3u, 0), ",")),
+ "0,0,0");
+
+ auto y = std::vector<int>(3u, 0);
+ EXPECT_EQ(fmt::format("{}", fmt::join(y, ",")), "0,0,0");
+ EXPECT_EQ(fmt::format("{}", fmt::join(std::vector<int>(3u, 0), ",")),
+ "0,0,0");
+
+ const auto z = std::vector<int>(3u, 0);
+ EXPECT_EQ(fmt::format("{}", fmt::join(z, ",")), "0,0,0");
+
+# ifdef __cpp_lib_ranges
+ EXPECT_EQ(fmt::format("{}", cpp20_only_range{.lo = 0, .hi = 5}),
+ "[0, 1, 2, 3, 4]");
+ EXPECT_EQ(
+ fmt::format("{}", fmt::join(cpp20_only_range{.lo = 0, .hi = 5}, ",")),
+ "0,1,2,3,4");
+# endif
+}
+#endif // FMT_RANGES_TEST_ENABLE_JOIN
+
+TEST(ranges_test, is_printable) {
+ using fmt::detail::is_printable;
+ EXPECT_TRUE(is_printable(0x0323));
+ EXPECT_FALSE(is_printable(0x0378));
+ EXPECT_FALSE(is_printable(0x110000));
+}
+
+TEST(ranges_test, escape_string) {
+ using vec = std::vector<std::string>;
+ EXPECT_EQ(fmt::format("{}", vec{"\n\r\t\"\\"}), "[\"\\n\\r\\t\\\"\\\\\"]");
+ EXPECT_EQ(fmt::format("{}", vec{"\x07"}), "[\"\\x07\"]");
+ EXPECT_EQ(fmt::format("{}", vec{"\x7f"}), "[\"\\x7f\"]");
+ EXPECT_EQ(fmt::format("{}", vec{"n\xcc\x83"}), "[\"n\xcc\x83\"]");
+
+ if (fmt::detail::is_utf8()) {
+ EXPECT_EQ(fmt::format("{}", vec{"\xcd\xb8"}), "[\"\\u0378\"]");
+ // Unassigned Unicode code points.
+ EXPECT_EQ(fmt::format("{}", vec{"\xf0\xaa\x9b\x9e"}), "[\"\\U0002a6de\"]");
+ EXPECT_EQ(fmt::format("{}", vec{"\xf4\x8f\xbf\xc0"}),
+ "[\"\\xf4\\x8f\\xbf\\xc0\"]");
+ }
+}
+
+#ifdef FMT_USE_STRING_VIEW
+struct convertible_to_string_view {
+ operator std::string_view() const { return "foo"; }
+};
+
+TEST(ranges_test, escape_convertible_to_string_view) {
+ EXPECT_EQ(fmt::format("{}", std::vector<convertible_to_string_view>(1)),
+ "[\"foo\"]");
+}
+#endif // FMT_USE_STRING_VIEW
diff --git a/contrib/libs/fmt/test/scan-test.cc b/contrib/libs/fmt/test/scan-test.cc
index 90c0edef9b..7e327ea3f5 100644
--- a/contrib/libs/fmt/test/scan-test.cc
+++ b/contrib/libs/fmt/test/scan-test.cc
@@ -11,25 +11,25 @@
#include <climits>
-#include <gmock/gmock.h>
+#include "gmock/gmock.h"
#include "gtest-extra.h"
-TEST(ScanTest, ReadText) {
- fmt::string_view s = "foo";
+TEST(scan_test, read_text) {
+ auto s = fmt::string_view("foo");
auto end = fmt::scan(s, "foo");
EXPECT_EQ(end, s.end());
EXPECT_THROW_MSG(fmt::scan("fob", "foo"), fmt::format_error, "invalid input");
}
-TEST(ScanTest, ReadInt) {
- int n = 0;
+TEST(scan_test, read_int) {
+ auto n = int();
fmt::scan("42", "{}", n);
EXPECT_EQ(n, 42);
fmt::scan("-42", "{}", n);
EXPECT_EQ(n, -42);
}
-TEST(ScanTest, ReadLongLong) {
+TEST(scan_test, read_longlong) {
long long n = 0;
fmt::scan("42", "{}", n);
EXPECT_EQ(n, 42);
@@ -37,15 +37,15 @@ TEST(ScanTest, ReadLongLong) {
EXPECT_EQ(n, -42);
}
-TEST(ScanTest, ReadUInt) {
- unsigned n = 0;
+TEST(scan_test, read_uint) {
+ auto n = unsigned();
fmt::scan("42", "{}", n);
EXPECT_EQ(n, 42);
EXPECT_THROW_MSG(fmt::scan("-42", "{}", n), fmt::format_error,
"invalid input");
}
-TEST(ScanTest, ReadULongLong) {
+TEST(scan_test, read_ulonglong) {
unsigned long long n = 0;
fmt::scan("42", "{}", n);
EXPECT_EQ(n, 42);
@@ -53,14 +53,14 @@ TEST(ScanTest, ReadULongLong) {
"invalid input");
}
-TEST(ScanTest, ReadString) {
- std::string s;
+TEST(scan_test, read_string) {
+ auto s = std::string();
fmt::scan("foo", "{}", s);
EXPECT_EQ(s, "foo");
}
-TEST(ScanTest, ReadStringView) {
- fmt::string_view s;
+TEST(scan_test, read_string_view) {
+ auto s = fmt::string_view();
fmt::scan("foo", "{}", s);
EXPECT_EQ(s, "foo");
}
@@ -90,8 +90,8 @@ template <> struct scanner<tm> {
};
} // namespace fmt
-TEST(ScanTest, ReadCustom) {
- const char* input = "Date: 1985-10-25";
+TEST(scan_test, read_custom) {
+ auto input = "Date: 1985-10-25";
auto t = tm();
fmt::scan(input, "Date: {0:%Y-%m-%d}", t);
EXPECT_EQ(t.tm_year, 85);
@@ -100,16 +100,16 @@ TEST(ScanTest, ReadCustom) {
}
#endif
-TEST(ScanTest, InvalidFormat) {
+TEST(scan_test, invalid_format) {
EXPECT_THROW_MSG(fmt::scan("", "{}"), fmt::format_error,
"argument index out of range");
EXPECT_THROW_MSG(fmt::scan("", "{"), fmt::format_error,
"invalid format string");
}
-TEST(ScanTest, Example) {
- std::string key;
- int value;
+TEST(scan_test, example) {
+ auto key = std::string();
+ auto value = int();
fmt::scan("answer = 42", "{} = {}", key, value);
EXPECT_EQ(key, "answer");
EXPECT_EQ(value, 42);
diff --git a/contrib/libs/fmt/test/scan.h b/contrib/libs/fmt/test/scan.h
index de82067a49..41748ae895 100644
--- a/contrib/libs/fmt/test/scan.h
+++ b/contrib/libs/fmt/test/scan.h
@@ -169,13 +169,16 @@ struct scan_handler : error_handler {
scan_ctx_.advance_to(it + size);
}
- int on_arg_id() { return on_arg_id(next_arg_id_++); }
- int on_arg_id(int id) {
+ FMT_CONSTEXPR int on_arg_id() { return on_arg_id(next_arg_id_++); }
+ FMT_CONSTEXPR int on_arg_id(int id) {
if (id >= args_.size) on_error("argument index out of range");
arg_ = args_.data[id];
return id;
}
- int on_arg_id(string_view) { return on_error("invalid format"), 0; }
+ FMT_CONSTEXPR int on_arg_id(string_view id) {
+ if (id.data()) on_error("invalid format");
+ return 0;
+ }
void on_replacement_field(int, const char*) {
auto it = scan_ctx_.begin(), end = scan_ctx_.end();
diff --git a/contrib/libs/fmt/test/test-assert.h b/contrib/libs/fmt/test/test-assert.h
index f9df580539..ab7b2bf732 100644
--- a/contrib/libs/fmt/test/test-assert.h
+++ b/contrib/libs/fmt/test/test-assert.h
@@ -10,7 +10,11 @@
#include <stdexcept>
-#include <gtest/gtest.h>
+void throw_assertion_failure(const char* message);
+#define FMT_ASSERT(condition, message) \
+ if (!(condition)) throw_assertion_failure(message);
+
+#include "gtest/gtest.h"
class assertion_failure : public std::logic_error {
public:
@@ -22,8 +26,11 @@ class assertion_failure : public std::logic_error {
void assertion_failure::avoid_weak_vtable() {}
-#define FMT_ASSERT(condition, message) \
- if (!(condition)) throw assertion_failure(message);
+// We use a separate function (rather than throw directly from FMT_ASSERT) to
+// avoid GCC's -Wterminate warning when FMT_ASSERT is used in a destructor.
+inline void throw_assertion_failure(const char* message) {
+ throw assertion_failure(message);
+}
// Expects an assertion failure.
#define EXPECT_ASSERT(stmt, message) \
diff --git a/contrib/libs/fmt/test/unicode-test.cc b/contrib/libs/fmt/test/unicode-test.cc
new file mode 100644
index 0000000000..63c828dd8f
--- /dev/null
+++ b/contrib/libs/fmt/test/unicode-test.cc
@@ -0,0 +1,48 @@
+// Formatting library for C++ - Unicode tests
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include <iomanip>
+#include <locale>
+#include <vector>
+
+#include "fmt/chrono.h"
+#include "gmock/gmock.h"
+#include "util.h" // get_locale
+
+using testing::Contains;
+
+TEST(unicode_test, is_utf8) { EXPECT_TRUE(fmt::detail::is_utf8()); }
+
+TEST(unicode_test, legacy_locale) {
+ auto loc = get_locale("ru_RU.CP1251", "Russian_Russia.1251");
+ if (loc == std::locale::classic()) return;
+
+ auto s = std::string();
+ try {
+ s = fmt::format(loc, "День недели: {:L}", fmt::weekday(1));
+ } catch (const fmt::format_error& e) {
+ // Formatting can fail due to an unsupported encoding.
+ fmt::print("Format error: {}\n", e.what());
+ return;
+ }
+
+#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 500
+ auto&& os = std::ostringstream();
+ os.imbue(loc);
+ auto tm = std::tm();
+ tm.tm_wday = 1;
+ os << std::put_time(&tm, "%a");
+ auto wd = os.str();
+ if (wd == "??") {
+ EXPECT_EQ(s, "День недели: ??");
+ fmt::print("std::locale gives ?? as a weekday.\n");
+ return;
+ }
+#endif
+ EXPECT_THAT((std::vector<std::string>{"День недели: пн", "День недели: Пн"}),
+ Contains(s));
+}
diff --git a/contrib/libs/fmt/test/util.cc b/contrib/libs/fmt/test/util.cc
index d08dcbdcbf..f4cb74ca0a 100644
--- a/contrib/libs/fmt/test/util.cc
+++ b/contrib/libs/fmt/test/util.cc
@@ -9,42 +9,38 @@
#include <cstring>
-void increment(char* s) {
- for (int i = static_cast<int>(std::strlen(s)) - 1; i >= 0; --i) {
- if (s[i] != '9') {
- ++s[i];
- break;
- }
- s[i] = '0';
- }
-}
-
-std::string get_system_error(int error_code) {
-#if defined(__MINGW32__) || !defined(_WIN32)
- return strerror(error_code);
-#else
- enum { BUFFER_SIZE = 200 };
- char buffer[BUFFER_SIZE];
- if (strerror_s(buffer, BUFFER_SIZE, error_code))
- throw std::exception("strerror_s failed");
- return buffer;
-#endif
-}
-
-const char* const FILE_CONTENT = "Don't panic!";
+const char* const file_content = "Don't panic!";
fmt::buffered_file open_buffered_file(FILE** fp) {
#if FMT_USE_FCNTL
fmt::file read_end, write_end;
fmt::file::pipe(read_end, write_end);
- write_end.write(FILE_CONTENT, std::strlen(FILE_CONTENT));
+ write_end.write(file_content, std::strlen(file_content));
write_end.close();
fmt::buffered_file f = read_end.fdopen("r");
if (fp) *fp = f.get();
#else
fmt::buffered_file f("test-file", "w");
- fputs(FILE_CONTENT, f.get());
+ fputs(file_content, f.get());
if (fp) *fp = f.get();
#endif
return f;
}
+
+std::locale do_get_locale(const char* name) {
+ try {
+ return std::locale(name);
+ } catch (const std::runtime_error&) {
+ }
+ return std::locale::classic();
+}
+
+std::locale get_locale(const char* name, const char* alt_name) {
+ auto loc = do_get_locale(name);
+ if (loc == std::locale::classic() && alt_name) {
+ loc = do_get_locale(alt_name);
+ }
+ if (loc == std::locale::classic())
+ fmt::print(stderr, "{} locale is missing.\n", name);
+ return loc;
+}
diff --git a/contrib/libs/fmt/test/util.h b/contrib/libs/fmt/test/util.h
index 24a5f4e34b..2e58ad950c 100644
--- a/contrib/libs/fmt/test/util.h
+++ b/contrib/libs/fmt/test/util.h
@@ -7,11 +7,14 @@
#include <cstdarg>
#include <cstdio>
+#include <locale>
#include <string>
-#include "fmt/os.h"
-
-enum { BUFFER_SIZE = 256 };
+#ifdef FMT_MODULE_TEST
+import fmt;
+#else
+# include "fmt/os.h"
+#endif // FMT_MODULE_TEST
#ifdef _MSC_VER
# define FMT_VSNPRINTF vsprintf_s
@@ -27,12 +30,7 @@ void safe_sprintf(char (&buffer)[SIZE], const char* format, ...) {
va_end(args);
}
-// Increment a number in a string.
-void increment(char* s);
-
-std::string get_system_error(int error_code);
-
-extern const char* const FILE_CONTENT;
+extern const char* const file_content;
// Opens a buffered file for reading.
fmt::buffered_file open_buffered_file(FILE** fp = nullptr);
@@ -40,7 +38,7 @@ fmt::buffered_file open_buffered_file(FILE** fp = nullptr);
inline FILE* safe_fopen(const char* filename, const char* mode) {
#if defined(_WIN32) && !defined(__MINGW32__)
// Fix MSVC warning about "unsafe" fopen.
- FILE* f = 0;
+ FILE* f = nullptr;
errno = fopen_s(&f, filename, mode);
return f;
#else
@@ -48,37 +46,40 @@ inline FILE* safe_fopen(const char* filename, const char* mode) {
#endif
}
-template <typename Char> class BasicTestString {
+template <typename Char> class basic_test_string {
private:
std::basic_string<Char> value_;
- static const Char EMPTY[];
+ static const Char empty[];
public:
- explicit BasicTestString(const Char* value = EMPTY) : value_(value) {}
+ explicit basic_test_string(const Char* value = empty) : value_(value) {}
const std::basic_string<Char>& value() const { return value_; }
};
-template <typename Char> const Char BasicTestString<Char>::EMPTY[] = {0};
+template <typename Char> const Char basic_test_string<Char>::empty[] = {0};
-typedef BasicTestString<char> TestString;
-typedef BasicTestString<wchar_t> TestWString;
+typedef basic_test_string<char> test_string;
+typedef basic_test_string<wchar_t> test_wstring;
template <typename Char>
std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os,
- const BasicTestString<Char>& s) {
+ const basic_test_string<Char>& s) {
os << s.value();
return os;
}
-class Date {
+class date {
int year_, month_, day_;
public:
- Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
+ date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
int year() const { return year_; }
int month() const { return month_; }
int day() const { return day_; }
};
+
+// Returns a locale with the given name if available or classic locale othewise.
+std::locale get_locale(const char* name, const char* alt_name = nullptr);
diff --git a/contrib/libs/fmt/test/xchar-test.cc b/contrib/libs/fmt/test/xchar-test.cc
new file mode 100644
index 0000000000..346cd21262
--- /dev/null
+++ b/contrib/libs/fmt/test/xchar-test.cc
@@ -0,0 +1,502 @@
+// Formatting library for C++ - formatting library tests
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include "fmt/xchar.h"
+
+#include <complex>
+#include <cwchar>
+#include <vector>
+
+#include "fmt/chrono.h"
+#include "fmt/color.h"
+#include "fmt/ostream.h"
+#include "fmt/ranges.h"
+#include "gtest-extra.h" // Contains
+#include "util.h" // get_locale
+
+using fmt::detail::max_value;
+using testing::Contains;
+
+namespace test_ns {
+template <typename Char> class test_string {
+ private:
+ std::basic_string<Char> s_;
+
+ public:
+ test_string(const Char* s) : s_(s) {}
+ const Char* data() const { return s_.data(); }
+ size_t length() const { return s_.size(); }
+ operator const Char*() const { return s_.c_str(); }
+};
+
+template <typename Char>
+fmt::basic_string_view<Char> to_string_view(const test_string<Char>& s) {
+ return {s.data(), s.length()};
+}
+
+struct non_string {};
+} // namespace test_ns
+
+template <typename T> class is_string_test : public testing::Test {};
+
+using string_char_types = testing::Types<char, wchar_t, char16_t, char32_t>;
+TYPED_TEST_SUITE(is_string_test, string_char_types);
+
+template <typename Char>
+struct derived_from_string_view : fmt::basic_string_view<Char> {};
+
+TYPED_TEST(is_string_test, is_string) {
+ EXPECT_TRUE(fmt::detail::is_string<TypeParam*>::value);
+ EXPECT_TRUE(fmt::detail::is_string<const TypeParam*>::value);
+ EXPECT_TRUE(fmt::detail::is_string<TypeParam[2]>::value);
+ EXPECT_TRUE(fmt::detail::is_string<const TypeParam[2]>::value);
+ EXPECT_TRUE(fmt::detail::is_string<std::basic_string<TypeParam>>::value);
+ EXPECT_TRUE(fmt::detail::is_string<fmt::basic_string_view<TypeParam>>::value);
+ EXPECT_TRUE(
+ fmt::detail::is_string<derived_from_string_view<TypeParam>>::value);
+ using fmt_string_view = fmt::detail::std_string_view<TypeParam>;
+ EXPECT_TRUE(std::is_empty<fmt_string_view>::value !=
+ fmt::detail::is_string<fmt_string_view>::value);
+ EXPECT_TRUE(fmt::detail::is_string<test_ns::test_string<TypeParam>>::value);
+ EXPECT_FALSE(fmt::detail::is_string<test_ns::non_string>::value);
+}
+
+// std::is_constructible is broken in MSVC until version 2015.
+#if !FMT_MSC_VER || FMT_MSC_VER >= 1900
+struct explicitly_convertible_to_wstring_view {
+ explicit operator fmt::wstring_view() const { return L"foo"; }
+};
+
+TEST(xchar_test, format_explicitly_convertible_to_wstring_view) {
+ EXPECT_EQ(L"foo",
+ fmt::format(L"{}", explicitly_convertible_to_wstring_view()));
+}
+#endif
+
+TEST(xchar_test, format) {
+ EXPECT_EQ(L"42", fmt::format(L"{}", 42));
+ EXPECT_EQ(L"4.2", fmt::format(L"{}", 4.2));
+ EXPECT_EQ(L"abc", fmt::format(L"{}", L"abc"));
+ EXPECT_EQ(L"z", fmt::format(L"{}", L'z'));
+ EXPECT_THROW(fmt::format(L"{:*\x343E}", 42), fmt::format_error);
+ EXPECT_EQ(L"true", fmt::format(L"{}", true));
+ EXPECT_EQ(L"a", fmt::format(L"{0}", 'a'));
+ EXPECT_EQ(L"a", fmt::format(L"{0}", L'a'));
+ EXPECT_EQ(L"Cyrillic letter \x42e",
+ fmt::format(L"Cyrillic letter {}", L'\x42e'));
+ EXPECT_EQ(L"abc1", fmt::format(L"{}c{}", L"ab", 1));
+}
+
+TEST(xchar_test, is_formattable) {
+ static_assert(!fmt::is_formattable<const wchar_t*>::value, "");
+}
+
+TEST(xchar_test, compile_time_string) {
+#if defined(FMT_USE_STRING_VIEW) && __cplusplus >= 201703L
+ EXPECT_EQ(L"42", fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42));
+#endif
+}
+
+#if __cplusplus > 201103L
+struct custom_char {
+ int value;
+ custom_char() = default;
+
+ template <typename T>
+ constexpr custom_char(T val) : value(static_cast<int>(val)) {}
+
+ operator int() const { return value; }
+};
+
+int to_ascii(custom_char c) { return c; }
+
+FMT_BEGIN_NAMESPACE
+template <> struct is_char<custom_char> : std::true_type {};
+FMT_END_NAMESPACE
+
+TEST(xchar_test, format_custom_char) {
+ const custom_char format[] = {'{', '}', 0};
+ auto result = fmt::format(format, custom_char('x'));
+ EXPECT_EQ(result.size(), 1);
+ EXPECT_EQ(result[0], custom_char('x'));
+}
+#endif
+
+// Convert a char8_t string to std::string. Otherwise GTest will insist on
+// inserting `char8_t` NTBS into a `char` stream which is disabled by P1423.
+template <typename S> std::string from_u8str(const S& str) {
+ return std::string(str.begin(), str.end());
+}
+
+TEST(xchar_test, format_utf8_precision) {
+ using str_type = std::basic_string<fmt::detail::char8_type>;
+ auto format =
+ str_type(reinterpret_cast<const fmt::detail::char8_type*>(u8"{:.4}"));
+ auto str = str_type(reinterpret_cast<const fmt::detail::char8_type*>(
+ u8"caf\u00e9s")); // cafés
+ auto result = fmt::format(format, str);
+ EXPECT_EQ(fmt::detail::compute_width(result), 4);
+ EXPECT_EQ(result.size(), 5);
+ EXPECT_EQ(from_u8str(result), from_u8str(str.substr(0, 5)));
+}
+
+TEST(xchar_test, format_to) {
+ auto buf = std::vector<wchar_t>();
+ fmt::format_to(std::back_inserter(buf), L"{}{}", 42, L'\0');
+ EXPECT_STREQ(buf.data(), L"42");
+}
+
+TEST(xchar_test, vformat_to) {
+ using wcontext = fmt::wformat_context;
+ fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42);
+ auto wargs = fmt::basic_format_args<wcontext>(&warg, 1);
+ auto w = std::wstring();
+ fmt::vformat_to(std::back_inserter(w), L"{}", wargs);
+ EXPECT_EQ(L"42", w);
+ w.clear();
+ fmt::vformat_to(std::back_inserter(w), FMT_STRING(L"{}"), wargs);
+ EXPECT_EQ(L"42", w);
+}
+
+TEST(format_test, wide_format_to_n) {
+ wchar_t buffer[4];
+ buffer[3] = L'x';
+ auto result = fmt::format_to_n(buffer, 3, L"{}", 12345);
+ EXPECT_EQ(5u, result.size);
+ EXPECT_EQ(buffer + 3, result.out);
+ EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4));
+ buffer[0] = L'x';
+ buffer[1] = L'x';
+ buffer[2] = L'x';
+ result = fmt::format_to_n(buffer, 3, L"{}", L'A');
+ EXPECT_EQ(1u, result.size);
+ EXPECT_EQ(buffer + 1, result.out);
+ EXPECT_EQ(L"Axxx", fmt::wstring_view(buffer, 4));
+ result = fmt::format_to_n(buffer, 3, L"{}{} ", L'B', L'C');
+ EXPECT_EQ(3u, result.size);
+ EXPECT_EQ(buffer + 3, result.out);
+ EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4));
+}
+
+#if FMT_USE_USER_DEFINED_LITERALS
+TEST(xchar_test, format_udl) {
+ using namespace fmt::literals;
+ EXPECT_EQ(L"{}c{}"_format(L"ab", 1), fmt::format(L"{}c{}", L"ab", 1));
+}
+
+TEST(xchar_test, named_arg_udl) {
+ using namespace fmt::literals;
+ auto udl_a =
+ fmt::format(L"{first}{second}{first}{third}", L"first"_a = L"abra",
+ L"second"_a = L"cad", L"third"_a = 99);
+ EXPECT_EQ(
+ fmt::format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"),
+ fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)),
+ udl_a);
+}
+#endif // FMT_USE_USER_DEFINED_LITERALS
+
+TEST(xchar_test, print) {
+ // Check that the wide print overload compiles.
+ if (fmt::detail::const_check(false)) fmt::print(L"test");
+}
+
+TEST(xchar_test, join) {
+ int v[3] = {1, 2, 3};
+ EXPECT_EQ(fmt::format(L"({})", fmt::join(v, v + 3, L", ")), L"(1, 2, 3)");
+ auto t = std::tuple<wchar_t, int, float>('a', 1, 2.0f);
+ EXPECT_EQ(fmt::format(L"({})", fmt::join(t, L", ")), L"(a, 1, 2)");
+}
+
+enum streamable_enum {};
+
+std::wostream& operator<<(std::wostream& os, streamable_enum) {
+ return os << L"streamable_enum";
+}
+
+enum unstreamable_enum {};
+
+TEST(xchar_test, enum) {
+ EXPECT_EQ(L"streamable_enum", fmt::format(L"{}", streamable_enum()));
+ EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum()));
+}
+
+TEST(xchar_test, sign_not_truncated) {
+ wchar_t format_str[] = {
+ L'{', L':',
+ '+' | static_cast<wchar_t>(1 << fmt::detail::num_bits<char>()), L'}', 0};
+ EXPECT_THROW(fmt::format(format_str, 42), fmt::format_error);
+}
+
+namespace fake_qt {
+class QString {
+ public:
+ QString(const wchar_t* s) : s_(s) {}
+ const wchar_t* utf16() const FMT_NOEXCEPT { return s_.data(); }
+ int size() const FMT_NOEXCEPT { return static_cast<int>(s_.size()); }
+
+ private:
+ std::wstring s_;
+};
+
+fmt::basic_string_view<wchar_t> to_string_view(const QString& s) FMT_NOEXCEPT {
+ return {s.utf16(), static_cast<size_t>(s.size())};
+}
+} // namespace fake_qt
+
+TEST(format_test, format_foreign_strings) {
+ using fake_qt::QString;
+ EXPECT_EQ(fmt::format(QString(L"{}"), 42), L"42");
+ EXPECT_EQ(fmt::format(QString(L"{}"), QString(L"42")), L"42");
+}
+
+TEST(xchar_test, chrono) {
+ auto tm = std::tm();
+ 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(L"42s", fmt::format(L"{}", std::chrono::seconds(42)));
+ EXPECT_EQ(fmt::format(L"{:%F}", tm), L"2016-04-25");
+ EXPECT_EQ(fmt::format(L"{:%T}", tm), L"11:22:33");
+}
+
+std::wstring system_wcsftime(const std::wstring& format, const std::tm* timeptr,
+ std::locale* locptr = nullptr) {
+ auto loc = locptr ? *locptr : std::locale::classic();
+ auto& facet = std::use_facet<std::time_put<wchar_t>>(loc);
+ std::wostringstream os;
+ os.imbue(loc);
+ facet.put(os, os, L' ', timeptr, format.c_str(),
+ format.c_str() + format.size());
+#ifdef _WIN32
+ // Workaround a bug in older versions of Universal CRT.
+ auto str = os.str();
+ if (str == L"-0000") str = L"+0000";
+ return str;
+#else
+ return os.str();
+#endif
+}
+
+TEST(chrono_test, time_point) {
+ auto t1 = std::chrono::system_clock::now();
+
+ std::vector<std::wstring> spec_list = {
+ L"%%", L"%n", L"%t", L"%Y", L"%EY", L"%y", L"%Oy", L"%Ey", L"%C",
+ L"%EC", L"%G", L"%g", L"%b", L"%h", L"%B", L"%m", L"%Om", L"%U",
+ L"%OU", L"%W", L"%OW", L"%V", L"%OV", L"%j", L"%d", L"%Od", L"%e",
+ L"%Oe", L"%a", L"%A", L"%w", L"%Ow", L"%u", L"%Ou", L"%H", L"%OH",
+ L"%I", L"%OI", L"%M", L"%OM", L"%S", L"%OS", L"%x", L"%Ex", L"%X",
+ L"%EX", L"%D", L"%F", L"%R", L"%T", L"%p", L"%z", L"%Z"};
+ spec_list.push_back(L"%Y-%m-%d %H:%M:%S");
+#ifndef _WIN32
+ // Disabled on Windows, because these formats is not consistent among
+ // platforms.
+ spec_list.insert(spec_list.end(), {L"%c", L"%Ec", L"%r"});
+#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_wcsftime(spec, &tm);
+
+ auto fmt_spec = fmt::format(L"{{:{}}}", spec);
+ EXPECT_EQ(sys_output, fmt::format(fmt_spec, t1));
+ EXPECT_EQ(sys_output, fmt::format(fmt_spec, tm));
+ }
+}
+
+TEST(xchar_test, color) {
+ EXPECT_EQ(fmt::format(fg(fmt::rgb(255, 20, 30)), L"rgb(255,20,30) wide"),
+ L"\x1b[38;2;255;020;030mrgb(255,20,30) wide\x1b[0m");
+}
+
+TEST(xchar_test, ostream) {
+ std::wostringstream wos;
+ fmt::print(wos, L"Don't {}!", L"panic");
+ EXPECT_EQ(L"Don't panic!", wos.str());
+}
+
+TEST(xchar_test, to_wstring) { EXPECT_EQ(L"42", fmt::to_wstring(42)); }
+
+#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+template <typename Char> struct numpunct : std::numpunct<Char> {
+ protected:
+ Char do_decimal_point() const override { return '?'; }
+ std::string do_grouping() const override { return "\03"; }
+ Char do_thousands_sep() const override { return '~'; }
+};
+
+template <typename Char> struct no_grouping : std::numpunct<Char> {
+ protected:
+ Char do_decimal_point() const override { return '.'; }
+ std::string do_grouping() const override { return ""; }
+ Char do_thousands_sep() const override { return ','; }
+};
+
+template <typename Char> struct special_grouping : std::numpunct<Char> {
+ protected:
+ Char do_decimal_point() const override { return '.'; }
+ std::string do_grouping() const override { return "\03\02"; }
+ Char do_thousands_sep() const override { return ','; }
+};
+
+template <typename Char> struct small_grouping : std::numpunct<Char> {
+ protected:
+ Char do_decimal_point() const override { return '.'; }
+ std::string do_grouping() const override { return "\01"; }
+ Char do_thousands_sep() const override { return ','; }
+};
+
+TEST(locale_test, localized_double) {
+ auto loc = std::locale(std::locale(), new numpunct<char>());
+ EXPECT_EQ("1?23", fmt::format(loc, "{:L}", 1.23));
+ EXPECT_EQ("1?230000", fmt::format(loc, "{:Lf}", 1.23));
+ EXPECT_EQ("1~234?5", fmt::format(loc, "{:L}", 1234.5));
+ EXPECT_EQ("12~000", fmt::format(loc, "{:L}", 12000.0));
+}
+
+TEST(locale_test, format) {
+ auto loc = std::locale(std::locale(), new numpunct<char>());
+ EXPECT_EQ("1234567", fmt::format(std::locale(), "{:L}", 1234567));
+ EXPECT_EQ("1~234~567", fmt::format(loc, "{:L}", 1234567));
+ EXPECT_EQ("-1~234~567", fmt::format(loc, "{:L}", -1234567));
+ EXPECT_EQ("-256", fmt::format(loc, "{:L}", -256));
+ fmt::format_arg_store<fmt::format_context, int> as{1234567};
+ EXPECT_EQ("1~234~567", fmt::vformat(loc, "{:L}", fmt::format_args(as)));
+ auto s = std::string();
+ fmt::format_to(std::back_inserter(s), loc, "{:L}", 1234567);
+ EXPECT_EQ("1~234~567", s);
+
+ auto no_grouping_loc = std::locale(std::locale(), new no_grouping<char>());
+ EXPECT_EQ("1234567", fmt::format(no_grouping_loc, "{:L}", 1234567));
+
+ auto special_grouping_loc =
+ std::locale(std::locale(), new special_grouping<char>());
+ EXPECT_EQ("1,23,45,678", fmt::format(special_grouping_loc, "{:L}", 12345678));
+ EXPECT_EQ("12,345", fmt::format(special_grouping_loc, "{:L}", 12345));
+
+ auto small_grouping_loc =
+ std::locale(std::locale(), new small_grouping<char>());
+ EXPECT_EQ("4,2,9,4,9,6,7,2,9,5",
+ fmt::format(small_grouping_loc, "{:L}", max_value<uint32_t>()));
+}
+
+TEST(locale_test, format_detault_align) {
+ auto loc = std::locale({}, new special_grouping<char>());
+ EXPECT_EQ(" 12,345", fmt::format(loc, "{:8L}", 12345));
+}
+
+TEST(locale_test, format_plus) {
+ auto loc = std::locale({}, new special_grouping<char>());
+ EXPECT_EQ("+100", fmt::format(loc, "{:+L}", 100));
+}
+
+TEST(locale_test, wformat) {
+ auto loc = std::locale(std::locale(), new numpunct<wchar_t>());
+ EXPECT_EQ(L"1234567", fmt::format(std::locale(), L"{:L}", 1234567));
+ EXPECT_EQ(L"1~234~567", fmt::format(loc, L"{:L}", 1234567));
+ using wcontext = fmt::buffer_context<wchar_t>;
+ fmt::format_arg_store<wcontext, int> as{1234567};
+ EXPECT_EQ(L"1~234~567",
+ fmt::vformat(loc, L"{:L}", fmt::basic_format_args<wcontext>(as)));
+ EXPECT_EQ(L"1234567", fmt::format(std::locale("C"), L"{:L}", 1234567));
+
+ auto no_grouping_loc = std::locale(std::locale(), new no_grouping<wchar_t>());
+ EXPECT_EQ(L"1234567", fmt::format(no_grouping_loc, L"{:L}", 1234567));
+
+ auto special_grouping_loc =
+ std::locale(std::locale(), new special_grouping<wchar_t>());
+ EXPECT_EQ(L"1,23,45,678",
+ fmt::format(special_grouping_loc, L"{:L}", 12345678));
+
+ auto small_grouping_loc =
+ std::locale(std::locale(), new small_grouping<wchar_t>());
+ EXPECT_EQ(L"4,2,9,4,9,6,7,2,9,5",
+ fmt::format(small_grouping_loc, L"{:L}", max_value<uint32_t>()));
+}
+
+TEST(locale_test, double_formatter) {
+ auto loc = std::locale(std::locale(), new special_grouping<char>());
+ auto f = fmt::formatter<int>();
+ auto parse_ctx = fmt::format_parse_context("L");
+ f.parse(parse_ctx);
+ char buf[10] = {};
+ fmt::basic_format_context<char*, char> format_ctx(
+ buf, {}, fmt::detail::locale_ref(loc));
+ *f.format(12345, format_ctx) = 0;
+ EXPECT_STREQ("12,345", buf);
+}
+
+FMT_BEGIN_NAMESPACE
+template <class charT> struct formatter<std::complex<double>, charT> {
+ private:
+ detail::dynamic_format_specs<char> specs_;
+
+ public:
+ FMT_CONSTEXPR typename basic_format_parse_context<charT>::iterator parse(
+ basic_format_parse_context<charT>& ctx) {
+ using handler_type =
+ detail::dynamic_specs_handler<basic_format_parse_context<charT>>;
+ detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
+ detail::type::string_type);
+ auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
+ detail::parse_float_type_spec(specs_, ctx.error_handler());
+ return it;
+ }
+
+ template <class FormatContext>
+ typename FormatContext::iterator format(const std::complex<double>& c,
+ FormatContext& ctx) {
+ detail::handle_dynamic_spec<detail::precision_checker>(
+ specs_.precision, specs_.precision_ref, ctx);
+ auto specs = std::string();
+ if (specs_.precision > 0) specs = fmt::format(".{}", specs_.precision);
+ if (specs_.type == presentation_type::fixed_lower) specs += 'f';
+ auto real = fmt::format(ctx.locale().template get<std::locale>(),
+ fmt::runtime("{:" + specs + "}"), c.real());
+ auto imag = fmt::format(ctx.locale().template get<std::locale>(),
+ fmt::runtime("{:" + specs + "}"), c.imag());
+ auto fill_align_width = std::string();
+ if (specs_.width > 0) fill_align_width = fmt::format(">{}", specs_.width);
+ return format_to(ctx.out(), runtime("{:" + fill_align_width + "}"),
+ c.real() != 0 ? fmt::format("({}+{}i)", real, imag)
+ : fmt::format("{}i", imag));
+ }
+};
+FMT_END_NAMESPACE
+
+TEST(locale_test, complex) {
+ std::string s = fmt::format("{}", std::complex<double>(1, 2));
+ EXPECT_EQ(s, "(1+2i)");
+ EXPECT_EQ(fmt::format("{:.2f}", std::complex<double>(1, 2)), "(1.00+2.00i)");
+ EXPECT_EQ(fmt::format("{:8}", std::complex<double>(1, 2)), " (1+2i)");
+}
+
+TEST(locale_test, chrono_weekday) {
+ auto loc = get_locale("ru_RU.UTF-8", "Russian_Russia.1251");
+ auto loc_old = std::locale::global(loc);
+ auto mon = fmt::weekday(1);
+ EXPECT_EQ(fmt::format(L"{}", mon), L"Mon");
+ if (loc != std::locale::classic()) {
+ // {L"\x43F\x43D", L"\x41F\x43D", L"\x43F\x43D\x434", L"\x41F\x43D\x434"}
+ // {L"пн", L"Пн", L"пнд", L"Пнд"}
+ EXPECT_THAT(
+ (std::vector<std::wstring>{L"\x43F\x43D", L"\x41F\x43D",
+ L"\x43F\x43D\x434", L"\x41F\x43D\x434"}),
+ Contains(fmt::format(loc, L"{:L}", mon)));
+ }
+ std::locale::global(loc_old);
+}
+
+#endif // FMT_STATIC_THOUSANDS_SEPARATOR