1 // Formatting library for C++ - formatting library tests
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #include <string>
9 #include <type_traits>
10
11 // Check that fmt/compile.h compiles with windows.h included before it.
12 #ifdef _WIN32
13 # include <windows.h>
14 #endif
15
16 #include "fmt/compile.h"
17 #include "gmock.h"
18 #include "gtest-extra.h"
19 #include "util.h"
20
21 // compiletime_prepared_parts_type_provider is useful only with relaxed
22 // constexpr.
23 #if FMT_USE_CONSTEXPR
24 template <unsigned EXPECTED_PARTS_COUNT, typename Format>
check_prepared_parts_type(Format format)25 void check_prepared_parts_type(Format format) {
26 typedef fmt::detail::compiled_format_base<decltype(format)> provider;
27 typedef fmt::detail::format_part<char>
28 expected_parts_type[EXPECTED_PARTS_COUNT];
29 static_assert(std::is_same<typename provider::parts_container,
30 expected_parts_type>::value,
31 "CompileTimePreparedPartsTypeProvider test failed");
32 }
33
TEST(CompileTest,CompileTimePreparedPartsTypeProvider)34 TEST(CompileTest, CompileTimePreparedPartsTypeProvider) {
35 check_prepared_parts_type<1u>(FMT_STRING("text"));
36 check_prepared_parts_type<1u>(FMT_STRING("{}"));
37 check_prepared_parts_type<2u>(FMT_STRING("text{}"));
38 check_prepared_parts_type<2u>(FMT_STRING("{}text"));
39 check_prepared_parts_type<3u>(FMT_STRING("text{}text"));
40 check_prepared_parts_type<3u>(FMT_STRING("{:{}.{}} {:{}}"));
41
42 check_prepared_parts_type<3u>(FMT_STRING("{{{}}}")); // '{', 'argument', '}'
43 check_prepared_parts_type<2u>(FMT_STRING("text{{")); // 'text', '{'
44 check_prepared_parts_type<3u>(FMT_STRING("text{{ ")); // 'text', '{', ' '
45 check_prepared_parts_type<2u>(FMT_STRING("}}text")); // '}', text
46 check_prepared_parts_type<2u>(FMT_STRING("text}}text")); // 'text}', 'text'
47 check_prepared_parts_type<4u>(
48 FMT_STRING("text{{}}text")); // 'text', '{', '}', 'text'
49 }
50 #endif
51
TEST(CompileTest,PassStringLiteralFormat)52 TEST(CompileTest, PassStringLiteralFormat) {
53 const auto prepared = fmt::detail::compile<int>("test {}");
54 EXPECT_EQ("test 42", fmt::format(prepared, 42));
55 const auto wprepared = fmt::detail::compile<int>(L"test {}");
56 EXPECT_EQ(L"test 42", fmt::format(wprepared, 42));
57 }
58
TEST(CompileTest,FormatToArrayOfChars)59 TEST(CompileTest, FormatToArrayOfChars) {
60 char buffer[32] = {0};
61 const auto prepared = fmt::detail::compile<int>("4{}");
62 fmt::format_to(fmt::detail::make_checked(buffer, 32), prepared, 2);
63 EXPECT_EQ(std::string("42"), buffer);
64 wchar_t wbuffer[32] = {0};
65 const auto wprepared = fmt::detail::compile<int>(L"4{}");
66 fmt::format_to(fmt::detail::make_checked(wbuffer, 32), wprepared, 2);
67 EXPECT_EQ(std::wstring(L"42"), wbuffer);
68 }
69
TEST(CompileTest,FormatToIterator)70 TEST(CompileTest, FormatToIterator) {
71 std::string s(2, ' ');
72 const auto prepared = fmt::detail::compile<int>("4{}");
73 fmt::format_to(s.begin(), prepared, 2);
74 EXPECT_EQ("42", s);
75 std::wstring ws(2, L' ');
76 const auto wprepared = fmt::detail::compile<int>(L"4{}");
77 fmt::format_to(ws.begin(), wprepared, 2);
78 EXPECT_EQ(L"42", ws);
79 }
80
TEST(CompileTest,FormatToN)81 TEST(CompileTest, FormatToN) {
82 char buf[5];
83 auto f = fmt::detail::compile<int>("{:10}");
84 auto result = fmt::format_to_n(buf, 5, f, 42);
85 EXPECT_EQ(result.size, 10);
86 EXPECT_EQ(result.out, buf + 5);
87 EXPECT_EQ(fmt::string_view(buf, 5), " ");
88 }
89
TEST(CompileTest,FormattedSize)90 TEST(CompileTest, FormattedSize) {
91 auto f = fmt::detail::compile<int>("{:10}");
92 EXPECT_EQ(fmt::formatted_size(f, 42), 10);
93 }
94
TEST(CompileTest,MultipleTypes)95 TEST(CompileTest, MultipleTypes) {
96 auto f = fmt::detail::compile<int, int>("{} {}");
97 EXPECT_EQ(fmt::format(f, 42, 42), "42 42");
98 }
99
100 struct test_formattable {};
101
102 FMT_BEGIN_NAMESPACE
103 template <> struct formatter<test_formattable> : formatter<const char*> {
104 template <typename FormatContext>
formatformatter105 auto format(test_formattable, FormatContext& ctx) -> decltype(ctx.out()) {
106 return formatter<const char*>::format("foo", ctx);
107 }
108 };
109 FMT_END_NAMESPACE
110
TEST(CompileTest,FormatUserDefinedType)111 TEST(CompileTest, FormatUserDefinedType) {
112 auto f = fmt::detail::compile<test_formattable>("{}");
113 EXPECT_EQ(fmt::format(f, test_formattable()), "foo");
114 }
115
TEST(CompileTest,EmptyFormatString)116 TEST(CompileTest, EmptyFormatString) {
117 auto f = fmt::detail::compile<>("");
118 EXPECT_EQ(fmt::format(f), "");
119 }
120
121 #ifdef __cpp_if_constexpr
TEST(CompileTest,FormatDefault)122 TEST(CompileTest, FormatDefault) {
123 EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42));
124 EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42u));
125 EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42ll));
126 EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42ull));
127 EXPECT_EQ("true", fmt::format(FMT_COMPILE("{}"), true));
128 EXPECT_EQ("x", fmt::format(FMT_COMPILE("{}"), 'x'));
129 EXPECT_EQ("4.2", fmt::format(FMT_COMPILE("{}"), 4.2));
130 EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), "foo"));
131 EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), std::string("foo")));
132 EXPECT_EQ("foo", fmt::format(FMT_COMPILE("{}"), test_formattable()));
133 }
134
TEST(CompileTest,FormatWideString)135 TEST(CompileTest, FormatWideString) {
136 EXPECT_EQ(L"42", fmt::format(FMT_COMPILE(L"{}"), 42));
137 }
138
TEST(CompileTest,FormatSpecs)139 TEST(CompileTest, FormatSpecs) {
140 EXPECT_EQ("42", fmt::format(FMT_COMPILE("{:x}"), 0x42));
141 }
142
TEST(CompileTest,DynamicWidth)143 TEST(CompileTest, DynamicWidth) {
144 EXPECT_EQ(" 42foo ",
145 fmt::format(FMT_COMPILE("{:{}}{:{}}"), 42, 4, "foo", 5));
146 }
147
TEST(CompileTest,FormatTo)148 TEST(CompileTest, FormatTo) {
149 char buf[8];
150 auto end = fmt::format_to(buf, FMT_COMPILE("{}"), 42);
151 *end = '\0';
152 EXPECT_STREQ("42", buf);
153 end = fmt::format_to(buf, FMT_COMPILE("{:x}"), 42);
154 *end = '\0';
155 EXPECT_STREQ("2a", buf);
156 }
157
TEST(CompileTest,FormatToNWithCompileMacro)158 TEST(CompileTest, FormatToNWithCompileMacro) {
159 constexpr auto buffer_size = 8;
160 char buffer[buffer_size];
161 auto res = fmt::format_to_n(buffer, buffer_size, FMT_COMPILE("{}"), 42);
162 *res.out = '\0';
163 EXPECT_STREQ("42", buffer);
164 res = fmt::format_to_n(buffer, buffer_size, FMT_COMPILE("{:x}"), 42);
165 *res.out = '\0';
166 EXPECT_STREQ("2a", buffer);
167 }
168
TEST(CompileTest,TextAndArg)169 TEST(CompileTest, TextAndArg) {
170 EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42));
171 EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42));
172 }
173 #endif
174