From 270f6649cc93abdd27d7663e84c0af6f2c7085a6 Mon Sep 17 00:00:00 2001 From: Walter Gray Date: Thu, 3 Dec 2020 20:20:26 -0800 Subject: [PATCH] trim down compiletime test --- test/enforce-compiletime-test.cc | 569 ++----------------------------- 1 file changed, 22 insertions(+), 547 deletions(-) diff --git a/test/enforce-compiletime-test.cc b/test/enforce-compiletime-test.cc index 4170a93eee49e..7f05d29a5077c 100644 --- a/test/enforce-compiletime-test.cc +++ b/test/enforce-compiletime-test.cc @@ -28,90 +28,19 @@ #undef index #include "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::string_view; -using fmt::wmemory_buffer; -using fmt::wstring_view; -using fmt::detail::max_value; - -using testing::Return; -using testing::StrictMock; - -class Answer {}; - -FMT_BEGIN_NAMESPACE -template <> struct formatter : formatter { - template - auto format(Answer, FormatContext& ctx) -> decltype(ctx.out()) { - return formatter::format(42, ctx); - } -}; -FMT_END_NAMESPACE - -struct string_like { - const char* begin(); - const char* end(); -#if defined(FMT_USE_STRING_VIEW) - explicit operator fmt::string_view() const { return "foo"; } - explicit operator std::string_view() const { return "foo"; } -#endif -}; - -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 wchar_t static_with_null_wide[3] = {'{', '}', - '\0'}; -static FMT_CONSTEXPR_DECL const char static_no_null[2] = {'{', '}'}; -static FMT_CONSTEXPR_DECL const wchar_t static_no_null_wide[2] = {'{', '}'}; -TEST(FormatTest, CompileTimeString) { +TEST(CompileTimeTest, FormatApi) { 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())); - - (void)static_with_null; - (void)static_with_null_wide; - (void)static_no_null; - (void)static_no_null_wide; -#if !defined(_MSC_VER) - EXPECT_EQ("42", fmt::format(FMT_STRING(static_with_null), 42)); - EXPECT_EQ(L"42", fmt::format(FMT_STRING(static_with_null_wide), 42)); - EXPECT_EQ("42", fmt::format(FMT_STRING(static_no_null), 42)); - EXPECT_EQ(L"42", fmt::format(FMT_STRING(static_no_null_wide), 42)); -#endif - - (void)with_null; - (void)no_null; -#if __cplusplus >= 201703L - EXPECT_EQ("42", fmt::format(FMT_STRING(with_null), 42)); - EXPECT_EQ("42", fmt::format(FMT_STRING(no_null), 42)); -#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 -} + EXPECT_EQ("42", fmt::to_string(42)); + EXPECT_EQ(L"42", fmt::to_wstring(42)); -TEST(FormatTest, CustomFormatCompileTimeString) { - EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), Answer())); - Answer answer; - EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), answer)); - char buf[10] = {}; - fmt::format_to(buf, FMT_STRING("{}"), answer); - const Answer const_answer = Answer(); - EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), const_answer)); + std::list out; + fmt::format_to(std::back_inserter(out), FMT_STRING("{}"), 42); + EXPECT_EQ("42", std::string(out.begin(), out.end())); + std::stringstream s; + fmt::format_to(std::ostream_iterator(s), FMT_STRING("{}"), 42); + EXPECT_EQ("42", s.str()); } #if FMT_USE_UDL_TEMPLATE @@ -121,102 +50,34 @@ TEST(FormatTest, CustomFormatCompileTimeString) { using namespace fmt::literals; -TEST(LiteralsTest, Format) { +TEST(CompileTimeTest, Literals) { auto udl_format = "{}c{}"_format("ab", 1); EXPECT_EQ("abc1", udl_format); auto udl_format_w = L"{}c{}"_format(L"ab", 1); EXPECT_EQ(L"abc1", udl_format_w); } +#endif -#endif // FMT_USE_UDL_TEMPLATE - -enum TestEnum { A }; - -namespace adl_test { -namespace fmt { -namespace detail { -struct foo {}; -template void write(OutputIt, foo) = delete; -} // namespace detail -} // namespace fmt -} // namespace adl_test - -FMT_BEGIN_NAMESPACE -template <> -struct formatter : formatter { - template - auto format(adl_test::fmt::detail::foo, FormatContext& ctx) - -> decltype(ctx.out()) { - return formatter::format("foo", ctx); - } -}; -FMT_END_NAMESPACE - -TEST(FormatTest, ToString) { - EXPECT_EQ("42", fmt::to_string(42)); - EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast(0x1234))); - EXPECT_EQ("foo", fmt::to_string(adl_test::fmt::detail::foo())); -} - -TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); } - -TEST(FormatTest, OutputIterators) { - std::list out; - fmt::format_to(std::back_inserter(out), FMT_STRING("{}"), 42); - EXPECT_EQ("42", std::string(out.begin(), out.end())); - std::stringstream s; - fmt::format_to(std::ostream_iterator(s), FMT_STRING("{}"), 42); - EXPECT_EQ("42", s.str()); -} - -TEST(FormatTest, FormattedSize) { +TEST(CompileTimeTest, FormattedSize) { EXPECT_EQ(2u, fmt::formatted_size(FMT_STRING("{}"), 42)); } -TEST(FormatTest, FormatTo) { +TEST(CompileTimeTest, FormatTo) { std::vector v; fmt::format_to(std::back_inserter(v), FMT_STRING("{}"), "foo"); EXPECT_EQ(fmt::string_view(v.data(), v.size()), "foo"); } -TEST(FormatTest, FormatToN) { +TEST(CompileTimeTest, FormatToN) { char buffer[4]; buffer[3] = 'x'; auto result = fmt::format_to_n(buffer, 3, FMT_STRING("{}"), 12345); EXPECT_EQ(5u, result.size); EXPECT_EQ(buffer + 3, result.out); EXPECT_EQ("123x", fmt::string_view(buffer, 4)); - - result = fmt::format_to_n(buffer, 3, FMT_STRING("{:s}"), "foobar"); - EXPECT_EQ(6u, result.size); - EXPECT_EQ(buffer + 3, result.out); - EXPECT_EQ("foox", fmt::string_view(buffer, 4)); - - buffer[0] = 'x'; - buffer[1] = 'x'; - buffer[2] = 'x'; - result = fmt::format_to_n(buffer, 3, FMT_STRING("{}"), 'A'); - EXPECT_EQ(1u, result.size); - EXPECT_EQ(buffer + 1, result.out); - EXPECT_EQ("Axxx", fmt::string_view(buffer, 4)); - - result = fmt::format_to_n(buffer, 3, FMT_STRING("{}{} "), 'B', 'C'); - EXPECT_EQ(3u, result.size); - EXPECT_EQ(buffer + 3, result.out); - EXPECT_EQ("BC x", fmt::string_view(buffer, 4)); - - result = fmt::format_to_n(buffer, 4, FMT_STRING("{}"), "ABCDE"); - EXPECT_EQ(5u, result.size); - EXPECT_EQ("ABCD", fmt::string_view(buffer, 4)); - - buffer[3] = 'x'; - result = - fmt::format_to_n(buffer, 3, FMT_STRING("{}"), std::string(1000, '*')); - EXPECT_EQ(1000u, result.size); - EXPECT_EQ("***x", fmt::string_view(buffer, 4)); } -TEST(FormatTest, WideFormatToN) { +TEST(CompileTimeTest, WideFormatToN) { wchar_t buffer[4]; buffer[3] = L'x'; auto result = fmt::format_to_n(buffer, 3, FMT_STRING(L"{}"), 12345); @@ -257,148 +118,38 @@ struct test_output_iterator { char& operator*() { return *data; } }; -TEST(FormatTest, FormatToNOutputIterator) { +TEST(CompileTimeTest, FormatToNOutputIterator) { char buf[10] = {}; fmt::format_to_n(test_output_iterator{buf}, 10, FMT_STRING("{}"), 42); EXPECT_STREQ(buf, "42"); } -TEST(FormatTest, VFormatTo) { - typedef fmt::format_context context; - fmt::basic_format_arg arg = fmt::detail::make_arg(42); - fmt::basic_format_args args(&arg, 1); - std::string s; - fmt::vformat_to(std::back_inserter(s), FMT_STRING("{}"), args); - EXPECT_EQ("42", s); - - typedef fmt::wformat_context wcontext; - fmt::basic_format_arg warg = fmt::detail::make_arg(42); - fmt::basic_format_args wargs(&warg, 1); - std::wstring w; - fmt::vformat_to(std::back_inserter(w), FMT_STRING(L"{}"), wargs); - EXPECT_EQ(L"42", w); -} - -template 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"); -} - #ifndef FMT_STATIC_THOUSANDS_SEPARATOR -TEST(ChronoTest, FormatDefault) { +TEST(CompileTimeTest, Chrono) { EXPECT_EQ("42s", fmt::format(FMT_STRING("{}"), std::chrono::seconds(42))); } -TEST(ChronoTest, FormatWide) { +TEST(CompileTimeTest, ChronoWide) { EXPECT_EQ(L"42s", fmt::format(FMT_STRING(L"{}"), std::chrono::seconds(42))); } -typedef std::chrono::duration dms; - -TEST(ChronoTest, FormatDefaultFP) { - EXPECT_EQ("1.234ms", fmt::format(FMT_STRING("{}"), dms(1.234))); -} - -TEST(ChronoTest, FormatPrecision) { - EXPECT_EQ("1.2ms", fmt::format(FMT_STRING("{:.1}"), dms(1.234))); - EXPECT_EQ("1.23ms", fmt::format(FMT_STRING("{:.{}}"), dms(1.234), 2)); -} - -TEST(ChronoTest, FormatFullSpecs) { - EXPECT_EQ("1.2ms ", fmt::format(FMT_STRING("{:6.1}"), dms(1.234))); - EXPECT_EQ(" 1.2ms ", fmt::format(FMT_STRING("{:^{}.{}}"), dms(1.234), 7, 1)); -} - -TEST(ChronoTest, FormatSimpleQq) { - typedef std::chrono::duration fs; - EXPECT_EQ("1.234 s", fmt::format(FMT_STRING("{:%Q %q}"), fs(1.234))); - typedef std::chrono::duration fms; - EXPECT_EQ("1.234 ms", fmt::format(FMT_STRING("{:%Q %q}"), fms(1.234))); - typedef std::chrono::duration ds; - EXPECT_EQ("1.234 s", fmt::format(FMT_STRING("{:%Q %q}"), ds(1.234))); - EXPECT_EQ("1.234 ms", fmt::format(FMT_STRING("{:%Q %q}"), dms(1.234))); -} - -TEST(ChronoTest, FormatPrecisionQq) { - EXPECT_EQ("1.2 ms", fmt::format(FMT_STRING("{:.1%Q %q}"), dms(1.234))); - EXPECT_EQ("1.23 ms", fmt::format(FMT_STRING("{:.{}%Q %q}"), dms(1.234), 2)); -} - -TEST(ChronoTest, FormatFullSpecsQq) { - EXPECT_EQ("1.2 ms ", fmt::format(FMT_STRING("{:7.1%Q %q}"), dms(1.234))); - EXPECT_EQ(" 1.2 ms ", - fmt::format(FMT_STRING("{:^{}.{}%Q %q}"), dms(1.234), 8, 1)); -} - -TEST(ChronoTest, UnsignedDuration) { - EXPECT_EQ("42s", - fmt::format(FMT_STRING("{}"), std::chrono::duration(42))); -} - #endif // FMT_STATIC_THOUSANDS_SEPARATOR -TEST(ColorsTest, ColorsPrint) { +TEST(CompileTimeTest, PrintTextStyle) { EXPECT_WRITE( stdout, fmt::print(fg(fmt::rgb(255, 20, 30)), FMT_STRING("{}"), "rgb(255,20,30)"), "\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m"); - EXPECT_WRITE(stdout, - fmt::print(fg(fmt::color::blue) | bg(fmt::color::red), - FMT_STRING("{}"), "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, FMT_STRING("{}"), "bold"), - "\x1b[1mbold\x1b[0m"); - EXPECT_WRITE(stdout, - fmt::print(fg(fmt::color::blue) | fmt::emphasis::bold, - FMT_STRING("{}"), "blue/bold"), - "\x1b[1m\x1b[38;2;000;000;255mblue/bold\x1b[0m"); - EXPECT_WRITE(stdout, fmt::print(fmt::text_style(), FMT_STRING("{}"), "hi"), - "hi"); - EXPECT_WRITE( - stdout, - fmt::print(fg(fmt::terminal_color::red), FMT_STRING("{}"), "tred"), - "\x1b[31mtred\x1b[0m"); - EXPECT_WRITE( - stdout, - fmt::print(bg(fmt::terminal_color::cyan), FMT_STRING("{}"), "tcyan"), - "\x1b[46mtcyan\x1b[0m"); - EXPECT_WRITE(stdout, - fmt::print(bg(fmt::terminal_color::bright_magenta), - FMT_STRING("{}"), "tbmagenta"), - "\x1b[105mtbmagenta\x1b[0m"); } -TEST(ColorsTest, Format) { +TEST(CompileTimeTest, FormatTextStyle) { EXPECT_EQ("\x1b[38;2;255;020;030mrgb(255,20,30)\x1b[0m", fmt::format(fg(fmt::rgb(255, 20, 30)), FMT_STRING("{}"), "rgb(255,20,30)")); - EXPECT_EQ("\x1b[38;2;000;000;255mblue\x1b[0m", - fmt::format(fg(fmt::color::blue), FMT_STRING("{}"), "blue")); - EXPECT_EQ("\x1b[38;2;000;000;255m\x1b[48;2;255;000;000mtwo color\x1b[0m", - fmt::format(fg(fmt::color::blue) | bg(fmt::color::red), - FMT_STRING("{}"), "two color")); - EXPECT_EQ("\x1b[1mbold\x1b[0m", - fmt::format(fmt::emphasis::bold, FMT_STRING("{}"), "bold")); - EXPECT_EQ("\x1b[1m\x1b[38;2;000;000;255mblue/bold\x1b[0m", - fmt::format(fg(fmt::color::blue) | fmt::emphasis::bold, - FMT_STRING("{}"), "blue/bold")); - EXPECT_EQ("hi", fmt::format(fmt::text_style(), FMT_STRING("{}"), "hi")); - EXPECT_EQ("\x1b[31mtred\x1b[0m", fmt::format(fg(fmt::terminal_color::red), - FMT_STRING("{}"), "tred")); - EXPECT_EQ("\x1b[46mtcyan\x1b[0m", fmt::format(bg(fmt::terminal_color::cyan), - FMT_STRING("{}"), "tcyan")); - EXPECT_EQ("\x1b[105mtbmagenta\x1b[0m", - fmt::format(bg(fmt::terminal_color::bright_magenta), - FMT_STRING("{}"), "tbmagenta")); } -TEST(ColorsTest, FormatToOutAcceptsTextStyle) { +TEST(CompileTimeTest, FormatToOutAcceptsTextStyle) { fmt::text_style ts = fg(fmt::rgb(255, 20, 30)); std::string out; fmt::format_to(std::back_inserter(out), ts, @@ -410,219 +161,10 @@ TEST(ColorsTest, FormatToOutAcceptsTextStyle) { 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 : formatter { - template - typename FormatContext::iterator format(const test&, FormatContext& ctx) { - return formatter::format(42, ctx); - } -}; -} // namespace fmt - -struct EmptyTest {}; -static std::ostream& operator<<(std::ostream& os, EmptyTest) { - return os << ""; -} - -TEST(OStreamTest, EmptyCustomOutput) { - EXPECT_EQ("", fmt::format(FMT_STRING("{}"), EmptyTest())); -} - -TEST(OStreamTest, Print) { - std::ostringstream os; - fmt::print(os, FMT_STRING("Don't {}!"), "panic"); - EXPECT_EQ("Don't panic!", os.str()); - std::wostringstream wos; - fmt::print(wos, FMT_STRING(L"Don't {}!"), L"panic"); - EXPECT_EQ(L"Don't panic!", wos.str()); -} - -TEST(OStreamTest, Join) { - int v[3] = {1, 2, 3}; - EXPECT_EQ("1, 2, 3", - fmt::format(FMT_STRING("{}"), fmt::join(v, v + 3, ", "))); -} - -namespace fmt_test { -struct ABC {}; - -template Output& operator<<(Output& out, ABC) { - out << "ABC"; - return out; -} -} // namespace fmt_test - -template struct TestTemplate {}; - -template -std::ostream& operator<<(std::ostream& os, TestTemplate) { - return os << 1; -} - -namespace fmt { -template struct formatter> : formatter { - template - typename FormatContext::iterator format(TestTemplate, FormatContext& ctx) { - return formatter::format(2, ctx); - } -}; -} // namespace fmt - -#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 407 -TEST(OStreamTest, Template) { - EXPECT_EQ("2", fmt::format(FMT_STRING("{}"), TestTemplate())); -} - -TEST(OStreamTest, FormatToN) { - char buffer[4]; - buffer[3] = 'x'; - auto result = fmt::format_to_n(buffer, 3, FMT_STRING("{}"), fmt_test::ABC()); - EXPECT_EQ(3u, result.size); - EXPECT_EQ(buffer + 3, result.out); - EXPECT_EQ("ABCx", fmt::string_view(buffer, 4)); -} -#endif - -TEST(OStreamTest, CompileTimeString) { - EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42)); -} - -TEST(OStreamTest, ToString) { - EXPECT_EQ("ABC", fmt::to_string(fmt_test::ABC())); -} - // Check if 'if constexpr' is supported. #if (__cplusplus > 201402L) || \ (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) -TEST(RangesTest, FormatArray) { - int32_t ia[] = {1, 2, 3, 5, 7, 11}; - auto iaf = fmt::format(FMT_STRING("{}"), ia); - EXPECT_EQ("{1, 2, 3, 5, 7, 11}", iaf); -} - -TEST(RangesTest, Format2dArray) { - int32_t ia[][2] = {{1, 2}, {3, 5}, {7, 11}}; - auto iaf = fmt::format(FMT_STRING("{}"), ia); - EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", iaf); -} - -TEST(RangesTest, FormatVector) { - std::vector iv{1, 2, 3, 5, 7, 11}; - auto ivf = fmt::format(FMT_STRING("{}"), iv); - EXPECT_EQ("{1, 2, 3, 5, 7, 11}", ivf); -} - -TEST(RangesTest, FormatVector2) { - std::vector> ivv{{1, 2}, {3, 5}, {7, 11}}; - auto ivf = fmt::format(FMT_STRING("{}"), ivv); - EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf); -} - -TEST(RangesTest, FormatMap) { - std::map simap{{"one", 1}, {"two", 2}}; - EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", - fmt::format(FMT_STRING("{}"), simap)); -} - -TEST(RangesTest, FormatPair) { - std::pair pa1{42, 1.5f}; - EXPECT_EQ("(42, 1.5)", fmt::format(FMT_STRING("{}"), pa1)); -} - -TEST(RangesTest, FormatTuple) { - std::tuple t{42, 1.5f, "this is tuple", - 'i'}; - EXPECT_EQ("(42, 1.5, \"this is tuple\", 'i')", - fmt::format(FMT_STRING("{}"), t)); - EXPECT_EQ("()", fmt::format(FMT_STRING("{}"), std::tuple<>())); -} - -TEST(RangesTest, JoinTuple) { - // Value tuple args - std::tuple t1 = std::make_tuple('a', 1, 2.0f); - EXPECT_EQ("(a, 1, 2)", fmt::format(FMT_STRING("({})"), fmt::join(t1, ", "))); - - // Testing lvalue tuple args - int x = 4; - std::tuple t2{'b', x}; - EXPECT_EQ("b + 4", fmt::format(FMT_STRING("{}"), fmt::join(t2, " + "))); - - // Empty tuple - std::tuple<> t3; - EXPECT_EQ("", fmt::format(FMT_STRING("{}"), fmt::join(t3, "|"))); - - // Single element tuple - std::tuple t4{4.0f}; - EXPECT_EQ("4", fmt::format(FMT_STRING("{}"), fmt::join(t4, "/"))); -} - -TEST(RangesTest, JoinInitializerList) { - EXPECT_EQ("1, 2, 3", - fmt::format(FMT_STRING("{}"), fmt::join({1, 2, 3}, ", "))); - EXPECT_EQ("fmt rocks !", fmt::format(FMT_STRING("{}"), - fmt::join({"fmt", "rocks", "!"}, " "))); -} - -struct my_struct { - int32_t i; - std::string str; // can throw - template decltype(auto) get() const noexcept { - if constexpr (N == 0) - return i; - else if constexpr (N == 1) - return fmt::string_view{str}; - } -}; - -template decltype(auto) get(const my_struct& s) noexcept { - return s.get(); -} - -namespace std { - -template <> struct tuple_size : std::integral_constant {}; - -template struct tuple_element { - using type = decltype(std::declval().get()); -}; - -} // namespace std - -TEST(RangesTest, FormatStruct) { - my_struct mst{13, "my struct"}; - EXPECT_EQ("(13, \"my struct\")", fmt::format(FMT_STRING("{}"), mst)); -} - -TEST(RangesTest, FormatTo) { - char buf[10]; - auto end = fmt::format_to(buf, FMT_STRING("{}"), std::vector{1, 2, 3}); - *end = '\0'; - EXPECT_STREQ(buf, "{1, 2, 3}"); -} - -struct path_like { - const path_like* begin() const; - const path_like* end() const; - - operator std::string() const; -}; - -TEST(RangesTest, PathLike) { - EXPECT_FALSE((fmt::is_range::value)); -} - -#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > - // 201402L && _MSC_VER >= 1910) - -#ifdef FMT_USE_STRING_VIEW -TEST(RangesTest, FormatStringLike) { - EXPECT_EQ("foo", fmt::format(FMT_STRING("{}"), string_like())); -} -#endif // FMT_USE_STRING_VIEW - struct zstring_sentinel {}; bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; } @@ -634,75 +176,8 @@ struct zstring { zstring_sentinel end() const { return {}; } }; -TEST(RangesTest, JoinSentinel) { +TEST(CompileTimeTest, JoinSentinel) { zstring hello{"hello"}; EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format(FMT_STRING("{}"), hello)); EXPECT_EQ("h_e_l_l_o", fmt::format(FMT_STRING("{}"), fmt::join(hello, "_"))); } - -// A range that provides non-const only begin()/end() to test fmt::join handles -// that -// -// Some ranges (eg those produced by range-v3's views::filter()) can cache -// information during iteration so they only provide non-const begin()/end(). -template class non_const_only_range { - private: - std::vector vec; - - public: - using const_iterator = typename ::std::vector::const_iterator; - - template - explicit non_const_only_range(Args&&... args) - : vec(::std::forward(args)...) {} - - const_iterator begin() { return vec.begin(); } - const_iterator end() { return vec.end(); } -}; - -template class noncopyable_range { - private: - std::vector vec; - - public: - using const_iterator = typename ::std::vector::const_iterator; - - template - explicit noncopyable_range(Args&&... args) - : vec(::std::forward(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(RangesTest, Range) { - noncopyable_range w(3u, 0); - EXPECT_EQ("{0, 0, 0}", fmt::format(FMT_STRING("{}"), w)); - EXPECT_EQ("{0, 0, 0}", - fmt::format(FMT_STRING("{}"), noncopyable_range(3u, 0))); - - non_const_only_range x(3u, 0); - EXPECT_EQ("{0, 0, 0}", fmt::format(FMT_STRING("{}"), x)); - EXPECT_EQ("{0, 0, 0}", - fmt::format(FMT_STRING("{}"), non_const_only_range(3u, 0))); - - std::vector y(3u, 0); - EXPECT_EQ("{0, 0, 0}", fmt::format(FMT_STRING("{}"), y)); - EXPECT_EQ("{0, 0, 0}", - fmt::format(FMT_STRING("{}"), std::vector(3u, 0))); - - const std::vector z(3u, 0); - EXPECT_EQ("{0, 0, 0}", fmt::format(FMT_STRING("{}"), z)); -} - -#if !FMT_MSC_VER || FMT_MSC_VER >= 1927 -struct unformattable {}; - -TEST(RangesTest, UnformattableRange) { - EXPECT_FALSE((fmt::has_formatter, - fmt::format_context>::value)); -} -#endif