]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 | ||
9f95a23c | 8 | #include <stdint.h> |
f67539c2 | 9 | |
11fdf7f2 TL |
10 | #include <cctype> |
11 | #include <cfloat> | |
12 | #include <climits> | |
13 | #include <cmath> | |
14 | #include <cstring> | |
15 | #include <list> | |
16 | #include <memory> | |
eafe8130 | 17 | #include <string> |
11fdf7f2 TL |
18 | |
19 | // Check if fmt/format.h compiles with windows.h included before it. | |
20 | #ifdef _WIN32 | |
9f95a23c | 21 | # include <windows.h> |
11fdf7f2 TL |
22 | #endif |
23 | ||
f67539c2 TL |
24 | // Check if fmt/format.h compiles with the X11 index macro defined. |
25 | #define index(x, y) no nice things | |
26 | ||
9f95a23c | 27 | #include "fmt/color.h" |
f67539c2 TL |
28 | #include "fmt/format.h" |
29 | ||
30 | #undef index | |
31 | ||
11fdf7f2 TL |
32 | #include "gmock.h" |
33 | #include "gtest-extra.h" | |
34 | #include "mock-allocator.h" | |
35 | #include "util.h" | |
36 | ||
37 | #undef ERROR | |
11fdf7f2 TL |
38 | |
39 | using fmt::basic_memory_buffer; | |
11fdf7f2 TL |
40 | using fmt::format; |
41 | using fmt::format_error; | |
11fdf7f2 | 42 | using fmt::memory_buffer; |
9f95a23c | 43 | using fmt::string_view; |
11fdf7f2 | 44 | using fmt::wmemory_buffer; |
f67539c2 TL |
45 | using fmt::wstring_view; |
46 | using fmt::detail::max_value; | |
11fdf7f2 TL |
47 | |
48 | using testing::Return; | |
49 | using testing::StrictMock; | |
50 | ||
51 | namespace { | |
52 | ||
eafe8130 | 53 | #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 408 |
9f95a23c TL |
54 | template <typename Char, typename T> bool check_enabled_formatter() { |
55 | static_assert(std::is_default_constructible<fmt::formatter<T, Char>>::value, | |
56 | ""); | |
eafe8130 TL |
57 | return true; |
58 | } | |
59 | ||
9f95a23c | 60 | template <typename Char, typename... T> void check_enabled_formatters() { |
eafe8130 TL |
61 | auto dummy = {check_enabled_formatter<Char, T>()...}; |
62 | (void)dummy; | |
63 | } | |
64 | ||
65 | TEST(FormatterTest, TestFormattersEnabled) { | |
9f95a23c TL |
66 | check_enabled_formatters<char, bool, char, signed char, unsigned char, short, |
67 | unsigned short, int, unsigned, long, unsigned long, | |
68 | long long, unsigned long long, float, double, | |
69 | long double, void*, const void*, char*, const char*, | |
f67539c2 | 70 | std::string, std::nullptr_t>(); |
9f95a23c TL |
71 | check_enabled_formatters<wchar_t, bool, wchar_t, signed char, unsigned char, |
72 | short, unsigned short, int, unsigned, long, | |
73 | unsigned long, long long, unsigned long long, float, | |
74 | double, long double, void*, const void*, wchar_t*, | |
f67539c2 | 75 | const wchar_t*, std::wstring, std::nullptr_t>(); |
eafe8130 TL |
76 | } |
77 | #endif | |
78 | ||
11fdf7f2 TL |
79 | // Format value using the standard library. |
80 | template <typename Char, typename T> | |
9f95a23c | 81 | void std_format(const T& value, std::basic_string<Char>& result) { |
11fdf7f2 TL |
82 | std::basic_ostringstream<Char> os; |
83 | os << value; | |
84 | result = os.str(); | |
85 | } | |
86 | ||
87 | #ifdef __MINGW32__ | |
88 | // Workaround a bug in formatting long double in MinGW. | |
9f95a23c | 89 | void std_format(long double value, std::string& result) { |
11fdf7f2 TL |
90 | char buffer[100]; |
91 | safe_sprintf(buffer, "%Lg", value); | |
92 | result = buffer; | |
93 | } | |
9f95a23c | 94 | void std_format(long double value, std::wstring& result) { |
11fdf7f2 TL |
95 | wchar_t buffer[100]; |
96 | swprintf(buffer, L"%Lg", value); | |
97 | result = buffer; | |
98 | } | |
99 | #endif | |
11fdf7f2 TL |
100 | } // namespace |
101 | ||
11fdf7f2 TL |
102 | struct uint32_pair { |
103 | uint32_t u[2]; | |
104 | }; | |
105 | ||
106 | TEST(UtilTest, BitCast) { | |
f67539c2 TL |
107 | auto s = fmt::detail::bit_cast<uint32_pair>(uint64_t{42}); |
108 | EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), 42ull); | |
109 | s = fmt::detail::bit_cast<uint32_pair>(uint64_t(~0ull)); | |
110 | EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), ~0ull); | |
11fdf7f2 TL |
111 | } |
112 | ||
113 | TEST(UtilTest, Increment) { | |
114 | char s[10] = "123"; | |
115 | increment(s); | |
116 | EXPECT_STREQ("124", s); | |
117 | s[2] = '8'; | |
118 | increment(s); | |
119 | EXPECT_STREQ("129", s); | |
120 | increment(s); | |
121 | EXPECT_STREQ("130", s); | |
122 | s[1] = s[2] = '9'; | |
123 | increment(s); | |
124 | EXPECT_STREQ("200", s); | |
125 | } | |
126 | ||
127 | TEST(UtilTest, ParseNonnegativeInt) { | |
f67539c2 | 128 | if (max_value<int>() != static_cast<int>(static_cast<unsigned>(1) << 31)) { |
11fdf7f2 TL |
129 | fmt::print("Skipping parse_nonnegative_int test\n"); |
130 | return; | |
131 | } | |
9f95a23c TL |
132 | fmt::string_view s = "10000000000"; |
133 | auto begin = s.begin(), end = s.end(); | |
11fdf7f2 | 134 | EXPECT_THROW_MSG( |
f67539c2 | 135 | parse_nonnegative_int(begin, end, fmt::detail::error_handler()), |
9f95a23c | 136 | fmt::format_error, "number is too big"); |
11fdf7f2 | 137 | s = "2147483649"; |
9f95a23c TL |
138 | begin = s.begin(); |
139 | end = s.end(); | |
11fdf7f2 | 140 | EXPECT_THROW_MSG( |
f67539c2 | 141 | parse_nonnegative_int(begin, end, fmt::detail::error_handler()), |
9f95a23c | 142 | fmt::format_error, "number is too big"); |
11fdf7f2 TL |
143 | } |
144 | ||
145 | TEST(IteratorTest, CountingIterator) { | |
f67539c2 | 146 | fmt::detail::counting_iterator it; |
11fdf7f2 TL |
147 | auto prev = it++; |
148 | EXPECT_EQ(prev.count(), 0); | |
149 | EXPECT_EQ(it.count(), 1); | |
150 | } | |
151 | ||
152 | TEST(IteratorTest, TruncatingIterator) { | |
f67539c2 TL |
153 | char* p = nullptr; |
154 | fmt::detail::truncating_iterator<char*> it(p, 3); | |
11fdf7f2 TL |
155 | auto prev = it++; |
156 | EXPECT_EQ(prev.base(), p); | |
157 | EXPECT_EQ(it.base(), p + 1); | |
158 | } | |
159 | ||
eafe8130 TL |
160 | TEST(IteratorTest, TruncatingBackInserter) { |
161 | std::string buffer; | |
162 | auto bi = std::back_inserter(buffer); | |
f67539c2 | 163 | fmt::detail::truncating_iterator<decltype(bi)> it(bi, 2); |
eafe8130 TL |
164 | *it++ = '4'; |
165 | *it++ = '2'; | |
166 | *it++ = '1'; | |
167 | EXPECT_EQ(buffer.size(), 2); | |
168 | EXPECT_EQ(buffer, "42"); | |
169 | } | |
170 | ||
171 | TEST(IteratorTest, IsOutputIterator) { | |
f67539c2 TL |
172 | EXPECT_TRUE(fmt::detail::is_output_iterator<char*>::value); |
173 | EXPECT_FALSE(fmt::detail::is_output_iterator<const char*>::value); | |
174 | EXPECT_FALSE(fmt::detail::is_output_iterator<std::string>::value); | |
175 | EXPECT_TRUE(fmt::detail::is_output_iterator< | |
eafe8130 | 176 | std::back_insert_iterator<std::string>>::value); |
f67539c2 | 177 | EXPECT_TRUE(fmt::detail::is_output_iterator<std::string::iterator>::value); |
9f95a23c | 178 | EXPECT_FALSE( |
f67539c2 TL |
179 | fmt::detail::is_output_iterator<std::string::const_iterator>::value); |
180 | EXPECT_FALSE(fmt::detail::is_output_iterator<std::list<char>>::value); | |
9f95a23c | 181 | EXPECT_TRUE( |
f67539c2 TL |
182 | fmt::detail::is_output_iterator<std::list<char>::iterator>::value); |
183 | EXPECT_FALSE( | |
184 | fmt::detail::is_output_iterator<std::list<char>::const_iterator>::value); | |
185 | EXPECT_FALSE(fmt::detail::is_output_iterator<uint32_pair>::value); | |
eafe8130 TL |
186 | } |
187 | ||
11fdf7f2 TL |
188 | TEST(MemoryBufferTest, Ctor) { |
189 | basic_memory_buffer<char, 123> buffer; | |
190 | EXPECT_EQ(static_cast<size_t>(0), buffer.size()); | |
191 | EXPECT_EQ(123u, buffer.capacity()); | |
192 | } | |
193 | ||
9f95a23c TL |
194 | static void check_forwarding(mock_allocator<int>& alloc, |
195 | allocator_ref<mock_allocator<int>>& ref) { | |
11fdf7f2 TL |
196 | int mem; |
197 | // Check if value_type is properly defined. | |
9f95a23c | 198 | allocator_ref<mock_allocator<int>>::value_type* ptr = &mem; |
11fdf7f2 TL |
199 | // Check forwarding. |
200 | EXPECT_CALL(alloc, allocate(42)).WillOnce(testing::Return(ptr)); | |
201 | ref.allocate(42); | |
202 | EXPECT_CALL(alloc, deallocate(ptr, 42)); | |
203 | ref.deallocate(ptr, 42); | |
204 | } | |
205 | ||
206 | TEST(AllocatorTest, allocator_ref) { | |
9f95a23c TL |
207 | StrictMock<mock_allocator<int>> alloc; |
208 | typedef allocator_ref<mock_allocator<int>> test_allocator_ref; | |
11fdf7f2 TL |
209 | test_allocator_ref ref(&alloc); |
210 | // Check if allocator_ref forwards to the underlying allocator. | |
211 | check_forwarding(alloc, ref); | |
212 | test_allocator_ref ref2(ref); | |
213 | check_forwarding(alloc, ref2); | |
214 | test_allocator_ref ref3; | |
f67539c2 | 215 | EXPECT_EQ(nullptr, ref3.get()); |
11fdf7f2 TL |
216 | ref3 = ref; |
217 | check_forwarding(alloc, ref3); | |
218 | } | |
219 | ||
9f95a23c | 220 | typedef allocator_ref<std::allocator<char>> TestAllocator; |
11fdf7f2 | 221 | |
9f95a23c TL |
222 | static void check_move_buffer( |
223 | const char* str, basic_memory_buffer<char, 5, TestAllocator>& buffer) { | |
224 | std::allocator<char>* alloc = buffer.get_allocator().get(); | |
11fdf7f2 TL |
225 | basic_memory_buffer<char, 5, TestAllocator> buffer2(std::move(buffer)); |
226 | // Move shouldn't destroy the inline content of the first buffer. | |
227 | EXPECT_EQ(str, std::string(&buffer[0], buffer.size())); | |
228 | EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size())); | |
229 | EXPECT_EQ(5u, buffer2.capacity()); | |
230 | // Move should transfer allocator. | |
f67539c2 | 231 | EXPECT_EQ(nullptr, buffer.get_allocator().get()); |
11fdf7f2 TL |
232 | EXPECT_EQ(alloc, buffer2.get_allocator().get()); |
233 | } | |
234 | ||
f67539c2 | 235 | TEST(MemoryBufferTest, MoveCtorInlineBuffer) { |
11fdf7f2 TL |
236 | std::allocator<char> alloc; |
237 | basic_memory_buffer<char, 5, TestAllocator> buffer((TestAllocator(&alloc))); | |
238 | const char test[] = "test"; | |
239 | buffer.append(test, test + 4); | |
240 | check_move_buffer("test", buffer); | |
241 | // Adding one more character fills the inline buffer, but doesn't cause | |
242 | // dynamic allocation. | |
243 | buffer.push_back('a'); | |
244 | check_move_buffer("testa", buffer); | |
f67539c2 TL |
245 | } |
246 | ||
247 | TEST(MemoryBufferTest, MoveCtorDynamicBuffer) { | |
248 | std::allocator<char> alloc; | |
249 | basic_memory_buffer<char, 4, TestAllocator> buffer((TestAllocator(&alloc))); | |
250 | const char test[] = "test"; | |
251 | buffer.append(test, test + 4); | |
9f95a23c | 252 | const char* inline_buffer_ptr = &buffer[0]; |
11fdf7f2 TL |
253 | // Adding one more character causes the content to move from the inline to |
254 | // a dynamically allocated buffer. | |
f67539c2 TL |
255 | buffer.push_back('a'); |
256 | basic_memory_buffer<char, 4, TestAllocator> buffer2(std::move(buffer)); | |
11fdf7f2 TL |
257 | // Move should rip the guts of the first buffer. |
258 | EXPECT_EQ(inline_buffer_ptr, &buffer[0]); | |
f67539c2 TL |
259 | EXPECT_EQ("testa", std::string(&buffer2[0], buffer2.size())); |
260 | EXPECT_GT(buffer2.capacity(), 4u); | |
11fdf7f2 TL |
261 | } |
262 | ||
9f95a23c TL |
263 | static void check_move_assign_buffer(const char* str, |
264 | basic_memory_buffer<char, 5>& buffer) { | |
11fdf7f2 TL |
265 | basic_memory_buffer<char, 5> buffer2; |
266 | buffer2 = std::move(buffer); | |
267 | // Move shouldn't destroy the inline content of the first buffer. | |
268 | EXPECT_EQ(str, std::string(&buffer[0], buffer.size())); | |
269 | EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size())); | |
270 | EXPECT_EQ(5u, buffer2.capacity()); | |
271 | } | |
272 | ||
273 | TEST(MemoryBufferTest, MoveAssignment) { | |
274 | basic_memory_buffer<char, 5> buffer; | |
275 | const char test[] = "test"; | |
276 | buffer.append(test, test + 4); | |
277 | check_move_assign_buffer("test", buffer); | |
278 | // Adding one more character fills the inline buffer, but doesn't cause | |
279 | // dynamic allocation. | |
280 | buffer.push_back('a'); | |
281 | check_move_assign_buffer("testa", buffer); | |
9f95a23c | 282 | const char* inline_buffer_ptr = &buffer[0]; |
11fdf7f2 TL |
283 | // Adding one more character causes the content to move from the inline to |
284 | // a dynamically allocated buffer. | |
285 | buffer.push_back('b'); | |
286 | basic_memory_buffer<char, 5> buffer2; | |
287 | buffer2 = std::move(buffer); | |
288 | // Move should rip the guts of the first buffer. | |
289 | EXPECT_EQ(inline_buffer_ptr, &buffer[0]); | |
290 | EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size())); | |
291 | EXPECT_GT(buffer2.capacity(), 5u); | |
292 | } | |
293 | ||
294 | TEST(MemoryBufferTest, Grow) { | |
9f95a23c | 295 | typedef allocator_ref<mock_allocator<int>> Allocator; |
11fdf7f2 TL |
296 | typedef basic_memory_buffer<int, 10, Allocator> Base; |
297 | mock_allocator<int> alloc; | |
298 | struct TestMemoryBuffer : Base { | |
299 | TestMemoryBuffer(Allocator alloc) : Base(alloc) {} | |
f67539c2 | 300 | void grow(size_t size) { Base::grow(size); } |
11fdf7f2 TL |
301 | } buffer((Allocator(&alloc))); |
302 | buffer.resize(7); | |
f67539c2 | 303 | using fmt::detail::to_unsigned; |
9f95a23c | 304 | for (int i = 0; i < 7; ++i) buffer[to_unsigned(i)] = i * i; |
11fdf7f2 TL |
305 | EXPECT_EQ(10u, buffer.capacity()); |
306 | int mem[20]; | |
307 | mem[7] = 0xdead; | |
308 | EXPECT_CALL(alloc, allocate(20)).WillOnce(Return(mem)); | |
309 | buffer.grow(20); | |
310 | EXPECT_EQ(20u, buffer.capacity()); | |
311 | // Check if size elements have been copied | |
9f95a23c | 312 | for (int i = 0; i < 7; ++i) EXPECT_EQ(i * i, buffer[to_unsigned(i)]); |
11fdf7f2 TL |
313 | // and no more than that. |
314 | EXPECT_EQ(0xdead, buffer[7]); | |
315 | EXPECT_CALL(alloc, deallocate(mem, 20)); | |
316 | } | |
317 | ||
318 | TEST(MemoryBufferTest, Allocator) { | |
9f95a23c | 319 | typedef allocator_ref<mock_allocator<char>> TestAllocator; |
11fdf7f2 | 320 | basic_memory_buffer<char, 10, TestAllocator> buffer; |
f67539c2 | 321 | EXPECT_EQ(nullptr, buffer.get_allocator().get()); |
9f95a23c | 322 | StrictMock<mock_allocator<char>> alloc; |
11fdf7f2 TL |
323 | char mem; |
324 | { | |
9f95a23c TL |
325 | basic_memory_buffer<char, 10, TestAllocator> buffer2( |
326 | (TestAllocator(&alloc))); | |
11fdf7f2 | 327 | EXPECT_EQ(&alloc, buffer2.get_allocator().get()); |
f67539c2 | 328 | size_t size = 2 * fmt::inline_buffer_size; |
11fdf7f2 TL |
329 | EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem)); |
330 | buffer2.reserve(size); | |
331 | EXPECT_CALL(alloc, deallocate(&mem, size)); | |
332 | } | |
333 | } | |
334 | ||
335 | TEST(MemoryBufferTest, ExceptionInDeallocate) { | |
9f95a23c TL |
336 | typedef allocator_ref<mock_allocator<char>> TestAllocator; |
337 | StrictMock<mock_allocator<char>> alloc; | |
11fdf7f2 | 338 | basic_memory_buffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc))); |
f67539c2 | 339 | size_t size = 2 * fmt::inline_buffer_size; |
11fdf7f2 TL |
340 | std::vector<char> mem(size); |
341 | { | |
342 | EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0])); | |
343 | buffer.resize(size); | |
344 | std::fill(&buffer[0], &buffer[0] + size, 'x'); | |
345 | } | |
346 | std::vector<char> mem2(2 * size); | |
347 | { | |
348 | EXPECT_CALL(alloc, allocate(2 * size)).WillOnce(Return(&mem2[0])); | |
349 | std::exception e; | |
350 | EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e)); | |
351 | EXPECT_THROW(buffer.reserve(2 * size), std::exception); | |
352 | EXPECT_EQ(&mem2[0], &buffer[0]); | |
353 | // Check that the data has been copied. | |
f67539c2 | 354 | for (size_t i = 0; i < size; ++i) EXPECT_EQ('x', buffer[i]); |
11fdf7f2 TL |
355 | } |
356 | EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size)); | |
357 | } | |
358 | ||
11fdf7f2 | 359 | TEST(UtilTest, UTF8ToUTF16) { |
f67539c2 | 360 | fmt::detail::utf8_to_utf16 u("лошадка"); |
11fdf7f2 TL |
361 | EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str()); |
362 | EXPECT_EQ(7, u.size()); | |
f67539c2 TL |
363 | // U+10437 { DESERET SMALL LETTER YEE } |
364 | EXPECT_EQ(L"\xD801\xDC37", fmt::detail::utf8_to_utf16("𐐷").str()); | |
365 | EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16("\xc3\x28"), std::runtime_error, | |
366 | "invalid utf8"); | |
367 | EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16(fmt::string_view("л", 1)), | |
368 | std::runtime_error, "invalid utf8"); | |
369 | EXPECT_EQ(L"123456", fmt::detail::utf8_to_utf16("123456").str()); | |
11fdf7f2 TL |
370 | } |
371 | ||
372 | TEST(UtilTest, UTF8ToUTF16EmptyString) { | |
373 | std::string s = ""; | |
f67539c2 | 374 | fmt::detail::utf8_to_utf16 u(s.c_str()); |
11fdf7f2 TL |
375 | EXPECT_EQ(L"", u.str()); |
376 | EXPECT_EQ(s.size(), u.size()); | |
377 | } | |
378 | ||
11fdf7f2 TL |
379 | TEST(UtilTest, FormatSystemError) { |
380 | fmt::memory_buffer message; | |
381 | fmt::format_system_error(message, EDOM, "test"); | |
382 | EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), | |
383 | to_string(message)); | |
384 | message = fmt::memory_buffer(); | |
385 | ||
386 | // Check if std::allocator throws on allocating max size_t / 2 chars. | |
f67539c2 | 387 | size_t max_size = max_value<size_t>() / 2; |
11fdf7f2 TL |
388 | bool throws_on_alloc = false; |
389 | try { | |
390 | std::allocator<char> alloc; | |
391 | alloc.deallocate(alloc.allocate(max_size), max_size); | |
392 | } catch (const std::bad_alloc&) { | |
393 | throws_on_alloc = true; | |
394 | } | |
395 | if (!throws_on_alloc) { | |
396 | fmt::print("warning: std::allocator allocates {} chars", max_size); | |
397 | return; | |
398 | } | |
f67539c2 | 399 | fmt::format_system_error(message, EDOM, fmt::string_view(nullptr, max_size)); |
11fdf7f2 TL |
400 | EXPECT_EQ(fmt::format("error {}", EDOM), to_string(message)); |
401 | } | |
402 | ||
403 | TEST(UtilTest, SystemError) { | |
404 | fmt::system_error e(EDOM, "test"); | |
405 | EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), e.what()); | |
406 | EXPECT_EQ(EDOM, e.error_code()); | |
f67539c2 TL |
407 | |
408 | fmt::system_error error(0, ""); | |
409 | try { | |
410 | throw fmt::system_error(EDOM, "test {}", "error"); | |
411 | } catch (const fmt::system_error& e) { | |
412 | error = e; | |
413 | } | |
414 | fmt::memory_buffer message; | |
415 | fmt::format_system_error(message, EDOM, "test error"); | |
416 | EXPECT_EQ(to_string(message), error.what()); | |
417 | EXPECT_EQ(EDOM, error.error_code()); | |
11fdf7f2 TL |
418 | } |
419 | ||
420 | TEST(UtilTest, ReportSystemError) { | |
421 | fmt::memory_buffer out; | |
422 | fmt::format_system_error(out, EDOM, "test error"); | |
423 | out.push_back('\n'); | |
424 | EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"), | |
425 | to_string(out)); | |
426 | } | |
427 | ||
11fdf7f2 TL |
428 | TEST(StringViewTest, Ctor) { |
429 | EXPECT_STREQ("abc", string_view("abc").data()); | |
430 | EXPECT_EQ(3u, string_view("abc").size()); | |
431 | ||
432 | EXPECT_STREQ("defg", string_view(std::string("defg")).data()); | |
433 | EXPECT_EQ(4u, string_view(std::string("defg")).size()); | |
434 | } | |
435 | ||
11fdf7f2 TL |
436 | TEST(FormatToTest, FormatWithoutArgs) { |
437 | std::string s; | |
438 | fmt::format_to(std::back_inserter(s), "test"); | |
439 | EXPECT_EQ("test", s); | |
440 | } | |
441 | ||
442 | TEST(FormatToTest, Format) { | |
443 | std::string s; | |
444 | fmt::format_to(std::back_inserter(s), "part{0}", 1); | |
445 | EXPECT_EQ("part1", s); | |
446 | fmt::format_to(std::back_inserter(s), "part{0}", 2); | |
447 | EXPECT_EQ("part1part2", s); | |
448 | } | |
449 | ||
eafe8130 TL |
450 | TEST(FormatToTest, WideString) { |
451 | std::vector<wchar_t> buf; | |
452 | fmt::format_to(std::back_inserter(buf), L"{}{}", 42, L'\0'); | |
453 | EXPECT_STREQ(buf.data(), L"42"); | |
454 | } | |
455 | ||
11fdf7f2 TL |
456 | TEST(FormatToTest, FormatToMemoryBuffer) { |
457 | fmt::basic_memory_buffer<char, 100> buffer; | |
458 | fmt::format_to(buffer, "{}", "foo"); | |
459 | EXPECT_EQ("foo", to_string(buffer)); | |
460 | fmt::wmemory_buffer wbuffer; | |
461 | fmt::format_to(wbuffer, L"{}", L"foo"); | |
462 | EXPECT_EQ(L"foo", to_string(wbuffer)); | |
463 | } | |
464 | ||
465 | TEST(FormatterTest, Escape) { | |
466 | EXPECT_EQ("{", format("{{")); | |
467 | EXPECT_EQ("before {", format("before {{")); | |
468 | EXPECT_EQ("{ after", format("{{ after")); | |
469 | EXPECT_EQ("before { after", format("before {{ after")); | |
470 | ||
471 | EXPECT_EQ("}", format("}}")); | |
472 | EXPECT_EQ("before }", format("before }}")); | |
473 | EXPECT_EQ("} after", format("}} after")); | |
474 | EXPECT_EQ("before } after", format("before }} after")); | |
475 | ||
476 | EXPECT_EQ("{}", format("{{}}")); | |
477 | EXPECT_EQ("{42}", format("{{{0}}}", 42)); | |
478 | } | |
479 | ||
480 | TEST(FormatterTest, UnmatchedBraces) { | |
481 | EXPECT_THROW_MSG(format("{"), format_error, "invalid format string"); | |
482 | EXPECT_THROW_MSG(format("}"), format_error, "unmatched '}' in format string"); | |
483 | EXPECT_THROW_MSG(format("{0{}"), format_error, "invalid format string"); | |
484 | } | |
485 | ||
9f95a23c | 486 | TEST(FormatterTest, NoArgs) { EXPECT_EQ("test", format("test")); } |
11fdf7f2 TL |
487 | |
488 | TEST(FormatterTest, ArgsInDifferentPositions) { | |
489 | EXPECT_EQ("42", format("{0}", 42)); | |
490 | EXPECT_EQ("before 42", format("before {0}", 42)); | |
491 | EXPECT_EQ("42 after", format("{0} after", 42)); | |
492 | EXPECT_EQ("before 42 after", format("before {0} after", 42)); | |
493 | EXPECT_EQ("answer = 42", format("{0} = {1}", "answer", 42)); | |
494 | EXPECT_EQ("42 is the answer", format("{1} is the {0}", "answer", 42)); | |
495 | EXPECT_EQ("abracadabra", format("{0}{1}{0}", "abra", "cad")); | |
496 | } | |
497 | ||
498 | TEST(FormatterTest, ArgErrors) { | |
499 | EXPECT_THROW_MSG(format("{"), format_error, "invalid format string"); | |
500 | EXPECT_THROW_MSG(format("{?}"), format_error, "invalid format string"); | |
501 | EXPECT_THROW_MSG(format("{0"), format_error, "invalid format string"); | |
f67539c2 | 502 | EXPECT_THROW_MSG(format("{0}"), format_error, "argument not found"); |
eafe8130 | 503 | EXPECT_THROW_MSG(format("{00}", 42), format_error, "invalid format string"); |
11fdf7f2 TL |
504 | |
505 | char format_str[BUFFER_SIZE]; | |
506 | safe_sprintf(format_str, "{%u", INT_MAX); | |
507 | EXPECT_THROW_MSG(format(format_str), format_error, "invalid format string"); | |
508 | safe_sprintf(format_str, "{%u}", INT_MAX); | |
f67539c2 | 509 | EXPECT_THROW_MSG(format(format_str), format_error, "argument not found"); |
11fdf7f2 TL |
510 | |
511 | safe_sprintf(format_str, "{%u", INT_MAX + 1u); | |
512 | EXPECT_THROW_MSG(format(format_str), format_error, "number is too big"); | |
513 | safe_sprintf(format_str, "{%u}", INT_MAX + 1u); | |
514 | EXPECT_THROW_MSG(format(format_str), format_error, "number is too big"); | |
515 | } | |
516 | ||
9f95a23c | 517 | template <int N> struct TestFormat { |
11fdf7f2 | 518 | template <typename... Args> |
9f95a23c | 519 | static std::string format(fmt::string_view format_str, const Args&... args) { |
11fdf7f2 TL |
520 | return TestFormat<N - 1>::format(format_str, N - 1, args...); |
521 | } | |
522 | }; | |
523 | ||
9f95a23c | 524 | template <> struct TestFormat<0> { |
11fdf7f2 | 525 | template <typename... Args> |
9f95a23c | 526 | static std::string format(fmt::string_view format_str, const Args&... args) { |
11fdf7f2 TL |
527 | return fmt::format(format_str, args...); |
528 | } | |
529 | }; | |
530 | ||
531 | TEST(FormatterTest, ManyArgs) { | |
532 | EXPECT_EQ("19", TestFormat<20>::format("{19}")); | |
9f95a23c | 533 | EXPECT_THROW_MSG(TestFormat<20>::format("{20}"), format_error, |
f67539c2 | 534 | "argument not found"); |
9f95a23c | 535 | EXPECT_THROW_MSG(TestFormat<21>::format("{21}"), format_error, |
f67539c2 TL |
536 | "argument not found"); |
537 | enum { max_packed_args = fmt::detail::max_packed_args }; | |
11fdf7f2 TL |
538 | std::string format_str = fmt::format("{{{}}}", max_packed_args + 1); |
539 | EXPECT_THROW_MSG(TestFormat<max_packed_args>::format(format_str), | |
f67539c2 | 540 | format_error, "argument not found"); |
11fdf7f2 TL |
541 | } |
542 | ||
543 | TEST(FormatterTest, NamedArg) { | |
544 | EXPECT_EQ("1/a/A", format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'), | |
545 | fmt::arg("A_", "A"), fmt::arg("_1", 1))); | |
546 | EXPECT_THROW_MSG(format("{a}"), format_error, "argument not found"); | |
547 | EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4))); | |
548 | EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2))); | |
549 | EXPECT_EQ("1 2", format("{} {two}", 1, fmt::arg("two", 2))); | |
9f95a23c TL |
550 | EXPECT_EQ("42", format("{c}", fmt::arg("a", 0), fmt::arg("b", 0), |
551 | fmt::arg("c", 42), fmt::arg("d", 0), fmt::arg("e", 0), | |
552 | fmt::arg("f", 0), fmt::arg("g", 0), fmt::arg("h", 0), | |
553 | fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0), | |
554 | fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0), | |
555 | fmt::arg("o", 0), fmt::arg("p", 0))); | |
11fdf7f2 TL |
556 | } |
557 | ||
558 | TEST(FormatterTest, AutoArgIndex) { | |
559 | EXPECT_EQ("abc", format("{}{}{}", 'a', 'b', 'c')); | |
9f95a23c TL |
560 | EXPECT_THROW_MSG(format("{0}{}", 'a', 'b'), format_error, |
561 | "cannot switch from manual to automatic argument indexing"); | |
562 | EXPECT_THROW_MSG(format("{}{0}", 'a', 'b'), format_error, | |
563 | "cannot switch from automatic to manual argument indexing"); | |
11fdf7f2 | 564 | EXPECT_EQ("1.2", format("{:.{}}", 1.2345, 2)); |
9f95a23c TL |
565 | EXPECT_THROW_MSG(format("{0}:.{}", 1.2345, 2), format_error, |
566 | "cannot switch from manual to automatic argument indexing"); | |
567 | EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2), format_error, | |
568 | "cannot switch from automatic to manual argument indexing"); | |
f67539c2 | 569 | EXPECT_THROW_MSG(format("{}"), format_error, "argument not found"); |
11fdf7f2 TL |
570 | } |
571 | ||
9f95a23c | 572 | TEST(FormatterTest, EmptySpecs) { EXPECT_EQ("42", format("{0:}", 42)); } |
11fdf7f2 TL |
573 | |
574 | TEST(FormatterTest, LeftAlign) { | |
575 | EXPECT_EQ("42 ", format("{0:<4}", 42)); | |
576 | EXPECT_EQ("42 ", format("{0:<4o}", 042)); | |
577 | EXPECT_EQ("42 ", format("{0:<4x}", 0x42)); | |
578 | EXPECT_EQ("-42 ", format("{0:<5}", -42)); | |
579 | EXPECT_EQ("42 ", format("{0:<5}", 42u)); | |
580 | EXPECT_EQ("-42 ", format("{0:<5}", -42l)); | |
581 | EXPECT_EQ("42 ", format("{0:<5}", 42ul)); | |
582 | EXPECT_EQ("-42 ", format("{0:<5}", -42ll)); | |
583 | EXPECT_EQ("42 ", format("{0:<5}", 42ull)); | |
9f95a23c TL |
584 | EXPECT_EQ("-42.0 ", format("{0:<7}", -42.0)); |
585 | EXPECT_EQ("-42.0 ", format("{0:<7}", -42.0l)); | |
11fdf7f2 TL |
586 | EXPECT_EQ("c ", format("{0:<5}", 'c')); |
587 | EXPECT_EQ("abc ", format("{0:<5}", "abc")); | |
588 | EXPECT_EQ("0xface ", format("{0:<8}", reinterpret_cast<void*>(0xface))); | |
589 | } | |
590 | ||
591 | TEST(FormatterTest, RightAlign) { | |
592 | EXPECT_EQ(" 42", format("{0:>4}", 42)); | |
593 | EXPECT_EQ(" 42", format("{0:>4o}", 042)); | |
594 | EXPECT_EQ(" 42", format("{0:>4x}", 0x42)); | |
595 | EXPECT_EQ(" -42", format("{0:>5}", -42)); | |
596 | EXPECT_EQ(" 42", format("{0:>5}", 42u)); | |
597 | EXPECT_EQ(" -42", format("{0:>5}", -42l)); | |
598 | EXPECT_EQ(" 42", format("{0:>5}", 42ul)); | |
599 | EXPECT_EQ(" -42", format("{0:>5}", -42ll)); | |
600 | EXPECT_EQ(" 42", format("{0:>5}", 42ull)); | |
9f95a23c TL |
601 | EXPECT_EQ(" -42.0", format("{0:>7}", -42.0)); |
602 | EXPECT_EQ(" -42.0", format("{0:>7}", -42.0l)); | |
11fdf7f2 TL |
603 | EXPECT_EQ(" c", format("{0:>5}", 'c')); |
604 | EXPECT_EQ(" abc", format("{0:>5}", "abc")); | |
605 | EXPECT_EQ(" 0xface", format("{0:>8}", reinterpret_cast<void*>(0xface))); | |
606 | } | |
607 | ||
f67539c2 TL |
608 | #if FMT_NUMERIC_ALIGN |
609 | TEST(FormatterTest, NumericAlign) { EXPECT_EQ("0042", format("{0:=4}", 42)); } | |
610 | #endif | |
11fdf7f2 TL |
611 | |
612 | TEST(FormatterTest, CenterAlign) { | |
613 | EXPECT_EQ(" 42 ", format("{0:^5}", 42)); | |
614 | EXPECT_EQ(" 42 ", format("{0:^5o}", 042)); | |
615 | EXPECT_EQ(" 42 ", format("{0:^5x}", 0x42)); | |
616 | EXPECT_EQ(" -42 ", format("{0:^5}", -42)); | |
617 | EXPECT_EQ(" 42 ", format("{0:^5}", 42u)); | |
618 | EXPECT_EQ(" -42 ", format("{0:^5}", -42l)); | |
619 | EXPECT_EQ(" 42 ", format("{0:^5}", 42ul)); | |
620 | EXPECT_EQ(" -42 ", format("{0:^5}", -42ll)); | |
621 | EXPECT_EQ(" 42 ", format("{0:^5}", 42ull)); | |
9f95a23c TL |
622 | EXPECT_EQ(" -42.0 ", format("{0:^7}", -42.0)); |
623 | EXPECT_EQ(" -42.0 ", format("{0:^7}", -42.0l)); | |
11fdf7f2 TL |
624 | EXPECT_EQ(" c ", format("{0:^5}", 'c')); |
625 | EXPECT_EQ(" abc ", format("{0:^6}", "abc")); | |
626 | EXPECT_EQ(" 0xface ", format("{0:^8}", reinterpret_cast<void*>(0xface))); | |
627 | } | |
628 | ||
629 | TEST(FormatterTest, Fill) { | |
9f95a23c TL |
630 | EXPECT_THROW_MSG(format("{0:{<5}", 'c'), format_error, |
631 | "invalid fill character '{'"); | |
632 | EXPECT_THROW_MSG(format("{0:{<5}}", 'c'), format_error, | |
633 | "invalid fill character '{'"); | |
11fdf7f2 TL |
634 | EXPECT_EQ("**42", format("{0:*>4}", 42)); |
635 | EXPECT_EQ("**-42", format("{0:*>5}", -42)); | |
636 | EXPECT_EQ("***42", format("{0:*>5}", 42u)); | |
637 | EXPECT_EQ("**-42", format("{0:*>5}", -42l)); | |
638 | EXPECT_EQ("***42", format("{0:*>5}", 42ul)); | |
639 | EXPECT_EQ("**-42", format("{0:*>5}", -42ll)); | |
640 | EXPECT_EQ("***42", format("{0:*>5}", 42ull)); | |
9f95a23c TL |
641 | EXPECT_EQ("**-42.0", format("{0:*>7}", -42.0)); |
642 | EXPECT_EQ("**-42.0", format("{0:*>7}", -42.0l)); | |
11fdf7f2 TL |
643 | EXPECT_EQ("c****", format("{0:*<5}", 'c')); |
644 | EXPECT_EQ("abc**", format("{0:*<5}", "abc")); | |
645 | EXPECT_EQ("**0xface", format("{0:*>8}", reinterpret_cast<void*>(0xface))); | |
646 | EXPECT_EQ("foo=", format("{:}=", "foo")); | |
9f95a23c | 647 | EXPECT_EQ(std::string("\0\0\0*", 4), format(string_view("{:\0>4}", 6), '*')); |
f67539c2 TL |
648 | EXPECT_EQ("жж42", format("{0:ж>4}", 42)); |
649 | EXPECT_THROW_MSG(format("{:\x80\x80\x80\x80\x80>}", 0), format_error, | |
650 | "invalid fill"); | |
11fdf7f2 TL |
651 | } |
652 | ||
653 | TEST(FormatterTest, PlusSign) { | |
654 | EXPECT_EQ("+42", format("{0:+}", 42)); | |
655 | EXPECT_EQ("-42", format("{0:+}", -42)); | |
656 | EXPECT_EQ("+42", format("{0:+}", 42)); | |
9f95a23c TL |
657 | EXPECT_THROW_MSG(format("{0:+}", 42u), format_error, |
658 | "format specifier requires signed argument"); | |
11fdf7f2 | 659 | EXPECT_EQ("+42", format("{0:+}", 42l)); |
9f95a23c TL |
660 | EXPECT_THROW_MSG(format("{0:+}", 42ul), format_error, |
661 | "format specifier requires signed argument"); | |
11fdf7f2 | 662 | EXPECT_EQ("+42", format("{0:+}", 42ll)); |
9f95a23c TL |
663 | EXPECT_THROW_MSG(format("{0:+}", 42ull), format_error, |
664 | "format specifier requires signed argument"); | |
665 | EXPECT_EQ("+42.0", format("{0:+}", 42.0)); | |
666 | EXPECT_EQ("+42.0", format("{0:+}", 42.0l)); | |
667 | EXPECT_THROW_MSG(format("{0:+", 'c'), format_error, | |
668 | "missing '}' in format string"); | |
669 | EXPECT_THROW_MSG(format("{0:+}", 'c'), format_error, | |
670 | "invalid format specifier for char"); | |
671 | EXPECT_THROW_MSG(format("{0:+}", "abc"), format_error, | |
672 | "format specifier requires numeric argument"); | |
673 | EXPECT_THROW_MSG(format("{0:+}", reinterpret_cast<void*>(0x42)), format_error, | |
674 | "format specifier requires numeric argument"); | |
11fdf7f2 TL |
675 | } |
676 | ||
677 | TEST(FormatterTest, MinusSign) { | |
678 | EXPECT_EQ("42", format("{0:-}", 42)); | |
679 | EXPECT_EQ("-42", format("{0:-}", -42)); | |
680 | EXPECT_EQ("42", format("{0:-}", 42)); | |
9f95a23c TL |
681 | EXPECT_THROW_MSG(format("{0:-}", 42u), format_error, |
682 | "format specifier requires signed argument"); | |
11fdf7f2 | 683 | EXPECT_EQ("42", format("{0:-}", 42l)); |
9f95a23c TL |
684 | EXPECT_THROW_MSG(format("{0:-}", 42ul), format_error, |
685 | "format specifier requires signed argument"); | |
11fdf7f2 | 686 | EXPECT_EQ("42", format("{0:-}", 42ll)); |
9f95a23c TL |
687 | EXPECT_THROW_MSG(format("{0:-}", 42ull), format_error, |
688 | "format specifier requires signed argument"); | |
689 | EXPECT_EQ("42.0", format("{0:-}", 42.0)); | |
690 | EXPECT_EQ("42.0", format("{0:-}", 42.0l)); | |
691 | EXPECT_THROW_MSG(format("{0:-", 'c'), format_error, | |
692 | "missing '}' in format string"); | |
693 | EXPECT_THROW_MSG(format("{0:-}", 'c'), format_error, | |
694 | "invalid format specifier for char"); | |
695 | EXPECT_THROW_MSG(format("{0:-}", "abc"), format_error, | |
696 | "format specifier requires numeric argument"); | |
697 | EXPECT_THROW_MSG(format("{0:-}", reinterpret_cast<void*>(0x42)), format_error, | |
698 | "format specifier requires numeric argument"); | |
11fdf7f2 TL |
699 | } |
700 | ||
701 | TEST(FormatterTest, SpaceSign) { | |
702 | EXPECT_EQ(" 42", format("{0: }", 42)); | |
703 | EXPECT_EQ("-42", format("{0: }", -42)); | |
704 | EXPECT_EQ(" 42", format("{0: }", 42)); | |
9f95a23c TL |
705 | EXPECT_THROW_MSG(format("{0: }", 42u), format_error, |
706 | "format specifier requires signed argument"); | |
11fdf7f2 | 707 | EXPECT_EQ(" 42", format("{0: }", 42l)); |
9f95a23c TL |
708 | EXPECT_THROW_MSG(format("{0: }", 42ul), format_error, |
709 | "format specifier requires signed argument"); | |
11fdf7f2 | 710 | EXPECT_EQ(" 42", format("{0: }", 42ll)); |
9f95a23c TL |
711 | EXPECT_THROW_MSG(format("{0: }", 42ull), format_error, |
712 | "format specifier requires signed argument"); | |
713 | EXPECT_EQ(" 42.0", format("{0: }", 42.0)); | |
714 | EXPECT_EQ(" 42.0", format("{0: }", 42.0l)); | |
715 | EXPECT_THROW_MSG(format("{0: ", 'c'), format_error, | |
716 | "missing '}' in format string"); | |
717 | EXPECT_THROW_MSG(format("{0: }", 'c'), format_error, | |
718 | "invalid format specifier for char"); | |
719 | EXPECT_THROW_MSG(format("{0: }", "abc"), format_error, | |
720 | "format specifier requires numeric argument"); | |
721 | EXPECT_THROW_MSG(format("{0: }", reinterpret_cast<void*>(0x42)), format_error, | |
722 | "format specifier requires numeric argument"); | |
11fdf7f2 TL |
723 | } |
724 | ||
725 | TEST(FormatterTest, HashFlag) { | |
726 | EXPECT_EQ("42", format("{0:#}", 42)); | |
727 | EXPECT_EQ("-42", format("{0:#}", -42)); | |
728 | EXPECT_EQ("0b101010", format("{0:#b}", 42)); | |
729 | EXPECT_EQ("0B101010", format("{0:#B}", 42)); | |
730 | EXPECT_EQ("-0b101010", format("{0:#b}", -42)); | |
731 | EXPECT_EQ("0x42", format("{0:#x}", 0x42)); | |
732 | EXPECT_EQ("0X42", format("{0:#X}", 0x42)); | |
733 | EXPECT_EQ("-0x42", format("{0:#x}", -0x42)); | |
f67539c2 | 734 | EXPECT_EQ("0", format("{0:#o}", 0)); |
11fdf7f2 TL |
735 | EXPECT_EQ("042", format("{0:#o}", 042)); |
736 | EXPECT_EQ("-042", format("{0:#o}", -042)); | |
737 | EXPECT_EQ("42", format("{0:#}", 42u)); | |
738 | EXPECT_EQ("0x42", format("{0:#x}", 0x42u)); | |
739 | EXPECT_EQ("042", format("{0:#o}", 042u)); | |
740 | ||
741 | EXPECT_EQ("-42", format("{0:#}", -42l)); | |
742 | EXPECT_EQ("0x42", format("{0:#x}", 0x42l)); | |
743 | EXPECT_EQ("-0x42", format("{0:#x}", -0x42l)); | |
744 | EXPECT_EQ("042", format("{0:#o}", 042l)); | |
745 | EXPECT_EQ("-042", format("{0:#o}", -042l)); | |
746 | EXPECT_EQ("42", format("{0:#}", 42ul)); | |
747 | EXPECT_EQ("0x42", format("{0:#x}", 0x42ul)); | |
748 | EXPECT_EQ("042", format("{0:#o}", 042ul)); | |
749 | ||
750 | EXPECT_EQ("-42", format("{0:#}", -42ll)); | |
751 | EXPECT_EQ("0x42", format("{0:#x}", 0x42ll)); | |
752 | EXPECT_EQ("-0x42", format("{0:#x}", -0x42ll)); | |
753 | EXPECT_EQ("042", format("{0:#o}", 042ll)); | |
754 | EXPECT_EQ("-042", format("{0:#o}", -042ll)); | |
755 | EXPECT_EQ("42", format("{0:#}", 42ull)); | |
756 | EXPECT_EQ("0x42", format("{0:#x}", 0x42ull)); | |
757 | EXPECT_EQ("042", format("{0:#o}", 042ull)); | |
758 | ||
9f95a23c TL |
759 | EXPECT_EQ("-42.0", format("{0:#}", -42.0)); |
760 | EXPECT_EQ("-42.0", format("{0:#}", -42.0l)); | |
f67539c2 TL |
761 | EXPECT_EQ("4.e+01", format("{:#.0e}", 42.0)); |
762 | EXPECT_EQ("0.", format("{:#.0f}", 0.01)); | |
763 | auto s = format("{:#.0f}", 0.5); // MSVC's printf uses wrong rounding mode. | |
764 | EXPECT_TRUE(s == "0." || s == "1."); | |
9f95a23c TL |
765 | EXPECT_THROW_MSG(format("{0:#", 'c'), format_error, |
766 | "missing '}' in format string"); | |
767 | EXPECT_THROW_MSG(format("{0:#}", 'c'), format_error, | |
768 | "invalid format specifier for char"); | |
769 | EXPECT_THROW_MSG(format("{0:#}", "abc"), format_error, | |
770 | "format specifier requires numeric argument"); | |
771 | EXPECT_THROW_MSG(format("{0:#}", reinterpret_cast<void*>(0x42)), format_error, | |
772 | "format specifier requires numeric argument"); | |
11fdf7f2 TL |
773 | } |
774 | ||
775 | TEST(FormatterTest, ZeroFlag) { | |
776 | EXPECT_EQ("42", format("{0:0}", 42)); | |
777 | EXPECT_EQ("-0042", format("{0:05}", -42)); | |
778 | EXPECT_EQ("00042", format("{0:05}", 42u)); | |
779 | EXPECT_EQ("-0042", format("{0:05}", -42l)); | |
780 | EXPECT_EQ("00042", format("{0:05}", 42ul)); | |
781 | EXPECT_EQ("-0042", format("{0:05}", -42ll)); | |
782 | EXPECT_EQ("00042", format("{0:05}", 42ull)); | |
9f95a23c TL |
783 | EXPECT_EQ("-0042.0", format("{0:07}", -42.0)); |
784 | EXPECT_EQ("-0042.0", format("{0:07}", -42.0l)); | |
785 | EXPECT_THROW_MSG(format("{0:0", 'c'), format_error, | |
786 | "missing '}' in format string"); | |
787 | EXPECT_THROW_MSG(format("{0:05}", 'c'), format_error, | |
788 | "invalid format specifier for char"); | |
789 | EXPECT_THROW_MSG(format("{0:05}", "abc"), format_error, | |
790 | "format specifier requires numeric argument"); | |
11fdf7f2 | 791 | EXPECT_THROW_MSG(format("{0:05}", reinterpret_cast<void*>(0x42)), |
9f95a23c | 792 | format_error, "format specifier requires numeric argument"); |
11fdf7f2 TL |
793 | } |
794 | ||
795 | TEST(FormatterTest, Width) { | |
796 | char format_str[BUFFER_SIZE]; | |
797 | safe_sprintf(format_str, "{0:%u", UINT_MAX); | |
798 | increment(format_str + 3); | |
799 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
f67539c2 | 800 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
801 | format_str[size] = '}'; |
802 | format_str[size + 1] = 0; | |
803 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
804 | ||
805 | safe_sprintf(format_str, "{0:%u", INT_MAX + 1u); | |
806 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
807 | safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u); | |
808 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
809 | EXPECT_EQ(" -42", format("{0:4}", -42)); | |
810 | EXPECT_EQ(" 42", format("{0:5}", 42u)); | |
811 | EXPECT_EQ(" -42", format("{0:6}", -42l)); | |
812 | EXPECT_EQ(" 42", format("{0:7}", 42ul)); | |
813 | EXPECT_EQ(" -42", format("{0:6}", -42ll)); | |
814 | EXPECT_EQ(" 42", format("{0:7}", 42ull)); | |
815 | EXPECT_EQ(" -1.23", format("{0:8}", -1.23)); | |
816 | EXPECT_EQ(" -1.23", format("{0:9}", -1.23l)); | |
817 | EXPECT_EQ(" 0xcafe", format("{0:10}", reinterpret_cast<void*>(0xcafe))); | |
818 | EXPECT_EQ("x ", format("{0:11}", 'x')); | |
819 | EXPECT_EQ("str ", format("{0:12}", "str")); | |
f67539c2 | 820 | EXPECT_EQ(fmt::format("{:*^5}", "🤡"), "**🤡**"); |
11fdf7f2 | 821 | } |
f67539c2 | 822 | |
9f95a23c | 823 | template <typename T> inline T const_check(T value) { return value; } |
11fdf7f2 TL |
824 | |
825 | TEST(FormatterTest, RuntimeWidth) { | |
826 | char format_str[BUFFER_SIZE]; | |
827 | safe_sprintf(format_str, "{0:{%u", UINT_MAX); | |
828 | increment(format_str + 4); | |
829 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
f67539c2 | 830 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
831 | format_str[size] = '}'; |
832 | format_str[size + 1] = 0; | |
833 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
834 | format_str[size + 1] = '}'; | |
835 | format_str[size + 2] = 0; | |
836 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
837 | ||
9f95a23c TL |
838 | EXPECT_THROW_MSG(format("{0:{", 0), format_error, "invalid format string"); |
839 | EXPECT_THROW_MSG(format("{0:{}", 0), format_error, | |
840 | "cannot switch from manual to automatic argument indexing"); | |
841 | EXPECT_THROW_MSG(format("{0:{?}}", 0), format_error, "invalid format string"); | |
f67539c2 | 842 | EXPECT_THROW_MSG(format("{0:{1}}", 0), format_error, "argument not found"); |
9f95a23c TL |
843 | |
844 | EXPECT_THROW_MSG(format("{0:{0:}}", 0), format_error, | |
845 | "invalid format string"); | |
846 | ||
847 | EXPECT_THROW_MSG(format("{0:{1}}", 0, -1), format_error, "negative width"); | |
848 | EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1u)), format_error, | |
849 | "number is too big"); | |
850 | EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l), format_error, "negative width"); | |
851 | if (const_check(sizeof(long) > sizeof(int))) { | |
11fdf7f2 | 852 | long value = INT_MAX; |
9f95a23c TL |
853 | EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)), format_error, |
854 | "number is too big"); | |
11fdf7f2 | 855 | } |
9f95a23c TL |
856 | EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1ul)), format_error, |
857 | "number is too big"); | |
11fdf7f2 | 858 | |
9f95a23c TL |
859 | EXPECT_THROW_MSG(format("{0:{1}}", 0, '0'), format_error, |
860 | "width is not integer"); | |
861 | EXPECT_THROW_MSG(format("{0:{1}}", 0, 0.0), format_error, | |
862 | "width is not integer"); | |
11fdf7f2 TL |
863 | |
864 | EXPECT_EQ(" -42", format("{0:{1}}", -42, 4)); | |
865 | EXPECT_EQ(" 42", format("{0:{1}}", 42u, 5)); | |
866 | EXPECT_EQ(" -42", format("{0:{1}}", -42l, 6)); | |
867 | EXPECT_EQ(" 42", format("{0:{1}}", 42ul, 7)); | |
868 | EXPECT_EQ(" -42", format("{0:{1}}", -42ll, 6)); | |
869 | EXPECT_EQ(" 42", format("{0:{1}}", 42ull, 7)); | |
870 | EXPECT_EQ(" -1.23", format("{0:{1}}", -1.23, 8)); | |
871 | EXPECT_EQ(" -1.23", format("{0:{1}}", -1.23l, 9)); | |
872 | EXPECT_EQ(" 0xcafe", | |
873 | format("{0:{1}}", reinterpret_cast<void*>(0xcafe), 10)); | |
874 | EXPECT_EQ("x ", format("{0:{1}}", 'x', 11)); | |
875 | EXPECT_EQ("str ", format("{0:{1}}", "str", 12)); | |
876 | } | |
877 | ||
878 | TEST(FormatterTest, Precision) { | |
879 | char format_str[BUFFER_SIZE]; | |
880 | safe_sprintf(format_str, "{0:.%u", UINT_MAX); | |
881 | increment(format_str + 4); | |
882 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
f67539c2 | 883 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
884 | format_str[size] = '}'; |
885 | format_str[size + 1] = 0; | |
886 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
887 | ||
888 | safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u); | |
889 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
890 | safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u); | |
891 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
892 | ||
9f95a23c TL |
893 | EXPECT_THROW_MSG(format("{0:.", 0), format_error, |
894 | "missing precision specifier"); | |
895 | EXPECT_THROW_MSG(format("{0:.}", 0), format_error, | |
896 | "missing precision specifier"); | |
897 | ||
898 | EXPECT_THROW_MSG(format("{0:.2", 0), format_error, | |
899 | "precision not allowed for this argument type"); | |
900 | EXPECT_THROW_MSG(format("{0:.2}", 42), format_error, | |
901 | "precision not allowed for this argument type"); | |
902 | EXPECT_THROW_MSG(format("{0:.2f}", 42), format_error, | |
903 | "precision not allowed for this argument type"); | |
904 | EXPECT_THROW_MSG(format("{0:.2}", 42u), format_error, | |
905 | "precision not allowed for this argument type"); | |
906 | EXPECT_THROW_MSG(format("{0:.2f}", 42u), format_error, | |
907 | "precision not allowed for this argument type"); | |
908 | EXPECT_THROW_MSG(format("{0:.2}", 42l), format_error, | |
909 | "precision not allowed for this argument type"); | |
910 | EXPECT_THROW_MSG(format("{0:.2f}", 42l), format_error, | |
911 | "precision not allowed for this argument type"); | |
912 | EXPECT_THROW_MSG(format("{0:.2}", 42ul), format_error, | |
913 | "precision not allowed for this argument type"); | |
914 | EXPECT_THROW_MSG(format("{0:.2f}", 42ul), format_error, | |
915 | "precision not allowed for this argument type"); | |
916 | EXPECT_THROW_MSG(format("{0:.2}", 42ll), format_error, | |
917 | "precision not allowed for this argument type"); | |
918 | EXPECT_THROW_MSG(format("{0:.2f}", 42ll), format_error, | |
919 | "precision not allowed for this argument type"); | |
920 | EXPECT_THROW_MSG(format("{0:.2}", 42ull), format_error, | |
921 | "precision not allowed for this argument type"); | |
922 | EXPECT_THROW_MSG(format("{0:.2f}", 42ull), format_error, | |
923 | "precision not allowed for this argument type"); | |
9f95a23c TL |
924 | EXPECT_THROW_MSG(format("{0:3.0}", 'x'), format_error, |
925 | "precision not allowed for this argument type"); | |
11fdf7f2 TL |
926 | EXPECT_EQ("1.2", format("{0:.2}", 1.2345)); |
927 | EXPECT_EQ("1.2", format("{0:.2}", 1.2345l)); | |
f67539c2 TL |
928 | EXPECT_EQ("1.2e+56", format("{:.2}", 1.234e56)); |
929 | EXPECT_EQ("1e+00", format("{:.0e}", 1.0L)); | |
930 | EXPECT_EQ(" 0.0e+00", format("{:9.1e}", 0.0)); | |
931 | EXPECT_EQ( | |
932 | "4.9406564584124654417656879286822137236505980261432476442558568250067550" | |
933 | "727020875186529983636163599237979656469544571773092665671035593979639877" | |
934 | "479601078187812630071319031140452784581716784898210368871863605699873072" | |
935 | "305000638740915356498438731247339727316961514003171538539807412623856559" | |
936 | "117102665855668676818703956031062493194527159149245532930545654440112748" | |
937 | "012970999954193198940908041656332452475714786901472678015935523861155013" | |
938 | "480352649347201937902681071074917033322268447533357208324319361e-324", | |
939 | format("{:.494}", 4.9406564584124654E-324)); | |
940 | EXPECT_EQ( | |
941 | "-0X1.41FE3FFE71C9E000000000000000000000000000000000000000000000000000000" | |
942 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
943 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
944 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
945 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
946 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
947 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
948 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
949 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
950 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
951 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
952 | "000000000000000000000000000000000000000000000000000P+127", | |
953 | format("{:.838A}", -2.14001164E+38)); | |
954 | EXPECT_EQ("123.", format("{:#.0f}", 123.0)); | |
955 | EXPECT_EQ("1.23", format("{:.02f}", 1.234)); | |
956 | EXPECT_EQ("0.001", format("{:.1g}", 0.001)); | |
11fdf7f2 TL |
957 | |
958 | EXPECT_THROW_MSG(format("{0:.2}", reinterpret_cast<void*>(0xcafe)), | |
9f95a23c TL |
959 | format_error, |
960 | "precision not allowed for this argument type"); | |
11fdf7f2 | 961 | EXPECT_THROW_MSG(format("{0:.2f}", reinterpret_cast<void*>(0xcafe)), |
9f95a23c TL |
962 | format_error, |
963 | "precision not allowed for this argument type"); | |
f67539c2 TL |
964 | EXPECT_THROW_MSG(format("{:.{}e}", 42.0, fmt::detail::max_value<int>()), |
965 | format_error, "number is too big"); | |
11fdf7f2 TL |
966 | |
967 | EXPECT_EQ("st", format("{0:.2}", "str")); | |
968 | } | |
969 | ||
970 | TEST(FormatterTest, RuntimePrecision) { | |
971 | char format_str[BUFFER_SIZE]; | |
972 | safe_sprintf(format_str, "{0:.{%u", UINT_MAX); | |
973 | increment(format_str + 5); | |
974 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
f67539c2 | 975 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
976 | format_str[size] = '}'; |
977 | format_str[size + 1] = 0; | |
978 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
979 | format_str[size + 1] = '}'; | |
980 | format_str[size + 2] = 0; | |
981 | EXPECT_THROW_MSG(format(format_str, 0), format_error, "number is too big"); | |
982 | ||
9f95a23c TL |
983 | EXPECT_THROW_MSG(format("{0:.{", 0), format_error, "invalid format string"); |
984 | EXPECT_THROW_MSG(format("{0:.{}", 0), format_error, | |
985 | "cannot switch from manual to automatic argument indexing"); | |
986 | EXPECT_THROW_MSG(format("{0:.{?}}", 0), format_error, | |
987 | "invalid format string"); | |
988 | EXPECT_THROW_MSG(format("{0:.{1}", 0, 0), format_error, | |
989 | "precision not allowed for this argument type"); | |
f67539c2 | 990 | EXPECT_THROW_MSG(format("{0:.{1}}", 0), format_error, "argument not found"); |
9f95a23c TL |
991 | |
992 | EXPECT_THROW_MSG(format("{0:.{0:}}", 0), format_error, | |
993 | "invalid format string"); | |
994 | ||
995 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1), format_error, | |
996 | "negative precision"); | |
997 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1u)), format_error, | |
998 | "number is too big"); | |
999 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l), format_error, | |
1000 | "negative precision"); | |
1001 | if (const_check(sizeof(long) > sizeof(int))) { | |
11fdf7f2 | 1002 | long value = INT_MAX; |
9f95a23c TL |
1003 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)), format_error, |
1004 | "number is too big"); | |
11fdf7f2 | 1005 | } |
9f95a23c TL |
1006 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1ul)), format_error, |
1007 | "number is too big"); | |
1008 | ||
1009 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, '0'), format_error, | |
1010 | "precision is not integer"); | |
1011 | EXPECT_THROW_MSG(format("{0:.{1}}", 0, 0.0), format_error, | |
1012 | "precision is not integer"); | |
1013 | ||
1014 | EXPECT_THROW_MSG(format("{0:.{1}}", 42, 2), format_error, | |
1015 | "precision not allowed for this argument type"); | |
1016 | EXPECT_THROW_MSG(format("{0:.{1}f}", 42, 2), format_error, | |
1017 | "precision not allowed for this argument type"); | |
1018 | EXPECT_THROW_MSG(format("{0:.{1}}", 42u, 2), format_error, | |
1019 | "precision not allowed for this argument type"); | |
1020 | EXPECT_THROW_MSG(format("{0:.{1}f}", 42u, 2), format_error, | |
1021 | "precision not allowed for this argument type"); | |
1022 | EXPECT_THROW_MSG(format("{0:.{1}}", 42l, 2), format_error, | |
1023 | "precision not allowed for this argument type"); | |
1024 | EXPECT_THROW_MSG(format("{0:.{1}f}", 42l, 2), format_error, | |
1025 | "precision not allowed for this argument type"); | |
1026 | EXPECT_THROW_MSG(format("{0:.{1}}", 42ul, 2), format_error, | |
1027 | "precision not allowed for this argument type"); | |
1028 | EXPECT_THROW_MSG(format("{0:.{1}f}", 42ul, 2), format_error, | |
1029 | "precision not allowed for this argument type"); | |
1030 | EXPECT_THROW_MSG(format("{0:.{1}}", 42ll, 2), format_error, | |
1031 | "precision not allowed for this argument type"); | |
1032 | EXPECT_THROW_MSG(format("{0:.{1}f}", 42ll, 2), format_error, | |
1033 | "precision not allowed for this argument type"); | |
1034 | EXPECT_THROW_MSG(format("{0:.{1}}", 42ull, 2), format_error, | |
1035 | "precision not allowed for this argument type"); | |
1036 | EXPECT_THROW_MSG(format("{0:.{1}f}", 42ull, 2), format_error, | |
1037 | "precision not allowed for this argument type"); | |
1038 | EXPECT_THROW_MSG(format("{0:3.{1}}", 'x', 0), format_error, | |
1039 | "precision not allowed for this argument type"); | |
11fdf7f2 TL |
1040 | EXPECT_EQ("1.2", format("{0:.{1}}", 1.2345, 2)); |
1041 | EXPECT_EQ("1.2", format("{1:.{0}}", 2, 1.2345l)); | |
1042 | ||
1043 | EXPECT_THROW_MSG(format("{0:.{1}}", reinterpret_cast<void*>(0xcafe), 2), | |
9f95a23c TL |
1044 | format_error, |
1045 | "precision not allowed for this argument type"); | |
11fdf7f2 | 1046 | EXPECT_THROW_MSG(format("{0:.{1}f}", reinterpret_cast<void*>(0xcafe), 2), |
9f95a23c TL |
1047 | format_error, |
1048 | "precision not allowed for this argument type"); | |
11fdf7f2 TL |
1049 | |
1050 | EXPECT_EQ("st", format("{0:.{1}}", "str", 2)); | |
1051 | } | |
1052 | ||
1053 | template <typename T> | |
9f95a23c | 1054 | void check_unknown_types(const T& value, const char* types, const char*) { |
11fdf7f2 | 1055 | char format_str[BUFFER_SIZE]; |
9f95a23c | 1056 | const char* special = ".0123456789}"; |
11fdf7f2 TL |
1057 | for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) { |
1058 | char c = static_cast<char>(i); | |
1059 | if (std::strchr(types, c) || std::strchr(special, c) || !c) continue; | |
1060 | safe_sprintf(format_str, "{0:10%c}", c); | |
9f95a23c | 1061 | const char* message = "invalid type specifier"; |
11fdf7f2 | 1062 | EXPECT_THROW_MSG(format(format_str, value), format_error, message) |
9f95a23c | 1063 | << format_str << " " << message; |
11fdf7f2 TL |
1064 | } |
1065 | } | |
1066 | ||
1067 | TEST(BoolTest, FormatBool) { | |
1068 | EXPECT_EQ("true", format("{}", true)); | |
1069 | EXPECT_EQ("false", format("{}", false)); | |
1070 | EXPECT_EQ("1", format("{:d}", true)); | |
1071 | EXPECT_EQ("true ", format("{:5}", true)); | |
1072 | EXPECT_EQ(L"true", format(L"{}", true)); | |
1073 | } | |
1074 | ||
1075 | TEST(FormatterTest, FormatShort) { | |
1076 | short s = 42; | |
1077 | EXPECT_EQ("42", format("{0:d}", s)); | |
1078 | unsigned short us = 42; | |
1079 | EXPECT_EQ("42", format("{0:d}", us)); | |
1080 | } | |
1081 | ||
1082 | TEST(FormatterTest, FormatInt) { | |
9f95a23c TL |
1083 | EXPECT_THROW_MSG(format("{0:v", 42), format_error, |
1084 | "missing '}' in format string"); | |
f67539c2 TL |
1085 | check_unknown_types(42, "bBdoxXnLc", "integer"); |
1086 | EXPECT_EQ("x", format("{:c}", static_cast<int>('x'))); | |
11fdf7f2 TL |
1087 | } |
1088 | ||
1089 | TEST(FormatterTest, FormatBin) { | |
1090 | EXPECT_EQ("0", format("{0:b}", 0)); | |
1091 | EXPECT_EQ("101010", format("{0:b}", 42)); | |
1092 | EXPECT_EQ("101010", format("{0:b}", 42u)); | |
1093 | EXPECT_EQ("-101010", format("{0:b}", -42)); | |
1094 | EXPECT_EQ("11000000111001", format("{0:b}", 12345)); | |
1095 | EXPECT_EQ("10010001101000101011001111000", format("{0:b}", 0x12345678)); | |
1096 | EXPECT_EQ("10010000101010111100110111101111", format("{0:b}", 0x90ABCDEF)); | |
1097 | EXPECT_EQ("11111111111111111111111111111111", | |
f67539c2 | 1098 | format("{0:b}", max_value<uint32_t>())); |
11fdf7f2 TL |
1099 | } |
1100 | ||
f67539c2 TL |
1101 | #if FMT_USE_INT128 |
1102 | constexpr auto int128_max = static_cast<__int128_t>( | |
1103 | (static_cast<__uint128_t>(1) << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); | |
1104 | constexpr auto int128_min = -int128_max - 1; | |
1105 | ||
1106 | constexpr auto uint128_max = ~static_cast<__uint128_t>(0); | |
1107 | #endif | |
1108 | ||
11fdf7f2 TL |
1109 | TEST(FormatterTest, FormatDec) { |
1110 | EXPECT_EQ("0", format("{0}", 0)); | |
1111 | EXPECT_EQ("42", format("{0}", 42)); | |
1112 | EXPECT_EQ("42", format("{0:d}", 42)); | |
1113 | EXPECT_EQ("42", format("{0}", 42u)); | |
1114 | EXPECT_EQ("-42", format("{0}", -42)); | |
1115 | EXPECT_EQ("12345", format("{0}", 12345)); | |
1116 | EXPECT_EQ("67890", format("{0}", 67890)); | |
f67539c2 TL |
1117 | #if FMT_USE_INT128 |
1118 | EXPECT_EQ("0", format("{0}", static_cast<__int128_t>(0))); | |
1119 | EXPECT_EQ("0", format("{0}", static_cast<__uint128_t>(0))); | |
1120 | EXPECT_EQ("9223372036854775808", | |
1121 | format("{0}", static_cast<__int128_t>(INT64_MAX) + 1)); | |
1122 | EXPECT_EQ("-9223372036854775809", | |
1123 | format("{0}", static_cast<__int128_t>(INT64_MIN) - 1)); | |
1124 | EXPECT_EQ("18446744073709551616", | |
1125 | format("{0}", static_cast<__int128_t>(UINT64_MAX) + 1)); | |
1126 | EXPECT_EQ("170141183460469231731687303715884105727", | |
1127 | format("{0}", int128_max)); | |
1128 | EXPECT_EQ("-170141183460469231731687303715884105728", | |
1129 | format("{0}", int128_min)); | |
1130 | EXPECT_EQ("340282366920938463463374607431768211455", | |
1131 | format("{0}", uint128_max)); | |
1132 | #endif | |
1133 | ||
11fdf7f2 TL |
1134 | char buffer[BUFFER_SIZE]; |
1135 | safe_sprintf(buffer, "%d", INT_MIN); | |
1136 | EXPECT_EQ(buffer, format("{0}", INT_MIN)); | |
1137 | safe_sprintf(buffer, "%d", INT_MAX); | |
1138 | EXPECT_EQ(buffer, format("{0}", INT_MAX)); | |
1139 | safe_sprintf(buffer, "%u", UINT_MAX); | |
1140 | EXPECT_EQ(buffer, format("{0}", UINT_MAX)); | |
1141 | safe_sprintf(buffer, "%ld", 0 - static_cast<unsigned long>(LONG_MIN)); | |
1142 | EXPECT_EQ(buffer, format("{0}", LONG_MIN)); | |
1143 | safe_sprintf(buffer, "%ld", LONG_MAX); | |
1144 | EXPECT_EQ(buffer, format("{0}", LONG_MAX)); | |
1145 | safe_sprintf(buffer, "%lu", ULONG_MAX); | |
1146 | EXPECT_EQ(buffer, format("{0}", ULONG_MAX)); | |
1147 | } | |
1148 | ||
1149 | TEST(FormatterTest, FormatHex) { | |
1150 | EXPECT_EQ("0", format("{0:x}", 0)); | |
1151 | EXPECT_EQ("42", format("{0:x}", 0x42)); | |
1152 | EXPECT_EQ("42", format("{0:x}", 0x42u)); | |
1153 | EXPECT_EQ("-42", format("{0:x}", -0x42)); | |
1154 | EXPECT_EQ("12345678", format("{0:x}", 0x12345678)); | |
1155 | EXPECT_EQ("90abcdef", format("{0:x}", 0x90abcdef)); | |
1156 | EXPECT_EQ("12345678", format("{0:X}", 0x12345678)); | |
1157 | EXPECT_EQ("90ABCDEF", format("{0:X}", 0x90ABCDEF)); | |
f67539c2 TL |
1158 | #if FMT_USE_INT128 |
1159 | EXPECT_EQ("0", format("{0:x}", static_cast<__int128_t>(0))); | |
1160 | EXPECT_EQ("0", format("{0:x}", static_cast<__uint128_t>(0))); | |
1161 | EXPECT_EQ("8000000000000000", | |
1162 | format("{0:x}", static_cast<__int128_t>(INT64_MAX) + 1)); | |
1163 | EXPECT_EQ("-8000000000000001", | |
1164 | format("{0:x}", static_cast<__int128_t>(INT64_MIN) - 1)); | |
1165 | EXPECT_EQ("10000000000000000", | |
1166 | format("{0:x}", static_cast<__int128_t>(UINT64_MAX) + 1)); | |
1167 | EXPECT_EQ("7fffffffffffffffffffffffffffffff", format("{0:x}", int128_max)); | |
1168 | EXPECT_EQ("-80000000000000000000000000000000", format("{0:x}", int128_min)); | |
1169 | EXPECT_EQ("ffffffffffffffffffffffffffffffff", format("{0:x}", uint128_max)); | |
1170 | #endif | |
11fdf7f2 TL |
1171 | |
1172 | char buffer[BUFFER_SIZE]; | |
1173 | safe_sprintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN)); | |
1174 | EXPECT_EQ(buffer, format("{0:x}", INT_MIN)); | |
1175 | safe_sprintf(buffer, "%x", INT_MAX); | |
1176 | EXPECT_EQ(buffer, format("{0:x}", INT_MAX)); | |
1177 | safe_sprintf(buffer, "%x", UINT_MAX); | |
1178 | EXPECT_EQ(buffer, format("{0:x}", UINT_MAX)); | |
1179 | safe_sprintf(buffer, "-%lx", 0 - static_cast<unsigned long>(LONG_MIN)); | |
1180 | EXPECT_EQ(buffer, format("{0:x}", LONG_MIN)); | |
1181 | safe_sprintf(buffer, "%lx", LONG_MAX); | |
1182 | EXPECT_EQ(buffer, format("{0:x}", LONG_MAX)); | |
1183 | safe_sprintf(buffer, "%lx", ULONG_MAX); | |
1184 | EXPECT_EQ(buffer, format("{0:x}", ULONG_MAX)); | |
1185 | } | |
1186 | ||
1187 | TEST(FormatterTest, FormatOct) { | |
1188 | EXPECT_EQ("0", format("{0:o}", 0)); | |
1189 | EXPECT_EQ("42", format("{0:o}", 042)); | |
1190 | EXPECT_EQ("42", format("{0:o}", 042u)); | |
1191 | EXPECT_EQ("-42", format("{0:o}", -042)); | |
1192 | EXPECT_EQ("12345670", format("{0:o}", 012345670)); | |
f67539c2 TL |
1193 | #if FMT_USE_INT128 |
1194 | EXPECT_EQ("0", format("{0:o}", static_cast<__int128_t>(0))); | |
1195 | EXPECT_EQ("0", format("{0:o}", static_cast<__uint128_t>(0))); | |
1196 | EXPECT_EQ("1000000000000000000000", | |
1197 | format("{0:o}", static_cast<__int128_t>(INT64_MAX) + 1)); | |
1198 | EXPECT_EQ("-1000000000000000000001", | |
1199 | format("{0:o}", static_cast<__int128_t>(INT64_MIN) - 1)); | |
1200 | EXPECT_EQ("2000000000000000000000", | |
1201 | format("{0:o}", static_cast<__int128_t>(UINT64_MAX) + 1)); | |
1202 | EXPECT_EQ("1777777777777777777777777777777777777777777", | |
1203 | format("{0:o}", int128_max)); | |
1204 | EXPECT_EQ("-2000000000000000000000000000000000000000000", | |
1205 | format("{0:o}", int128_min)); | |
1206 | EXPECT_EQ("3777777777777777777777777777777777777777777", | |
1207 | format("{0:o}", uint128_max)); | |
1208 | #endif | |
1209 | ||
11fdf7f2 TL |
1210 | char buffer[BUFFER_SIZE]; |
1211 | safe_sprintf(buffer, "-%o", 0 - static_cast<unsigned>(INT_MIN)); | |
1212 | EXPECT_EQ(buffer, format("{0:o}", INT_MIN)); | |
1213 | safe_sprintf(buffer, "%o", INT_MAX); | |
1214 | EXPECT_EQ(buffer, format("{0:o}", INT_MAX)); | |
1215 | safe_sprintf(buffer, "%o", UINT_MAX); | |
1216 | EXPECT_EQ(buffer, format("{0:o}", UINT_MAX)); | |
1217 | safe_sprintf(buffer, "-%lo", 0 - static_cast<unsigned long>(LONG_MIN)); | |
1218 | EXPECT_EQ(buffer, format("{0:o}", LONG_MIN)); | |
1219 | safe_sprintf(buffer, "%lo", LONG_MAX); | |
1220 | EXPECT_EQ(buffer, format("{0:o}", LONG_MAX)); | |
1221 | safe_sprintf(buffer, "%lo", ULONG_MAX); | |
1222 | EXPECT_EQ(buffer, format("{0:o}", ULONG_MAX)); | |
1223 | } | |
1224 | ||
1225 | TEST(FormatterTest, FormatIntLocale) { | |
f67539c2 TL |
1226 | EXPECT_EQ("1234", format("{:n}", 1234)); |
1227 | EXPECT_EQ("1234", format("{:L}", 1234)); | |
11fdf7f2 TL |
1228 | } |
1229 | ||
1230 | struct ConvertibleToLongLong { | |
1231 | operator long long() const { return 1LL << 32; } | |
1232 | }; | |
1233 | ||
1234 | TEST(FormatterTest, FormatConvertibleToLongLong) { | |
1235 | EXPECT_EQ("100000000", format("{:x}", ConvertibleToLongLong())); | |
1236 | } | |
1237 | ||
1238 | TEST(FormatterTest, FormatFloat) { | |
1239 | EXPECT_EQ("392.500000", format("{0:f}", 392.5f)); | |
1240 | } | |
1241 | ||
1242 | TEST(FormatterTest, FormatDouble) { | |
f67539c2 | 1243 | check_unknown_types(1.2, "eEfFgGaAnL%", "double"); |
9f95a23c | 1244 | EXPECT_EQ("0.0", format("{:}", 0.0)); |
eafe8130 TL |
1245 | EXPECT_EQ("0.000000", format("{:f}", 0.0)); |
1246 | EXPECT_EQ("0", format("{:g}", 0.0)); | |
1247 | EXPECT_EQ("392.65", format("{:}", 392.65)); | |
1248 | EXPECT_EQ("392.65", format("{:g}", 392.65)); | |
1249 | EXPECT_EQ("392.65", format("{:G}", 392.65)); | |
1250 | EXPECT_EQ("392.650000", format("{:f}", 392.65)); | |
1251 | EXPECT_EQ("392.650000", format("{:F}", 392.65)); | |
f67539c2 | 1252 | EXPECT_EQ("42", format("{:L}", 42.0)); |
11fdf7f2 TL |
1253 | char buffer[BUFFER_SIZE]; |
1254 | safe_sprintf(buffer, "%e", 392.65); | |
1255 | EXPECT_EQ(buffer, format("{0:e}", 392.65)); | |
1256 | safe_sprintf(buffer, "%E", 392.65); | |
1257 | EXPECT_EQ(buffer, format("{0:E}", 392.65)); | |
1258 | EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.65)); | |
1259 | safe_sprintf(buffer, "%a", -42.0); | |
1260 | EXPECT_EQ(buffer, format("{:a}", -42.0)); | |
1261 | safe_sprintf(buffer, "%A", -42.0); | |
1262 | EXPECT_EQ(buffer, format("{:A}", -42.0)); | |
1263 | } | |
1264 | ||
9f95a23c | 1265 | TEST(FormatterTest, PrecisionRounding) { |
f67539c2 TL |
1266 | EXPECT_EQ("0", format("{:.0f}", 0.0)); |
1267 | EXPECT_EQ("0", format("{:.0f}", 0.01)); | |
9f95a23c TL |
1268 | EXPECT_EQ("0", format("{:.0f}", 0.1)); |
1269 | EXPECT_EQ("0.000", format("{:.3f}", 0.00049)); | |
1270 | EXPECT_EQ("0.001", format("{:.3f}", 0.0005)); | |
1271 | EXPECT_EQ("0.001", format("{:.3f}", 0.00149)); | |
1272 | EXPECT_EQ("0.002", format("{:.3f}", 0.0015)); | |
1273 | EXPECT_EQ("1.000", format("{:.3f}", 0.9999)); | |
1274 | EXPECT_EQ("0.00123", format("{:.3}", 0.00123)); | |
f67539c2 | 1275 | EXPECT_EQ("0.1", format("{:.16g}", 0.1)); |
9f95a23c TL |
1276 | // Trigger rounding error in Grisu by a carefully chosen number. |
1277 | auto n = 3788512123356.985352; | |
1278 | char buffer[64]; | |
f67539c2 | 1279 | safe_sprintf(buffer, "%f", n); |
9f95a23c | 1280 | EXPECT_EQ(buffer, format("{:f}", n)); |
eafe8130 TL |
1281 | } |
1282 | ||
11fdf7f2 TL |
1283 | TEST(FormatterTest, FormatNaN) { |
1284 | double nan = std::numeric_limits<double>::quiet_NaN(); | |
1285 | EXPECT_EQ("nan", format("{}", nan)); | |
1286 | EXPECT_EQ("+nan", format("{:+}", nan)); | |
1287 | EXPECT_EQ(" nan", format("{: }", nan)); | |
1288 | EXPECT_EQ("NAN", format("{:F}", nan)); | |
1289 | EXPECT_EQ("nan ", format("{:<7}", nan)); | |
1290 | EXPECT_EQ(" nan ", format("{:^7}", nan)); | |
1291 | EXPECT_EQ(" nan", format("{:>7}", nan)); | |
1292 | } | |
1293 | ||
1294 | TEST(FormatterTest, FormatInfinity) { | |
1295 | double inf = std::numeric_limits<double>::infinity(); | |
1296 | EXPECT_EQ("inf", format("{}", inf)); | |
1297 | EXPECT_EQ("+inf", format("{:+}", inf)); | |
1298 | EXPECT_EQ("-inf", format("{}", -inf)); | |
1299 | EXPECT_EQ(" inf", format("{: }", inf)); | |
1300 | EXPECT_EQ("INF", format("{:F}", inf)); | |
1301 | EXPECT_EQ("inf ", format("{:<7}", inf)); | |
1302 | EXPECT_EQ(" inf ", format("{:^7}", inf)); | |
1303 | EXPECT_EQ(" inf", format("{:>7}", inf)); | |
1304 | } | |
1305 | ||
1306 | TEST(FormatterTest, FormatLongDouble) { | |
9f95a23c | 1307 | EXPECT_EQ("0.0", format("{0:}", 0.0l)); |
11fdf7f2 TL |
1308 | EXPECT_EQ("0.000000", format("{0:f}", 0.0l)); |
1309 | EXPECT_EQ("392.65", format("{0:}", 392.65l)); | |
1310 | EXPECT_EQ("392.65", format("{0:g}", 392.65l)); | |
1311 | EXPECT_EQ("392.65", format("{0:G}", 392.65l)); | |
1312 | EXPECT_EQ("392.650000", format("{0:f}", 392.65l)); | |
1313 | EXPECT_EQ("392.650000", format("{0:F}", 392.65l)); | |
1314 | char buffer[BUFFER_SIZE]; | |
1315 | safe_sprintf(buffer, "%Le", 392.65l); | |
1316 | EXPECT_EQ(buffer, format("{0:e}", 392.65l)); | |
1317 | EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.64l)); | |
f67539c2 TL |
1318 | safe_sprintf(buffer, "%La", 3.31l); |
1319 | EXPECT_EQ(buffer, format("{:a}", 3.31l)); | |
11fdf7f2 TL |
1320 | } |
1321 | ||
1322 | TEST(FormatterTest, FormatChar) { | |
f67539c2 | 1323 | const char types[] = "cbBdoxXnL"; |
11fdf7f2 TL |
1324 | check_unknown_types('a', types, "char"); |
1325 | EXPECT_EQ("a", format("{0}", 'a')); | |
1326 | EXPECT_EQ("z", format("{0:c}", 'z')); | |
1327 | EXPECT_EQ(L"a", format(L"{0}", 'a')); | |
1328 | int n = 'x'; | |
9f95a23c | 1329 | for (const char* type = types + 1; *type; ++type) { |
11fdf7f2 TL |
1330 | std::string format_str = fmt::format("{{:{}}}", *type); |
1331 | EXPECT_EQ(fmt::format(format_str, n), fmt::format(format_str, 'x')); | |
1332 | } | |
1333 | EXPECT_EQ(fmt::format("{:02X}", n), fmt::format("{:02X}", 'x')); | |
1334 | } | |
1335 | ||
f67539c2 TL |
1336 | TEST(FormatterTest, FormatVolatileChar) { |
1337 | volatile char c = 'x'; | |
1338 | EXPECT_EQ("x", format("{}", c)); | |
1339 | } | |
1340 | ||
11fdf7f2 TL |
1341 | TEST(FormatterTest, FormatUnsignedChar) { |
1342 | EXPECT_EQ("42", format("{}", static_cast<unsigned char>(42))); | |
1343 | EXPECT_EQ("42", format("{}", static_cast<uint8_t>(42))); | |
1344 | } | |
1345 | ||
1346 | TEST(FormatterTest, FormatWChar) { | |
1347 | EXPECT_EQ(L"a", format(L"{0}", L'a')); | |
1348 | // This shouldn't compile: | |
9f95a23c | 1349 | // format("{}", L'a'); |
11fdf7f2 TL |
1350 | } |
1351 | ||
1352 | TEST(FormatterTest, FormatCString) { | |
1353 | check_unknown_types("test", "sp", "string"); | |
1354 | EXPECT_EQ("test", format("{0}", "test")); | |
1355 | EXPECT_EQ("test", format("{0:s}", "test")); | |
1356 | char nonconst[] = "nonconst"; | |
1357 | EXPECT_EQ("nonconst", format("{0}", nonconst)); | |
f67539c2 | 1358 | EXPECT_THROW_MSG(format("{0}", static_cast<const char*>(nullptr)), |
9f95a23c | 1359 | format_error, "string pointer is null"); |
11fdf7f2 TL |
1360 | } |
1361 | ||
1362 | TEST(FormatterTest, FormatSCharString) { | |
1363 | signed char str[] = "test"; | |
1364 | EXPECT_EQ("test", format("{0:s}", str)); | |
9f95a23c | 1365 | const signed char* const_str = str; |
11fdf7f2 TL |
1366 | EXPECT_EQ("test", format("{0:s}", const_str)); |
1367 | } | |
1368 | ||
1369 | TEST(FormatterTest, FormatUCharString) { | |
1370 | unsigned char str[] = "test"; | |
1371 | EXPECT_EQ("test", format("{0:s}", str)); | |
9f95a23c | 1372 | const unsigned char* const_str = str; |
11fdf7f2 | 1373 | EXPECT_EQ("test", format("{0:s}", const_str)); |
9f95a23c | 1374 | unsigned char* ptr = str; |
11fdf7f2 TL |
1375 | EXPECT_EQ("test", format("{0:s}", ptr)); |
1376 | } | |
1377 | ||
1378 | TEST(FormatterTest, FormatPointer) { | |
1379 | check_unknown_types(reinterpret_cast<void*>(0x1234), "p", "pointer"); | |
f67539c2 | 1380 | EXPECT_EQ("0x0", format("{0}", static_cast<void*>(nullptr))); |
11fdf7f2 TL |
1381 | EXPECT_EQ("0x1234", format("{0}", reinterpret_cast<void*>(0x1234))); |
1382 | EXPECT_EQ("0x1234", format("{0:p}", reinterpret_cast<void*>(0x1234))); | |
1383 | EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'), | |
9f95a23c | 1384 | format("{0}", reinterpret_cast<void*>(~uintptr_t()))); |
11fdf7f2 | 1385 | EXPECT_EQ("0x1234", format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234)))); |
f67539c2 TL |
1386 | std::unique_ptr<int> up(new int(1)); |
1387 | EXPECT_EQ(format("{}", fmt::ptr(up.get())), format("{}", fmt::ptr(up))); | |
1388 | std::shared_ptr<int> sp(new int(1)); | |
1389 | EXPECT_EQ(format("{}", fmt::ptr(sp.get())), format("{}", fmt::ptr(sp))); | |
1390 | EXPECT_EQ("0x0", format("{}", nullptr)); | |
11fdf7f2 TL |
1391 | } |
1392 | ||
1393 | TEST(FormatterTest, FormatString) { | |
1394 | EXPECT_EQ("test", format("{0}", std::string("test"))); | |
1395 | } | |
1396 | ||
1397 | TEST(FormatterTest, FormatStringView) { | |
1398 | EXPECT_EQ("test", format("{}", string_view("test"))); | |
1399 | EXPECT_EQ("", format("{}", string_view())); | |
1400 | } | |
1401 | ||
f67539c2 TL |
1402 | #ifdef FMT_USE_STRING_VIEW |
1403 | struct string_viewable {}; | |
1404 | ||
1405 | FMT_BEGIN_NAMESPACE | |
1406 | template <> struct formatter<string_viewable> : formatter<std::string_view> { | |
1407 | auto format(string_viewable, format_context& ctx) -> decltype(ctx.out()) { | |
1408 | return formatter<std::string_view>::format("foo", ctx); | |
1409 | } | |
1410 | }; | |
1411 | FMT_END_NAMESPACE | |
1412 | ||
11fdf7f2 | 1413 | TEST(FormatterTest, FormatStdStringView) { |
f67539c2 TL |
1414 | EXPECT_EQ("test", format("{}", std::string_view("test"))); |
1415 | EXPECT_EQ("foo", format("{}", string_viewable())); | |
1416 | } | |
1417 | ||
1418 | struct explicitly_convertible_to_std_string_view { | |
1419 | explicit operator std::string_view() const { return "foo"; } | |
1420 | }; | |
1421 | ||
1422 | namespace fmt { | |
1423 | template <> | |
1424 | struct formatter<explicitly_convertible_to_std_string_view> | |
1425 | : formatter<std::string_view> { | |
1426 | auto format(const explicitly_convertible_to_std_string_view& v, | |
1427 | format_context& ctx) -> decltype(ctx.out()) { | |
1428 | return format_to(ctx.out(), "'{}'", std::string_view(v)); | |
1429 | } | |
1430 | }; | |
1431 | } // namespace fmt | |
1432 | ||
1433 | TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) { | |
1434 | EXPECT_EQ("'foo'", | |
1435 | fmt::format("{}", explicitly_convertible_to_std_string_view())); | |
1436 | } | |
1437 | #endif | |
1438 | ||
1439 | // std::is_constructible is broken in MSVC until version 2015. | |
1440 | #if !FMT_MSC_VER || FMT_MSC_VER >= 1900 | |
1441 | struct explicitly_convertible_to_wstring_view { | |
1442 | explicit operator fmt::wstring_view() const { return L"foo"; } | |
1443 | }; | |
1444 | ||
1445 | TEST(FormatTest, FormatExplicitlyConvertibleToWStringView) { | |
1446 | EXPECT_EQ(L"foo", | |
1447 | fmt::format(L"{}", explicitly_convertible_to_wstring_view())); | |
11fdf7f2 TL |
1448 | } |
1449 | #endif | |
1450 | ||
f67539c2 TL |
1451 | namespace fake_qt { |
1452 | class QString { | |
1453 | public: | |
1454 | QString(const wchar_t* s) : s_(std::make_shared<std::wstring>(s)) {} | |
1455 | const wchar_t* utf16() const FMT_NOEXCEPT { return s_->data(); } | |
1456 | int size() const FMT_NOEXCEPT { return static_cast<int>(s_->size()); } | |
1457 | ||
1458 | private: | |
1459 | std::shared_ptr<std::wstring> s_; | |
1460 | }; | |
1461 | ||
1462 | fmt::basic_string_view<wchar_t> to_string_view(const QString& s) FMT_NOEXCEPT { | |
1463 | return {s.utf16(), static_cast<size_t>(s.size())}; | |
1464 | } | |
1465 | } // namespace fake_qt | |
1466 | ||
1467 | TEST(FormatTest, FormatForeignStrings) { | |
1468 | using fake_qt::QString; | |
1469 | EXPECT_EQ(fmt::format(QString(L"{}"), 42), L"42"); | |
1470 | EXPECT_EQ(fmt::format(QString(L"{}"), QString(L"42")), L"42"); | |
1471 | } | |
1472 | ||
11fdf7f2 | 1473 | FMT_BEGIN_NAMESPACE |
9f95a23c | 1474 | template <> struct formatter<Date> { |
11fdf7f2 | 1475 | template <typename ParseContext> |
9f95a23c | 1476 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { |
11fdf7f2 | 1477 | auto it = ctx.begin(); |
9f95a23c | 1478 | if (*it == 'd') ++it; |
11fdf7f2 TL |
1479 | return it; |
1480 | } | |
1481 | ||
9f95a23c | 1482 | auto format(const Date& d, format_context& ctx) -> decltype(ctx.out()) { |
11fdf7f2 TL |
1483 | format_to(ctx.out(), "{}-{}-{}", d.year(), d.month(), d.day()); |
1484 | return ctx.out(); | |
1485 | } | |
1486 | }; | |
1487 | FMT_END_NAMESPACE | |
1488 | ||
1489 | TEST(FormatterTest, FormatCustom) { | |
1490 | Date date(2012, 12, 9); | |
1491 | EXPECT_THROW_MSG(fmt::format("{:s}", date), format_error, | |
1492 | "unknown format specifier"); | |
1493 | } | |
1494 | ||
1495 | class Answer {}; | |
1496 | ||
1497 | FMT_BEGIN_NAMESPACE | |
9f95a23c | 1498 | template <> struct formatter<Answer> : formatter<int> { |
11fdf7f2 | 1499 | template <typename FormatContext> |
9f95a23c | 1500 | auto format(Answer, FormatContext& ctx) -> decltype(ctx.out()) { |
11fdf7f2 TL |
1501 | return formatter<int>::format(42, ctx); |
1502 | } | |
1503 | }; | |
1504 | FMT_END_NAMESPACE | |
1505 | ||
1506 | TEST(FormatterTest, CustomFormat) { | |
1507 | EXPECT_EQ("42", format("{0}", Answer())); | |
1508 | EXPECT_EQ("0042", format("{:04}", Answer())); | |
1509 | } | |
1510 | ||
1511 | TEST(FormatterTest, CustomFormatTo) { | |
1512 | char buf[10] = {}; | |
9f95a23c | 1513 | auto end = |
f67539c2 | 1514 | &*fmt::format_to(fmt::detail::make_checked(buf, 10), "{}", Answer()); |
11fdf7f2 TL |
1515 | EXPECT_EQ(end, buf + 2); |
1516 | EXPECT_STREQ(buf, "42"); | |
1517 | } | |
1518 | ||
1519 | TEST(FormatterTest, WideFormatString) { | |
1520 | EXPECT_EQ(L"42", format(L"{}", 42)); | |
1521 | EXPECT_EQ(L"4.2", format(L"{}", 4.2)); | |
1522 | EXPECT_EQ(L"abc", format(L"{}", L"abc")); | |
1523 | EXPECT_EQ(L"z", format(L"{}", L'z')); | |
1524 | } | |
1525 | ||
1526 | TEST(FormatterTest, FormatStringFromSpeedTest) { | |
1527 | EXPECT_EQ("1.2340000000:0042:+3.13:str:0x3e8:X:%", | |
9f95a23c TL |
1528 | format("{0:0.10f}:{1:04}:{2:+g}:{3}:{4}:{5}:%", 1.234, 42, 3.13, |
1529 | "str", reinterpret_cast<void*>(1000), 'X')); | |
11fdf7f2 TL |
1530 | } |
1531 | ||
1532 | TEST(FormatterTest, FormatExamples) { | |
1533 | std::string message = format("The answer is {}", 42); | |
1534 | EXPECT_EQ("The answer is 42", message); | |
1535 | ||
1536 | EXPECT_EQ("42", format("{}", 42)); | |
1537 | EXPECT_EQ("42", format(std::string("{}"), 42)); | |
1538 | ||
1539 | memory_buffer out; | |
1540 | format_to(out, "The answer is {}.", 42); | |
1541 | EXPECT_EQ("The answer is 42.", to_string(out)); | |
1542 | ||
9f95a23c TL |
1543 | const char* filename = "nonexistent"; |
1544 | FILE* ftest = safe_fopen(filename, "r"); | |
11fdf7f2 TL |
1545 | if (ftest) fclose(ftest); |
1546 | int error_code = errno; | |
f67539c2 | 1547 | EXPECT_TRUE(ftest == nullptr); |
9f95a23c TL |
1548 | EXPECT_SYSTEM_ERROR( |
1549 | { | |
1550 | FILE* f = safe_fopen(filename, "r"); | |
1551 | if (!f) | |
1552 | throw fmt::system_error(errno, "Cannot open file '{}'", filename); | |
1553 | fclose(f); | |
1554 | }, | |
1555 | error_code, "Cannot open file 'nonexistent'"); | |
11fdf7f2 TL |
1556 | } |
1557 | ||
1558 | TEST(FormatterTest, Examples) { | |
1559 | EXPECT_EQ("First, thou shalt count to three", | |
9f95a23c TL |
1560 | format("First, thou shalt count to {0}", "three")); |
1561 | EXPECT_EQ("Bring me a shrubbery", format("Bring me a {}", "shrubbery")); | |
11fdf7f2 TL |
1562 | EXPECT_EQ("From 1 to 3", format("From {} to {}", 1, 3)); |
1563 | ||
1564 | char buffer[BUFFER_SIZE]; | |
1565 | safe_sprintf(buffer, "%03.2f", -1.2); | |
1566 | EXPECT_EQ(buffer, format("{:03.2f}", -1.2)); | |
1567 | ||
1568 | EXPECT_EQ("a, b, c", format("{0}, {1}, {2}", 'a', 'b', 'c')); | |
1569 | EXPECT_EQ("a, b, c", format("{}, {}, {}", 'a', 'b', 'c')); | |
1570 | EXPECT_EQ("c, b, a", format("{2}, {1}, {0}", 'a', 'b', 'c')); | |
1571 | EXPECT_EQ("abracadabra", format("{0}{1}{0}", "abra", "cad")); | |
1572 | ||
9f95a23c | 1573 | EXPECT_EQ("left aligned ", format("{:<30}", "left aligned")); |
11fdf7f2 | 1574 | EXPECT_EQ(" right aligned", |
9f95a23c TL |
1575 | format("{:>30}", "right aligned")); |
1576 | EXPECT_EQ(" centered ", format("{:^30}", "centered")); | |
1577 | EXPECT_EQ("***********centered***********", format("{:*^30}", "centered")); | |
1578 | ||
1579 | EXPECT_EQ("+3.140000; -3.140000", format("{:+f}; {:+f}", 3.14, -3.14)); | |
1580 | EXPECT_EQ(" 3.140000; -3.140000", format("{: f}; {: f}", 3.14, -3.14)); | |
1581 | EXPECT_EQ("3.140000; -3.140000", format("{:-f}; {:-f}", 3.14, -3.14)); | |
11fdf7f2 TL |
1582 | |
1583 | EXPECT_EQ("int: 42; hex: 2a; oct: 52", | |
9f95a23c | 1584 | format("int: {0:d}; hex: {0:x}; oct: {0:o}", 42)); |
11fdf7f2 | 1585 | EXPECT_EQ("int: 42; hex: 0x2a; oct: 052", |
9f95a23c | 1586 | format("int: {0:d}; hex: {0:#x}; oct: {0:#o}", 42)); |
11fdf7f2 TL |
1587 | |
1588 | EXPECT_EQ("The answer is 42", format("The answer is {}", 42)); | |
9f95a23c TL |
1589 | EXPECT_THROW_MSG(format("The answer is {:d}", "forty-two"), format_error, |
1590 | "invalid type specifier"); | |
11fdf7f2 | 1591 | |
9f95a23c | 1592 | EXPECT_EQ(L"Cyrillic letter \x42e", format(L"Cyrillic letter {}", L'\x42e')); |
11fdf7f2 | 1593 | |
9f95a23c TL |
1594 | EXPECT_WRITE( |
1595 | stdout, fmt::print("{}", std::numeric_limits<double>::infinity()), "inf"); | |
11fdf7f2 TL |
1596 | } |
1597 | ||
1598 | TEST(FormatIntTest, Data) { | |
1599 | fmt::format_int format_int(42); | |
1600 | EXPECT_EQ("42", std::string(format_int.data(), format_int.size())); | |
1601 | } | |
1602 | ||
1603 | TEST(FormatIntTest, FormatInt) { | |
1604 | EXPECT_EQ("42", fmt::format_int(42).str()); | |
1605 | EXPECT_EQ(2u, fmt::format_int(42).size()); | |
1606 | EXPECT_EQ("-42", fmt::format_int(-42).str()); | |
1607 | EXPECT_EQ(3u, fmt::format_int(-42).size()); | |
1608 | EXPECT_EQ("42", fmt::format_int(42ul).str()); | |
1609 | EXPECT_EQ("-42", fmt::format_int(-42l).str()); | |
1610 | EXPECT_EQ("42", fmt::format_int(42ull).str()); | |
1611 | EXPECT_EQ("-42", fmt::format_int(-42ll).str()); | |
1612 | std::ostringstream os; | |
f67539c2 TL |
1613 | os << max_value<int64_t>(); |
1614 | EXPECT_EQ(os.str(), fmt::format_int(max_value<int64_t>()).str()); | |
11fdf7f2 TL |
1615 | } |
1616 | ||
1617 | TEST(FormatTest, Print) { | |
f67539c2 | 1618 | #if FMT_USE_FCNTL |
11fdf7f2 | 1619 | EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!"); |
9f95a23c TL |
1620 | EXPECT_WRITE(stderr, fmt::print(stderr, "Don't {}!", "panic"), |
1621 | "Don't panic!"); | |
11fdf7f2 | 1622 | #endif |
f67539c2 TL |
1623 | // Check that the wide print overload compiles. |
1624 | if (fmt::detail::const_check(false)) fmt::print(L"test"); | |
11fdf7f2 TL |
1625 | } |
1626 | ||
1627 | TEST(FormatTest, Variadic) { | |
1628 | EXPECT_EQ("abc1", format("{}c{}", "ab", 1)); | |
1629 | EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1)); | |
1630 | } | |
1631 | ||
1632 | TEST(FormatTest, Dynamic) { | |
eafe8130 | 1633 | typedef fmt::format_context ctx; |
11fdf7f2 | 1634 | std::vector<fmt::basic_format_arg<ctx>> args; |
f67539c2 TL |
1635 | args.emplace_back(fmt::detail::make_arg<ctx>(42)); |
1636 | args.emplace_back(fmt::detail::make_arg<ctx>("abc1")); | |
1637 | args.emplace_back(fmt::detail::make_arg<ctx>(1.5f)); | |
11fdf7f2 | 1638 | |
9f95a23c | 1639 | std::string result = fmt::vformat( |
f67539c2 TL |
1640 | "{} and {} and {}", |
1641 | fmt::basic_format_args<ctx>(args.data(), static_cast<int>(args.size()))); | |
11fdf7f2 | 1642 | |
9f95a23c | 1643 | EXPECT_EQ("42 and abc1 and 1.5", result); |
11fdf7f2 TL |
1644 | } |
1645 | ||
f67539c2 TL |
1646 | TEST(FormatTest, Bytes) { |
1647 | auto s = fmt::format("{:10}", fmt::bytes("ёжик")); | |
1648 | EXPECT_EQ("ёжик ", s); | |
1649 | EXPECT_EQ(10, s.size()); | |
1650 | } | |
1651 | ||
11fdf7f2 TL |
1652 | TEST(FormatTest, JoinArg) { |
1653 | using fmt::join; | |
9f95a23c | 1654 | int v1[3] = {1, 2, 3}; |
11fdf7f2 TL |
1655 | std::vector<float> v2; |
1656 | v2.push_back(1.2f); | |
1657 | v2.push_back(3.4f); | |
9f95a23c | 1658 | void* v3[2] = {&v1[0], &v1[1]}; |
11fdf7f2 TL |
1659 | |
1660 | EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, v1 + 3, ", "))); | |
1661 | EXPECT_EQ("(1)", format("({})", join(v1, v1 + 1, ", "))); | |
1662 | EXPECT_EQ("()", format("({})", join(v1, v1, ", "))); | |
1663 | EXPECT_EQ("(001, 002, 003)", format("({:03})", join(v1, v1 + 3, ", "))); | |
1664 | EXPECT_EQ("(+01.20, +03.40)", | |
1665 | format("({:+06.2f})", join(v2.begin(), v2.end(), ", "))); | |
1666 | ||
1667 | EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1, v1 + 3, L", "))); | |
1668 | EXPECT_EQ("1, 2, 3", format("{0:{1}}", join(v1, v1 + 3, ", "), 1)); | |
1669 | ||
1670 | EXPECT_EQ(format("{}, {}", v3[0], v3[1]), | |
1671 | format("{}", join(v3, v3 + 2, ", "))); | |
1672 | ||
f67539c2 | 1673 | #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 405 |
11fdf7f2 TL |
1674 | EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", "))); |
1675 | EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", "))); | |
1676 | #endif | |
1677 | } | |
1678 | ||
9f95a23c | 1679 | template <typename T> std::string str(const T& value) { |
11fdf7f2 TL |
1680 | return fmt::format("{}", value); |
1681 | } | |
1682 | ||
1683 | TEST(StrTest, Convert) { | |
1684 | EXPECT_EQ("42", str(42)); | |
1685 | std::string s = str(Date(2012, 12, 9)); | |
1686 | EXPECT_EQ("2012-12-9", s); | |
1687 | } | |
1688 | ||
9f95a23c | 1689 | std::string vformat_message(int id, const char* format, fmt::format_args args) { |
11fdf7f2 TL |
1690 | fmt::memory_buffer buffer; |
1691 | format_to(buffer, "[{}] ", id); | |
1692 | vformat_to(buffer, format, args); | |
1693 | return to_string(buffer); | |
1694 | } | |
1695 | ||
1696 | template <typename... Args> | |
9f95a23c | 1697 | std::string format_message(int id, const char* format, const Args&... args) { |
11fdf7f2 TL |
1698 | auto va = fmt::make_format_args(args...); |
1699 | return vformat_message(id, format, va); | |
1700 | } | |
1701 | ||
1702 | TEST(FormatTest, FormatMessageExample) { | |
1703 | EXPECT_EQ("[42] something happened", | |
9f95a23c | 1704 | format_message(42, "{} happened", "something")); |
11fdf7f2 TL |
1705 | } |
1706 | ||
9f95a23c TL |
1707 | template <typename... Args> |
1708 | void print_error(const char* file, int line, const char* format, | |
1709 | const Args&... args) { | |
11fdf7f2 TL |
1710 | fmt::print("{}: {}: ", file, line); |
1711 | fmt::print(format, args...); | |
1712 | } | |
1713 | ||
1714 | TEST(FormatTest, UnpackedArgs) { | |
1715 | EXPECT_EQ("0123456789abcdefg", | |
9f95a23c TL |
1716 | fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 0, 1, 2, 3, 4, 5, |
1717 | 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g')); | |
11fdf7f2 TL |
1718 | } |
1719 | ||
f67539c2 TL |
1720 | struct string_like {}; |
1721 | fmt::string_view to_string_view(string_like) { return "foo"; } | |
1722 | ||
1723 | constexpr char with_null[3] = {'{', '}', '\0'}; | |
1724 | constexpr char no_null[2] = {'{', '}'}; | |
1725 | ||
1726 | TEST(FormatTest, CompileTimeString) { | |
1727 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42)); | |
1728 | EXPECT_EQ(L"42", fmt::format(FMT_STRING(L"{}"), 42)); | |
1729 | EXPECT_EQ("foo", fmt::format(FMT_STRING("{}"), string_like())); | |
1730 | (void)with_null; | |
1731 | (void)no_null; | |
1732 | #if __cplusplus >= 201703L | |
1733 | EXPECT_EQ("42", fmt::format(FMT_STRING(with_null), 42)); | |
1734 | EXPECT_EQ("42", fmt::format(FMT_STRING(no_null), 42)); | |
1735 | #endif | |
1736 | #if defined(FMT_USE_STRING_VIEW) && __cplusplus >= 201703L | |
1737 | EXPECT_EQ("42", fmt::format(FMT_STRING(std::string_view("{}")), 42)); | |
1738 | EXPECT_EQ(L"42", fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42)); | |
1739 | #endif | |
1740 | } | |
1741 | ||
1742 | TEST(FormatTest, CustomFormatCompileTimeString) { | |
1743 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), Answer())); | |
1744 | Answer answer; | |
1745 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), answer)); | |
1746 | char buf[10] = {}; | |
1747 | fmt::format_to(buf, FMT_STRING("{}"), answer); | |
1748 | const Answer const_answer = Answer(); | |
1749 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), const_answer)); | |
1750 | } | |
1751 | ||
11fdf7f2 TL |
1752 | #if FMT_USE_USER_DEFINED_LITERALS |
1753 | // Passing user-defined literals directly to EXPECT_EQ causes problems | |
1754 | // with macro argument stringification (#) on some versions of GCC. | |
1755 | // Workaround: Assing the UDL result to a variable before the macro. | |
1756 | ||
1757 | using namespace fmt::literals; | |
1758 | ||
1759 | TEST(LiteralsTest, Format) { | |
1760 | auto udl_format = "{}c{}"_format("ab", 1); | |
1761 | EXPECT_EQ(format("{}c{}", "ab", 1), udl_format); | |
1762 | auto udl_format_w = L"{}c{}"_format(L"ab", 1); | |
1763 | EXPECT_EQ(format(L"{}c{}", L"ab", 1), udl_format_w); | |
1764 | } | |
1765 | ||
1766 | TEST(LiteralsTest, NamedArg) { | |
9f95a23c TL |
1767 | auto udl_a = format("{first}{second}{first}{third}", "first"_a = "abra", |
1768 | "second"_a = "cad", "third"_a = 99); | |
1769 | EXPECT_EQ(format("{first}{second}{first}{third}", fmt::arg("first", "abra"), | |
1770 | fmt::arg("second", "cad"), fmt::arg("third", 99)), | |
11fdf7f2 | 1771 | udl_a); |
9f95a23c TL |
1772 | auto udl_a_w = format(L"{first}{second}{first}{third}", L"first"_a = L"abra", |
1773 | L"second"_a = L"cad", L"third"_a = 99); | |
1774 | EXPECT_EQ( | |
1775 | format(L"{first}{second}{first}{third}", fmt::arg(L"first", L"abra"), | |
1776 | fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)), | |
1777 | udl_a_w); | |
11fdf7f2 TL |
1778 | } |
1779 | ||
1780 | TEST(FormatTest, UdlTemplate) { | |
1781 | EXPECT_EQ("foo", "foo"_format()); | |
1782 | EXPECT_EQ(" 42", "{0:10}"_format(42)); | |
f67539c2 TL |
1783 | } |
1784 | ||
1785 | TEST(FormatTest, UdlPassUserDefinedObjectAsLvalue) { | |
1786 | Date date(2015, 10, 21); | |
1787 | EXPECT_EQ("2015-10-21", "{}"_format(date)); | |
11fdf7f2 | 1788 | } |
9f95a23c | 1789 | #endif // FMT_USE_USER_DEFINED_LITERALS |
11fdf7f2 TL |
1790 | |
1791 | enum TestEnum { A }; | |
1792 | ||
9f95a23c | 1793 | TEST(FormatTest, Enum) { EXPECT_EQ("0", fmt::format("{}", A)); } |
11fdf7f2 | 1794 | |
f67539c2 TL |
1795 | TEST(FormatTest, FormatterNotSpecialized) { |
1796 | static_assert( | |
1797 | !fmt::has_formatter<fmt::formatter<TestEnum>, fmt::format_context>::value, | |
1798 | ""); | |
11fdf7f2 TL |
1799 | } |
1800 | ||
1801 | #if FMT_HAS_FEATURE(cxx_strong_enums) | |
f67539c2 | 1802 | enum big_enum : unsigned long long { big_enum_value = 5000000000ULL }; |
11fdf7f2 | 1803 | |
f67539c2 TL |
1804 | TEST(FormatTest, StrongEnum) { |
1805 | EXPECT_EQ("5000000000", fmt::format("{}", big_enum_value)); | |
1806 | } | |
11fdf7f2 TL |
1807 | #endif |
1808 | ||
f67539c2 | 1809 | using buffer_range = fmt::buffer_range<char>; |
11fdf7f2 | 1810 | |
9f95a23c | 1811 | class mock_arg_formatter |
f67539c2 | 1812 | : public fmt::detail::arg_formatter_base<buffer_range> { |
11fdf7f2 | 1813 | private: |
f67539c2 TL |
1814 | #if FMT_USE_INT128 |
1815 | MOCK_METHOD1(call, void(__int128_t value)); | |
1816 | #else | |
9f95a23c | 1817 | MOCK_METHOD1(call, void(long long value)); |
f67539c2 | 1818 | #endif |
11fdf7f2 TL |
1819 | |
1820 | public: | |
f67539c2 | 1821 | typedef fmt::detail::arg_formatter_base<buffer_range> base; |
11fdf7f2 TL |
1822 | typedef buffer_range range; |
1823 | ||
9f95a23c | 1824 | mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*, |
f67539c2 TL |
1825 | fmt::format_specs* s = nullptr) |
1826 | : base(fmt::detail::get_container(ctx.out()), s, ctx.locale()) { | |
11fdf7f2 TL |
1827 | EXPECT_CALL(*this, call(42)); |
1828 | } | |
1829 | ||
1830 | template <typename T> | |
f67539c2 | 1831 | typename std::enable_if<fmt::detail::is_integral<T>::value, iterator>::type |
9f95a23c | 1832 | operator()(T value) { |
11fdf7f2 TL |
1833 | call(value); |
1834 | return base::operator()(value); | |
1835 | } | |
1836 | ||
1837 | template <typename T> | |
f67539c2 | 1838 | typename std::enable_if<!fmt::detail::is_integral<T>::value, iterator>::type |
9f95a23c | 1839 | operator()(T value) { |
11fdf7f2 TL |
1840 | return base::operator()(value); |
1841 | } | |
1842 | ||
1843 | iterator operator()(fmt::basic_format_arg<fmt::format_context>::handle) { | |
1844 | return base::operator()(fmt::monostate()); | |
1845 | } | |
1846 | }; | |
1847 | ||
1848 | static void custom_vformat(fmt::string_view format_str, fmt::format_args args) { | |
1849 | fmt::memory_buffer buffer; | |
1850 | fmt::vformat_to<mock_arg_formatter>(buffer, format_str, args); | |
1851 | } | |
1852 | ||
1853 | template <typename... Args> | |
9f95a23c | 1854 | void custom_format(const char* format_str, const Args&... args) { |
11fdf7f2 TL |
1855 | auto va = fmt::make_format_args(args...); |
1856 | return custom_vformat(format_str, va); | |
1857 | } | |
1858 | ||
9f95a23c | 1859 | TEST(FormatTest, CustomArgFormatter) { custom_format("{}", 42); } |
11fdf7f2 TL |
1860 | |
1861 | TEST(FormatTest, NonNullTerminatedFormatString) { | |
1862 | EXPECT_EQ("42", format(string_view("{}foo", 2), 42)); | |
1863 | } | |
1864 | ||
1865 | struct variant { | |
9f95a23c | 1866 | enum { INT, STRING } type; |
11fdf7f2 | 1867 | explicit variant(int) : type(INT) {} |
9f95a23c | 1868 | explicit variant(const char*) : type(STRING) {} |
11fdf7f2 TL |
1869 | }; |
1870 | ||
1871 | FMT_BEGIN_NAMESPACE | |
9f95a23c | 1872 | template <> struct formatter<variant> : dynamic_formatter<> { |
11fdf7f2 | 1873 | auto format(variant value, format_context& ctx) -> decltype(ctx.out()) { |
9f95a23c | 1874 | if (value.type == variant::INT) return dynamic_formatter<>::format(42, ctx); |
11fdf7f2 TL |
1875 | return dynamic_formatter<>::format("foo", ctx); |
1876 | } | |
1877 | }; | |
1878 | FMT_END_NAMESPACE | |
1879 | ||
1880 | TEST(FormatTest, DynamicFormatter) { | |
1881 | auto num = variant(42); | |
1882 | auto str = variant("foo"); | |
1883 | EXPECT_EQ("42", format("{:d}", num)); | |
1884 | EXPECT_EQ("foo", format("{:s}", str)); | |
1885 | EXPECT_EQ(" 42 foo ", format("{:{}} {:{}}", num, 3, str, 4)); | |
9f95a23c TL |
1886 | EXPECT_THROW_MSG(format("{0:{}}", num), format_error, |
1887 | "cannot switch from manual to automatic argument indexing"); | |
1888 | EXPECT_THROW_MSG(format("{:{0}}", num), format_error, | |
1889 | "cannot switch from automatic to manual argument indexing"); | |
f67539c2 | 1890 | #if FMT_NUMERIC_ALIGN |
9f95a23c TL |
1891 | EXPECT_THROW_MSG(format("{:=}", str), format_error, |
1892 | "format specifier requires numeric argument"); | |
f67539c2 | 1893 | #endif |
9f95a23c TL |
1894 | EXPECT_THROW_MSG(format("{:+}", str), format_error, |
1895 | "format specifier requires numeric argument"); | |
1896 | EXPECT_THROW_MSG(format("{:-}", str), format_error, | |
1897 | "format specifier requires numeric argument"); | |
1898 | EXPECT_THROW_MSG(format("{: }", str), format_error, | |
1899 | "format specifier requires numeric argument"); | |
1900 | EXPECT_THROW_MSG(format("{:#}", str), format_error, | |
1901 | "format specifier requires numeric argument"); | |
1902 | EXPECT_THROW_MSG(format("{:0}", str), format_error, | |
1903 | "format specifier requires numeric argument"); | |
1904 | EXPECT_THROW_MSG(format("{:.2}", num), format_error, | |
1905 | "precision not allowed for this argument type"); | |
11fdf7f2 TL |
1906 | } |
1907 | ||
1908 | TEST(FormatTest, ToString) { | |
1909 | EXPECT_EQ("42", fmt::to_string(42)); | |
1910 | EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234))); | |
1911 | } | |
1912 | ||
9f95a23c | 1913 | TEST(FormatTest, ToWString) { EXPECT_EQ(L"42", fmt::to_wstring(42)); } |
11fdf7f2 TL |
1914 | |
1915 | TEST(FormatTest, OutputIterators) { | |
1916 | std::list<char> out; | |
1917 | fmt::format_to(std::back_inserter(out), "{}", 42); | |
1918 | EXPECT_EQ("42", std::string(out.begin(), out.end())); | |
1919 | std::stringstream s; | |
1920 | fmt::format_to(std::ostream_iterator<char>(s), "{}", 42); | |
1921 | EXPECT_EQ("42", s.str()); | |
1922 | } | |
1923 | ||
1924 | TEST(FormatTest, FormattedSize) { | |
1925 | EXPECT_EQ(2u, fmt::formatted_size("{}", 42)); | |
1926 | } | |
1927 | ||
1928 | TEST(FormatTest, FormatToN) { | |
1929 | char buffer[4]; | |
1930 | buffer[3] = 'x'; | |
1931 | auto result = fmt::format_to_n(buffer, 3, "{}", 12345); | |
1932 | EXPECT_EQ(5u, result.size); | |
1933 | EXPECT_EQ(buffer + 3, result.out); | |
1934 | EXPECT_EQ("123x", fmt::string_view(buffer, 4)); | |
1935 | result = fmt::format_to_n(buffer, 3, "{:s}", "foobar"); | |
1936 | EXPECT_EQ(6u, result.size); | |
1937 | EXPECT_EQ(buffer + 3, result.out); | |
1938 | EXPECT_EQ("foox", fmt::string_view(buffer, 4)); | |
9f95a23c TL |
1939 | buffer[0] = 'x'; |
1940 | buffer[1] = 'x'; | |
1941 | buffer[2] = 'x'; | |
1942 | result = fmt::format_to_n(buffer, 3, "{}", 'A'); | |
1943 | EXPECT_EQ(1u, result.size); | |
1944 | EXPECT_EQ(buffer + 1, result.out); | |
1945 | EXPECT_EQ("Axxx", fmt::string_view(buffer, 4)); | |
1946 | result = fmt::format_to_n(buffer, 3, "{}{} ", 'B', 'C'); | |
1947 | EXPECT_EQ(3u, result.size); | |
1948 | EXPECT_EQ(buffer + 3, result.out); | |
1949 | EXPECT_EQ("BC x", fmt::string_view(buffer, 4)); | |
11fdf7f2 TL |
1950 | } |
1951 | ||
1952 | TEST(FormatTest, WideFormatToN) { | |
1953 | wchar_t buffer[4]; | |
1954 | buffer[3] = L'x'; | |
1955 | auto result = fmt::format_to_n(buffer, 3, L"{}", 12345); | |
1956 | EXPECT_EQ(5u, result.size); | |
1957 | EXPECT_EQ(buffer + 3, result.out); | |
1958 | EXPECT_EQ(L"123x", fmt::wstring_view(buffer, 4)); | |
9f95a23c TL |
1959 | buffer[0] = L'x'; |
1960 | buffer[1] = L'x'; | |
1961 | buffer[2] = L'x'; | |
1962 | result = fmt::format_to_n(buffer, 3, L"{}", L'A'); | |
1963 | EXPECT_EQ(1u, result.size); | |
1964 | EXPECT_EQ(buffer + 1, result.out); | |
1965 | EXPECT_EQ(L"Axxx", fmt::wstring_view(buffer, 4)); | |
1966 | result = fmt::format_to_n(buffer, 3, L"{}{} ", L'B', L'C'); | |
1967 | EXPECT_EQ(3u, result.size); | |
1968 | EXPECT_EQ(buffer + 3, result.out); | |
1969 | EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4)); | |
11fdf7f2 TL |
1970 | } |
1971 | ||
f67539c2 TL |
1972 | struct test_output_iterator { |
1973 | char* data; | |
1974 | ||
1975 | using iterator_category = std::output_iterator_tag; | |
1976 | using value_type = void; | |
1977 | using difference_type = void; | |
1978 | using pointer = void; | |
1979 | using reference = void; | |
1980 | ||
1981 | test_output_iterator& operator++() { | |
1982 | ++data; | |
1983 | return *this; | |
1984 | } | |
1985 | test_output_iterator operator++(int) { | |
1986 | auto tmp = *this; | |
1987 | ++data; | |
1988 | return tmp; | |
1989 | } | |
1990 | char& operator*() { return *data; } | |
1991 | }; | |
1992 | ||
1993 | TEST(FormatTest, FormatToNOutputIterator) { | |
1994 | char buf[10] = {}; | |
1995 | fmt::format_to_n(test_output_iterator{buf}, 10, "{}", 42); | |
1996 | EXPECT_STREQ(buf, "42"); | |
1997 | } | |
1998 | ||
11fdf7f2 TL |
1999 | #if FMT_USE_CONSTEXPR |
2000 | struct test_arg_id_handler { | |
2001 | enum result { NONE, EMPTY, INDEX, NAME, ERROR }; | |
2002 | result res = NONE; | |
f67539c2 | 2003 | int index = 0; |
11fdf7f2 TL |
2004 | string_view name; |
2005 | ||
2006 | FMT_CONSTEXPR void operator()() { res = EMPTY; } | |
2007 | ||
f67539c2 | 2008 | FMT_CONSTEXPR void operator()(int i) { |
11fdf7f2 TL |
2009 | res = INDEX; |
2010 | index = i; | |
2011 | } | |
2012 | ||
2013 | FMT_CONSTEXPR void operator()(string_view n) { | |
2014 | res = NAME; | |
2015 | name = n; | |
2016 | } | |
2017 | ||
9f95a23c | 2018 | FMT_CONSTEXPR void on_error(const char*) { res = ERROR; } |
11fdf7f2 TL |
2019 | }; |
2020 | ||
9f95a23c TL |
2021 | template <size_t N> |
2022 | FMT_CONSTEXPR test_arg_id_handler parse_arg_id(const char (&s)[N]) { | |
11fdf7f2 | 2023 | test_arg_id_handler h; |
f67539c2 | 2024 | fmt::detail::parse_arg_id(s, s + N, h); |
11fdf7f2 TL |
2025 | return h; |
2026 | } | |
2027 | ||
2028 | TEST(FormatTest, ConstexprParseArgID) { | |
2029 | static_assert(parse_arg_id(":").res == test_arg_id_handler::EMPTY, ""); | |
2030 | static_assert(parse_arg_id("}").res == test_arg_id_handler::EMPTY, ""); | |
2031 | static_assert(parse_arg_id("42:").res == test_arg_id_handler::INDEX, ""); | |
2032 | static_assert(parse_arg_id("42:").index == 42, ""); | |
2033 | static_assert(parse_arg_id("foo:").res == test_arg_id_handler::NAME, ""); | |
2034 | static_assert(parse_arg_id("foo:").name.size() == 3, ""); | |
2035 | static_assert(parse_arg_id("!").res == test_arg_id_handler::ERROR, ""); | |
2036 | } | |
2037 | ||
2038 | struct test_format_specs_handler { | |
2039 | enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR }; | |
2040 | Result res = NONE; | |
2041 | ||
f67539c2 | 2042 | fmt::align_t align = fmt::align::none; |
11fdf7f2 | 2043 | char fill = 0; |
f67539c2 TL |
2044 | int width = 0; |
2045 | fmt::detail::arg_ref<char> width_ref; | |
2046 | int precision = 0; | |
2047 | fmt::detail::arg_ref<char> precision_ref; | |
11fdf7f2 TL |
2048 | char type = 0; |
2049 | ||
2050 | // Workaround for MSVC2017 bug that results in "expression did not evaluate | |
2051 | // to a constant" with compiler-generated copy ctor. | |
2052 | FMT_CONSTEXPR test_format_specs_handler() {} | |
9f95a23c TL |
2053 | FMT_CONSTEXPR test_format_specs_handler( |
2054 | const test_format_specs_handler& other) | |
2055 | : res(other.res), | |
f67539c2 | 2056 | align(other.align), |
9f95a23c TL |
2057 | fill(other.fill), |
2058 | width(other.width), | |
2059 | width_ref(other.width_ref), | |
2060 | precision(other.precision), | |
2061 | precision_ref(other.precision_ref), | |
2062 | type(other.type) {} | |
11fdf7f2 | 2063 | |
f67539c2 TL |
2064 | FMT_CONSTEXPR void on_align(fmt::align_t a) { align = a; } |
2065 | FMT_CONSTEXPR void on_fill(fmt::string_view f) { fill = f[0]; } | |
11fdf7f2 TL |
2066 | FMT_CONSTEXPR void on_plus() { res = PLUS; } |
2067 | FMT_CONSTEXPR void on_minus() { res = MINUS; } | |
2068 | FMT_CONSTEXPR void on_space() { res = SPACE; } | |
2069 | FMT_CONSTEXPR void on_hash() { res = HASH; } | |
2070 | FMT_CONSTEXPR void on_zero() { res = ZERO; } | |
2071 | ||
f67539c2 TL |
2072 | FMT_CONSTEXPR void on_width(int w) { width = w; } |
2073 | FMT_CONSTEXPR void on_dynamic_width(fmt::detail::auto_id) {} | |
2074 | FMT_CONSTEXPR void on_dynamic_width(int index) { width_ref = index; } | |
11fdf7f2 TL |
2075 | FMT_CONSTEXPR void on_dynamic_width(string_view) {} |
2076 | ||
f67539c2 TL |
2077 | FMT_CONSTEXPR void on_precision(int p) { precision = p; } |
2078 | FMT_CONSTEXPR void on_dynamic_precision(fmt::detail::auto_id) {} | |
2079 | FMT_CONSTEXPR void on_dynamic_precision(int index) { precision_ref = index; } | |
11fdf7f2 TL |
2080 | FMT_CONSTEXPR void on_dynamic_precision(string_view) {} |
2081 | ||
2082 | FMT_CONSTEXPR void end_precision() {} | |
2083 | FMT_CONSTEXPR void on_type(char t) { type = t; } | |
9f95a23c | 2084 | FMT_CONSTEXPR void on_error(const char*) { res = ERROR; } |
11fdf7f2 TL |
2085 | }; |
2086 | ||
9f95a23c TL |
2087 | template <size_t N> |
2088 | FMT_CONSTEXPR test_format_specs_handler parse_test_specs(const char (&s)[N]) { | |
11fdf7f2 | 2089 | test_format_specs_handler h; |
f67539c2 | 2090 | fmt::detail::parse_format_specs(s, s + N, h); |
11fdf7f2 TL |
2091 | return h; |
2092 | } | |
2093 | ||
2094 | TEST(FormatTest, ConstexprParseFormatSpecs) { | |
2095 | typedef test_format_specs_handler handler; | |
f67539c2 | 2096 | static_assert(parse_test_specs("<").align == fmt::align::left, ""); |
11fdf7f2 TL |
2097 | static_assert(parse_test_specs("*^").fill == '*', ""); |
2098 | static_assert(parse_test_specs("+").res == handler::PLUS, ""); | |
2099 | static_assert(parse_test_specs("-").res == handler::MINUS, ""); | |
2100 | static_assert(parse_test_specs(" ").res == handler::SPACE, ""); | |
2101 | static_assert(parse_test_specs("#").res == handler::HASH, ""); | |
2102 | static_assert(parse_test_specs("0").res == handler::ZERO, ""); | |
2103 | static_assert(parse_test_specs("42").width == 42, ""); | |
9f95a23c | 2104 | static_assert(parse_test_specs("{42}").width_ref.val.index == 42, ""); |
11fdf7f2 | 2105 | static_assert(parse_test_specs(".42").precision == 42, ""); |
9f95a23c | 2106 | static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, ""); |
11fdf7f2 TL |
2107 | static_assert(parse_test_specs("d").type == 'd', ""); |
2108 | static_assert(parse_test_specs("{<").res == handler::ERROR, ""); | |
2109 | } | |
2110 | ||
9f95a23c TL |
2111 | struct test_parse_context { |
2112 | typedef char char_type; | |
2113 | ||
f67539c2 | 2114 | FMT_CONSTEXPR int next_arg_id() { return 11; } |
9f95a23c TL |
2115 | template <typename Id> FMT_CONSTEXPR void check_arg_id(Id) {} |
2116 | ||
f67539c2 TL |
2117 | FMT_CONSTEXPR const char* begin() { return nullptr; } |
2118 | FMT_CONSTEXPR const char* end() { return nullptr; } | |
9f95a23c TL |
2119 | |
2120 | void on_error(const char*) {} | |
2121 | }; | |
2122 | ||
11fdf7f2 | 2123 | struct test_context { |
f67539c2 TL |
2124 | using char_type = char; |
2125 | using format_arg = fmt::basic_format_arg<test_context>; | |
2126 | using parse_context_type = fmt::format_parse_context; | |
11fdf7f2 | 2127 | |
9f95a23c TL |
2128 | template <typename T> struct formatter_type { |
2129 | typedef fmt::formatter<T, char_type> type; | |
2130 | }; | |
11fdf7f2 TL |
2131 | |
2132 | template <typename Id> | |
9f95a23c | 2133 | FMT_CONSTEXPR fmt::basic_format_arg<test_context> arg(Id id) { |
f67539c2 | 2134 | return fmt::detail::make_arg<test_context>(id); |
11fdf7f2 TL |
2135 | } |
2136 | ||
9f95a23c | 2137 | void on_error(const char*) {} |
11fdf7f2 | 2138 | |
11fdf7f2 TL |
2139 | FMT_CONSTEXPR test_context error_handler() { return *this; } |
2140 | }; | |
2141 | ||
9f95a23c TL |
2142 | template <size_t N> |
2143 | FMT_CONSTEXPR fmt::format_specs parse_specs(const char (&s)[N]) { | |
f67539c2 TL |
2144 | auto specs = fmt::format_specs(); |
2145 | auto parse_ctx = test_parse_context(); | |
2146 | auto ctx = test_context(); | |
2147 | fmt::detail::specs_handler<test_parse_context, test_context> h( | |
9f95a23c TL |
2148 | specs, parse_ctx, ctx); |
2149 | parse_format_specs(s, s + N, h); | |
11fdf7f2 TL |
2150 | return specs; |
2151 | } | |
2152 | ||
2153 | TEST(FormatTest, ConstexprSpecsHandler) { | |
f67539c2 TL |
2154 | static_assert(parse_specs("<").align == fmt::align::left, ""); |
2155 | static_assert(parse_specs("*^").fill[0] == '*', ""); | |
2156 | static_assert(parse_specs("+").sign == fmt::sign::plus, ""); | |
2157 | static_assert(parse_specs("-").sign == fmt::sign::minus, ""); | |
2158 | static_assert(parse_specs(" ").sign == fmt::sign::space, ""); | |
2159 | static_assert(parse_specs("#").alt, ""); | |
2160 | static_assert(parse_specs("0").align == fmt::align::numeric, ""); | |
2161 | static_assert(parse_specs("42").width == 42, ""); | |
2162 | static_assert(parse_specs("{}").width == 11, ""); | |
2163 | static_assert(parse_specs("{22}").width == 22, ""); | |
eafe8130 TL |
2164 | static_assert(parse_specs(".42").precision == 42, ""); |
2165 | static_assert(parse_specs(".{}").precision == 11, ""); | |
9f95a23c | 2166 | static_assert(parse_specs(".{22}").precision == 22, ""); |
eafe8130 | 2167 | static_assert(parse_specs("d").type == 'd', ""); |
11fdf7f2 TL |
2168 | } |
2169 | ||
9f95a23c | 2170 | template <size_t N> |
f67539c2 | 2171 | FMT_CONSTEXPR fmt::detail::dynamic_format_specs<char> parse_dynamic_specs( |
9f95a23c | 2172 | const char (&s)[N]) { |
f67539c2 | 2173 | fmt::detail::dynamic_format_specs<char> specs; |
9f95a23c | 2174 | test_parse_context ctx{}; |
f67539c2 | 2175 | fmt::detail::dynamic_specs_handler<test_parse_context> h(specs, ctx); |
9f95a23c | 2176 | parse_format_specs(s, s + N, h); |
11fdf7f2 TL |
2177 | return specs; |
2178 | } | |
2179 | ||
2180 | TEST(FormatTest, ConstexprDynamicSpecsHandler) { | |
f67539c2 TL |
2181 | static_assert(parse_dynamic_specs("<").align == fmt::align::left, ""); |
2182 | static_assert(parse_dynamic_specs("*^").fill[0] == '*', ""); | |
2183 | static_assert(parse_dynamic_specs("+").sign == fmt::sign::plus, ""); | |
2184 | static_assert(parse_dynamic_specs("-").sign == fmt::sign::minus, ""); | |
2185 | static_assert(parse_dynamic_specs(" ").sign == fmt::sign::space, ""); | |
2186 | static_assert(parse_dynamic_specs("#").alt, ""); | |
2187 | static_assert(parse_dynamic_specs("0").align == fmt::align::numeric, ""); | |
2188 | static_assert(parse_dynamic_specs("42").width == 42, ""); | |
9f95a23c TL |
2189 | static_assert(parse_dynamic_specs("{}").width_ref.val.index == 11, ""); |
2190 | static_assert(parse_dynamic_specs("{42}").width_ref.val.index == 42, ""); | |
eafe8130 | 2191 | static_assert(parse_dynamic_specs(".42").precision == 42, ""); |
9f95a23c TL |
2192 | static_assert(parse_dynamic_specs(".{}").precision_ref.val.index == 11, ""); |
2193 | static_assert(parse_dynamic_specs(".{42}").precision_ref.val.index == 42, ""); | |
eafe8130 | 2194 | static_assert(parse_dynamic_specs("d").type == 'd', ""); |
11fdf7f2 TL |
2195 | } |
2196 | ||
9f95a23c TL |
2197 | template <size_t N> |
2198 | FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) { | |
f67539c2 TL |
2199 | fmt::detail::specs_checker<test_format_specs_handler> checker( |
2200 | test_format_specs_handler(), fmt::detail::type::double_type); | |
9f95a23c | 2201 | parse_format_specs(s, s + N, checker); |
11fdf7f2 TL |
2202 | return checker; |
2203 | } | |
2204 | ||
2205 | TEST(FormatTest, ConstexprSpecsChecker) { | |
2206 | typedef test_format_specs_handler handler; | |
f67539c2 | 2207 | static_assert(check_specs("<").align == fmt::align::left, ""); |
11fdf7f2 TL |
2208 | static_assert(check_specs("*^").fill == '*', ""); |
2209 | static_assert(check_specs("+").res == handler::PLUS, ""); | |
2210 | static_assert(check_specs("-").res == handler::MINUS, ""); | |
2211 | static_assert(check_specs(" ").res == handler::SPACE, ""); | |
2212 | static_assert(check_specs("#").res == handler::HASH, ""); | |
2213 | static_assert(check_specs("0").res == handler::ZERO, ""); | |
2214 | static_assert(check_specs("42").width == 42, ""); | |
9f95a23c | 2215 | static_assert(check_specs("{42}").width_ref.val.index == 42, ""); |
11fdf7f2 | 2216 | static_assert(check_specs(".42").precision == 42, ""); |
9f95a23c | 2217 | static_assert(check_specs(".{42}").precision_ref.val.index == 42, ""); |
11fdf7f2 TL |
2218 | static_assert(check_specs("d").type == 'd', ""); |
2219 | static_assert(check_specs("{<").res == handler::ERROR, ""); | |
2220 | } | |
2221 | ||
2222 | struct test_format_string_handler { | |
9f95a23c | 2223 | FMT_CONSTEXPR void on_text(const char*, const char*) {} |
11fdf7f2 TL |
2224 | |
2225 | FMT_CONSTEXPR void on_arg_id() {} | |
2226 | ||
9f95a23c | 2227 | template <typename T> FMT_CONSTEXPR void on_arg_id(T) {} |
11fdf7f2 | 2228 | |
9f95a23c | 2229 | FMT_CONSTEXPR void on_replacement_field(const char*) {} |
11fdf7f2 | 2230 | |
9f95a23c TL |
2231 | FMT_CONSTEXPR const char* on_format_specs(const char* begin, const char*) { |
2232 | return begin; | |
2233 | } | |
11fdf7f2 | 2234 | |
9f95a23c | 2235 | FMT_CONSTEXPR void on_error(const char*) { error = true; } |
11fdf7f2 TL |
2236 | |
2237 | bool error = false; | |
2238 | }; | |
2239 | ||
9f95a23c | 2240 | template <size_t N> FMT_CONSTEXPR bool parse_string(const char (&s)[N]) { |
11fdf7f2 | 2241 | test_format_string_handler h; |
f67539c2 | 2242 | fmt::detail::parse_format_string<true>(fmt::string_view(s, N - 1), h); |
11fdf7f2 TL |
2243 | return !h.error; |
2244 | } | |
2245 | ||
2246 | TEST(FormatTest, ConstexprParseFormatString) { | |
2247 | static_assert(parse_string("foo"), ""); | |
2248 | static_assert(!parse_string("}"), ""); | |
2249 | static_assert(parse_string("{}"), ""); | |
2250 | static_assert(parse_string("{42}"), ""); | |
2251 | static_assert(parse_string("{foo}"), ""); | |
2252 | static_assert(parse_string("{:}"), ""); | |
2253 | } | |
2254 | ||
2255 | struct test_error_handler { | |
9f95a23c | 2256 | const char*& error; |
11fdf7f2 | 2257 | |
9f95a23c | 2258 | FMT_CONSTEXPR test_error_handler(const char*& err) : error(err) {} |
11fdf7f2 | 2259 | |
9f95a23c TL |
2260 | FMT_CONSTEXPR test_error_handler(const test_error_handler& other) |
2261 | : error(other.error) {} | |
11fdf7f2 | 2262 | |
9f95a23c TL |
2263 | FMT_CONSTEXPR void on_error(const char* message) { |
2264 | if (!error) error = message; | |
11fdf7f2 TL |
2265 | } |
2266 | }; | |
2267 | ||
9f95a23c | 2268 | FMT_CONSTEXPR size_t len(const char* s) { |
11fdf7f2 | 2269 | size_t len = 0; |
9f95a23c | 2270 | while (*s++) ++len; |
11fdf7f2 TL |
2271 | return len; |
2272 | } | |
2273 | ||
9f95a23c TL |
2274 | FMT_CONSTEXPR bool equal(const char* s1, const char* s2) { |
2275 | if (!s1 || !s2) return s1 == s2; | |
11fdf7f2 TL |
2276 | while (*s1 && *s1 == *s2) { |
2277 | ++s1; | |
2278 | ++s2; | |
2279 | } | |
2280 | return *s1 == *s2; | |
2281 | } | |
2282 | ||
2283 | template <typename... Args> | |
9f95a23c | 2284 | FMT_CONSTEXPR bool test_error(const char* fmt, const char* expected_error) { |
f67539c2 TL |
2285 | const char* actual_error = nullptr; |
2286 | string_view s(fmt, len(fmt)); | |
2287 | fmt::detail::format_string_checker<char, test_error_handler, Args...> checker( | |
2288 | s, test_error_handler(actual_error)); | |
2289 | fmt::detail::parse_format_string<true>(s, checker); | |
11fdf7f2 TL |
2290 | return equal(actual_error, expected_error); |
2291 | } | |
2292 | ||
9f95a23c TL |
2293 | # define EXPECT_ERROR_NOARGS(fmt, error) \ |
2294 | static_assert(test_error(fmt, error), "") | |
2295 | # define EXPECT_ERROR(fmt, error, ...) \ | |
2296 | static_assert(test_error<__VA_ARGS__>(fmt, error), "") | |
11fdf7f2 TL |
2297 | |
2298 | TEST(FormatTest, FormatStringErrors) { | |
f67539c2 | 2299 | EXPECT_ERROR_NOARGS("foo", nullptr); |
11fdf7f2 TL |
2300 | EXPECT_ERROR_NOARGS("}", "unmatched '}' in format string"); |
2301 | EXPECT_ERROR("{0:s", "unknown format specifier", Date); | |
f67539c2 TL |
2302 | # if !FMT_MSC_VER || FMT_MSC_VER >= 1916 |
2303 | // This causes an detail compiler error in MSVC2017. | |
11fdf7f2 TL |
2304 | EXPECT_ERROR("{:{<}", "invalid fill character '{'", int); |
2305 | EXPECT_ERROR("{:10000000000}", "number is too big", int); | |
2306 | EXPECT_ERROR("{:.10000000000}", "number is too big", int); | |
f67539c2 TL |
2307 | EXPECT_ERROR_NOARGS("{:x}", "argument not found"); |
2308 | # if FMT_NUMERIC_ALIGN | |
2309 | EXPECT_ERROR("{0:=5", "unknown format specifier", int); | |
11fdf7f2 | 2310 | EXPECT_ERROR("{:=}", "format specifier requires numeric argument", |
9f95a23c | 2311 | const char*); |
f67539c2 | 2312 | # endif |
11fdf7f2 | 2313 | EXPECT_ERROR("{:+}", "format specifier requires numeric argument", |
9f95a23c | 2314 | const char*); |
11fdf7f2 | 2315 | EXPECT_ERROR("{:-}", "format specifier requires numeric argument", |
9f95a23c | 2316 | const char*); |
11fdf7f2 | 2317 | EXPECT_ERROR("{:#}", "format specifier requires numeric argument", |
9f95a23c | 2318 | const char*); |
11fdf7f2 | 2319 | EXPECT_ERROR("{: }", "format specifier requires numeric argument", |
9f95a23c | 2320 | const char*); |
11fdf7f2 | 2321 | EXPECT_ERROR("{:0}", "format specifier requires numeric argument", |
9f95a23c | 2322 | const char*); |
11fdf7f2 TL |
2323 | EXPECT_ERROR("{:+}", "format specifier requires signed argument", unsigned); |
2324 | EXPECT_ERROR("{:-}", "format specifier requires signed argument", unsigned); | |
2325 | EXPECT_ERROR("{: }", "format specifier requires signed argument", unsigned); | |
f67539c2 TL |
2326 | EXPECT_ERROR("{:{}}", "argument not found", int); |
2327 | EXPECT_ERROR("{:.{}}", "argument not found", double); | |
11fdf7f2 TL |
2328 | EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int); |
2329 | EXPECT_ERROR("{:s}", "invalid type specifier", int); | |
2330 | EXPECT_ERROR("{:s}", "invalid type specifier", bool); | |
2331 | EXPECT_ERROR("{:s}", "invalid type specifier", char); | |
2332 | EXPECT_ERROR("{:+}", "invalid format specifier for char", char); | |
2333 | EXPECT_ERROR("{:s}", "invalid type specifier", double); | |
9f95a23c | 2334 | EXPECT_ERROR("{:d}", "invalid type specifier", const char*); |
11fdf7f2 | 2335 | EXPECT_ERROR("{:d}", "invalid type specifier", std::string); |
9f95a23c | 2336 | EXPECT_ERROR("{:s}", "invalid type specifier", void*); |
f67539c2 TL |
2337 | # else |
2338 | fmt::print("warning: constexpr is broken in this version of MSVC\n"); | |
9f95a23c TL |
2339 | # endif |
2340 | EXPECT_ERROR("{foo", "compile-time checks don't support named arguments", | |
2341 | int); | |
11fdf7f2 TL |
2342 | EXPECT_ERROR_NOARGS("{10000000000}", "number is too big"); |
2343 | EXPECT_ERROR_NOARGS("{0x}", "invalid format string"); | |
2344 | EXPECT_ERROR_NOARGS("{-}", "invalid format string"); | |
2345 | EXPECT_ERROR("{:{0x}}", "invalid format string", int); | |
2346 | EXPECT_ERROR("{:{-}}", "invalid format string", int); | |
2347 | EXPECT_ERROR("{:.{0x}}", "invalid format string", int); | |
2348 | EXPECT_ERROR("{:.{-}}", "invalid format string", int); | |
2349 | EXPECT_ERROR("{:.x}", "missing precision specifier", int); | |
f67539c2 TL |
2350 | EXPECT_ERROR_NOARGS("{}", "argument not found"); |
2351 | EXPECT_ERROR("{1}", "argument not found", int); | |
11fdf7f2 | 2352 | EXPECT_ERROR("{1}{}", |
9f95a23c TL |
2353 | "cannot switch from manual to automatic argument indexing", int, |
2354 | int); | |
11fdf7f2 | 2355 | EXPECT_ERROR("{}{1}", |
9f95a23c TL |
2356 | "cannot switch from automatic to manual argument indexing", int, |
2357 | int); | |
11fdf7f2 | 2358 | } |
eafe8130 TL |
2359 | |
2360 | TEST(FormatTest, VFormatTo) { | |
2361 | typedef fmt::format_context context; | |
f67539c2 | 2362 | fmt::basic_format_arg<context> arg = fmt::detail::make_arg<context>(42); |
eafe8130 TL |
2363 | fmt::basic_format_args<context> args(&arg, 1); |
2364 | std::string s; | |
2365 | fmt::vformat_to(std::back_inserter(s), "{}", args); | |
2366 | EXPECT_EQ("42", s); | |
2367 | s.clear(); | |
2368 | fmt::vformat_to(std::back_inserter(s), FMT_STRING("{}"), args); | |
2369 | EXPECT_EQ("42", s); | |
2370 | ||
2371 | typedef fmt::wformat_context wcontext; | |
f67539c2 | 2372 | fmt::basic_format_arg<wcontext> warg = fmt::detail::make_arg<wcontext>(42); |
eafe8130 TL |
2373 | fmt::basic_format_args<wcontext> wargs(&warg, 1); |
2374 | std::wstring w; | |
2375 | fmt::vformat_to(std::back_inserter(w), L"{}", wargs); | |
2376 | EXPECT_EQ(L"42", w); | |
2377 | w.clear(); | |
2378 | fmt::vformat_to(std::back_inserter(w), FMT_STRING(L"{}"), wargs); | |
2379 | EXPECT_EQ(L"42", w); | |
2380 | } | |
2381 | ||
9f95a23c TL |
2382 | template <typename T> static std::string FmtToString(const T& t) { |
2383 | return fmt::format(FMT_STRING("{}"), t); | |
2384 | } | |
2385 | ||
2386 | TEST(FormatTest, FmtStringInTemplate) { | |
2387 | EXPECT_EQ(FmtToString(1), "1"); | |
2388 | EXPECT_EQ(FmtToString(0), "0"); | |
2389 | } | |
2390 | ||
11fdf7f2 TL |
2391 | #endif // FMT_USE_CONSTEXPR |
2392 | ||
f67539c2 TL |
2393 | TEST(FormatTest, EmphasisNonHeaderOnly) { |
2394 | // Ensure this compiles even if FMT_HEADER_ONLY is not defined. | |
2395 | EXPECT_EQ(fmt::format(fmt::emphasis::bold, "bold error"), | |
2396 | "\x1b[1mbold error\x1b[0m"); | |
11fdf7f2 TL |
2397 | } |
2398 | ||
f67539c2 TL |
2399 | TEST(FormatTest, CharTraitsIsNotAmbiguous) { |
2400 | // Test that we don't inject detail names into the std namespace. | |
2401 | using namespace std; | |
2402 | char_traits<char>::char_type c; | |
2403 | (void)c; | |
2404 | #if __cplusplus >= 201103L | |
2405 | std::string s; | |
2406 | auto lval = begin(s); | |
2407 | (void)lval; | |
2408 | #endif | |
11fdf7f2 TL |
2409 | } |
2410 | ||
f67539c2 TL |
2411 | struct mychar { |
2412 | int value; | |
2413 | mychar() = default; | |
2414 | ||
2415 | template <typename T> mychar(T val) : value(static_cast<int>(val)) {} | |
2416 | ||
2417 | operator int() const { return value; } | |
2418 | }; | |
2419 | ||
2420 | FMT_BEGIN_NAMESPACE | |
2421 | template <> struct is_char<mychar> : std::true_type {}; | |
2422 | FMT_END_NAMESPACE | |
2423 | ||
2424 | TEST(FormatTest, FormatCustomChar) { | |
2425 | const mychar format[] = {'{', '}', 0}; | |
2426 | auto result = fmt::format(format, mychar('x')); | |
2427 | EXPECT_EQ(result.size(), 1); | |
2428 | EXPECT_EQ(result[0], mychar('x')); | |
11fdf7f2 | 2429 | } |
eafe8130 | 2430 | |
f67539c2 TL |
2431 | // Convert a char8_t string to std::string. Otherwise GTest will insist on |
2432 | // inserting `char8_t` NTBS into a `char` stream which is disabled by P1423. | |
2433 | template <typename S> std::string from_u8str(const S& str) { | |
2434 | return std::string(str.begin(), str.end()); | |
eafe8130 | 2435 | } |
9f95a23c | 2436 | |
f67539c2 TL |
2437 | TEST(FormatTest, FormatUTF8Precision) { |
2438 | using str_type = std::basic_string<fmt::detail::char8_type>; | |
2439 | str_type format(reinterpret_cast<const fmt::detail::char8_type*>(u8"{:.4}")); | |
2440 | str_type str(reinterpret_cast<const fmt::detail::char8_type*>( | |
2441 | u8"caf\u00e9s")); // cafés | |
2442 | auto result = fmt::format(format, str); | |
2443 | EXPECT_EQ(fmt::detail::count_code_points(result), 4); | |
2444 | EXPECT_EQ(result.size(), 5); | |
2445 | EXPECT_EQ(from_u8str(result), from_u8str(str.substr(0, 5))); | |
9f95a23c | 2446 | } |