]>
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 | ||
11fdf7f2 TL |
8 | // Check if fmt/format.h compiles with windows.h included before it. |
9 | #ifdef _WIN32 | |
9f95a23c | 10 | # include <windows.h> |
11fdf7f2 | 11 | #endif |
20effc67 | 12 | // clang-format off |
f67539c2 | 13 | #include "fmt/format.h" |
20effc67 | 14 | // clang-format on |
f67539c2 | 15 | |
20effc67 TL |
16 | #include <stdint.h> // uint32_t |
17 | ||
18 | #include <climits> // INT_MAX | |
19 | #include <cmath> // std::signbit | |
20 | #include <cstring> // std::strlen | |
21 | #include <iterator> // std::back_inserter | |
22 | #include <list> // std::list | |
23 | #include <memory> // std::unique_ptr | |
24 | #include <type_traits> // std::is_default_constructible | |
f67539c2 | 25 | |
11fdf7f2 TL |
26 | #include "gtest-extra.h" |
27 | #include "mock-allocator.h" | |
28 | #include "util.h" | |
29 | ||
11fdf7f2 | 30 | using fmt::basic_memory_buffer; |
11fdf7f2 | 31 | using fmt::format_error; |
11fdf7f2 | 32 | using fmt::memory_buffer; |
20effc67 | 33 | using fmt::runtime; |
9f95a23c | 34 | using fmt::string_view; |
f67539c2 | 35 | using fmt::detail::max_value; |
11fdf7f2 TL |
36 | |
37 | using testing::Return; | |
38 | using testing::StrictMock; | |
39 | ||
20effc67 | 40 | enum { buffer_size = 256 }; |
11fdf7f2 | 41 | |
11fdf7f2 TL |
42 | struct uint32_pair { |
43 | uint32_t u[2]; | |
44 | }; | |
45 | ||
20effc67 | 46 | TEST(util_test, bit_cast) { |
f67539c2 TL |
47 | auto s = fmt::detail::bit_cast<uint32_pair>(uint64_t{42}); |
48 | EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), 42ull); | |
20effc67 | 49 | s = fmt::detail::bit_cast<uint32_pair>(~uint64_t{0}); |
f67539c2 | 50 | EXPECT_EQ(fmt::detail::bit_cast<uint64_t>(s), ~0ull); |
11fdf7f2 TL |
51 | } |
52 | ||
20effc67 TL |
53 | // Increment a number in a string. |
54 | void increment(char* s) { | |
55 | for (int i = static_cast<int>(std::strlen(s)) - 1; i >= 0; --i) { | |
56 | if (s[i] != '9') { | |
57 | ++s[i]; | |
58 | break; | |
59 | } | |
60 | s[i] = '0'; | |
61 | } | |
62 | } | |
63 | ||
64 | TEST(util_test, increment) { | |
11fdf7f2 TL |
65 | char s[10] = "123"; |
66 | increment(s); | |
67 | EXPECT_STREQ("124", s); | |
68 | s[2] = '8'; | |
69 | increment(s); | |
70 | EXPECT_STREQ("129", s); | |
71 | increment(s); | |
72 | EXPECT_STREQ("130", s); | |
73 | s[1] = s[2] = '9'; | |
74 | increment(s); | |
75 | EXPECT_STREQ("200", s); | |
76 | } | |
77 | ||
20effc67 TL |
78 | TEST(util_test, parse_nonnegative_int) { |
79 | auto s = fmt::string_view("10000000000"); | |
9f95a23c | 80 | auto begin = s.begin(), end = s.end(); |
20effc67 | 81 | EXPECT_EQ(fmt::detail::parse_nonnegative_int(begin, end, -1), -1); |
11fdf7f2 | 82 | s = "2147483649"; |
9f95a23c TL |
83 | begin = s.begin(); |
84 | end = s.end(); | |
20effc67 | 85 | EXPECT_EQ(fmt::detail::parse_nonnegative_int(begin, end, -1), -1); |
11fdf7f2 TL |
86 | } |
87 | ||
20effc67 TL |
88 | TEST(util_test, utf8_to_utf16) { |
89 | auto u = fmt::detail::utf8_to_utf16("лошадка"); | |
90 | EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str()); | |
91 | EXPECT_EQ(7, u.size()); | |
92 | // U+10437 { DESERET SMALL LETTER YEE } | |
93 | EXPECT_EQ(L"\xD801\xDC37", fmt::detail::utf8_to_utf16("𐐷").str()); | |
94 | EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16("\xc3\x28"), std::runtime_error, | |
95 | "invalid utf8"); | |
96 | EXPECT_THROW_MSG(fmt::detail::utf8_to_utf16(fmt::string_view("л", 1)), | |
97 | std::runtime_error, "invalid utf8"); | |
98 | EXPECT_EQ(L"123456", fmt::detail::utf8_to_utf16("123456").str()); | |
11fdf7f2 TL |
99 | } |
100 | ||
20effc67 TL |
101 | TEST(util_test, utf8_to_utf16_empty_string) { |
102 | auto s = std::string(); | |
103 | auto u = fmt::detail::utf8_to_utf16(s.c_str()); | |
104 | EXPECT_EQ(L"", u.str()); | |
105 | EXPECT_EQ(s.size(), u.size()); | |
106 | } | |
107 | ||
108 | TEST(util_test, allocator_ref) { | |
109 | using test_allocator_ref = allocator_ref<mock_allocator<int>>; | |
110 | auto check_forwarding = [](mock_allocator<int>& alloc, | |
111 | test_allocator_ref& ref) { | |
112 | int mem; | |
113 | // Check if value_type is properly defined. | |
114 | allocator_ref<mock_allocator<int>>::value_type* ptr = &mem; | |
115 | // Check forwarding. | |
116 | EXPECT_CALL(alloc, allocate(42)).WillOnce(Return(ptr)); | |
117 | ref.allocate(42); | |
118 | EXPECT_CALL(alloc, deallocate(ptr, 42)); | |
119 | ref.deallocate(ptr, 42); | |
120 | }; | |
121 | ||
9f95a23c | 122 | StrictMock<mock_allocator<int>> alloc; |
20effc67 | 123 | auto ref = test_allocator_ref(&alloc); |
11fdf7f2 TL |
124 | // Check if allocator_ref forwards to the underlying allocator. |
125 | check_forwarding(alloc, ref); | |
126 | test_allocator_ref ref2(ref); | |
127 | check_forwarding(alloc, ref2); | |
128 | test_allocator_ref ref3; | |
f67539c2 | 129 | EXPECT_EQ(nullptr, ref3.get()); |
11fdf7f2 TL |
130 | ref3 = ref; |
131 | check_forwarding(alloc, ref3); | |
132 | } | |
133 | ||
20effc67 TL |
134 | TEST(util_test, format_system_error) { |
135 | fmt::memory_buffer message; | |
136 | fmt::format_system_error(message, EDOM, "test"); | |
137 | auto ec = std::error_code(EDOM, std::generic_category()); | |
138 | EXPECT_EQ(to_string(message), std::system_error(ec, "test").what()); | |
139 | message = fmt::memory_buffer(); | |
11fdf7f2 | 140 | |
20effc67 TL |
141 | // Check if std::allocator throws on allocating max size_t / 2 chars. |
142 | size_t max_size = max_value<size_t>() / 2; | |
143 | bool throws_on_alloc = false; | |
144 | try { | |
145 | auto alloc = std::allocator<char>(); | |
146 | alloc.deallocate(alloc.allocate(max_size), max_size); | |
147 | } catch (const std::bad_alloc&) { | |
148 | throws_on_alloc = true; | |
149 | } | |
150 | if (!throws_on_alloc) { | |
151 | fmt::print("warning: std::allocator allocates {} chars", max_size); | |
152 | return; | |
153 | } | |
154 | } | |
155 | ||
156 | TEST(util_test, system_error) { | |
157 | auto test_error = fmt::system_error(EDOM, "test"); | |
158 | auto ec = std::error_code(EDOM, std::generic_category()); | |
159 | EXPECT_STREQ(test_error.what(), std::system_error(ec, "test").what()); | |
160 | EXPECT_EQ(test_error.code(), ec); | |
161 | ||
162 | auto error = std::system_error(std::error_code()); | |
163 | try { | |
164 | throw fmt::system_error(EDOM, "test {}", "error"); | |
165 | } catch (const std::system_error& e) { | |
166 | error = e; | |
167 | } | |
168 | fmt::memory_buffer message; | |
169 | fmt::format_system_error(message, EDOM, "test error"); | |
170 | EXPECT_EQ(error.what(), to_string(message)); | |
171 | EXPECT_EQ(error.code(), std::error_code(EDOM, std::generic_category())); | |
11fdf7f2 TL |
172 | } |
173 | ||
20effc67 TL |
174 | TEST(util_test, report_system_error) { |
175 | fmt::memory_buffer out; | |
176 | fmt::format_system_error(out, EDOM, "test error"); | |
177 | out.push_back('\n'); | |
178 | EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"), | |
179 | to_string(out)); | |
180 | } | |
181 | ||
182 | TEST(memory_buffer_test, ctor) { | |
183 | basic_memory_buffer<char, 123> buffer; | |
184 | EXPECT_EQ(static_cast<size_t>(0), buffer.size()); | |
185 | EXPECT_EQ(123u, buffer.capacity()); | |
186 | } | |
187 | ||
188 | using std_allocator = allocator_ref<std::allocator<char>>; | |
189 | ||
190 | TEST(memory_buffer_test, move_ctor_inline_buffer) { | |
191 | auto check_move_buffer = | |
192 | [](const char* str, basic_memory_buffer<char, 5, std_allocator>& buffer) { | |
193 | std::allocator<char>* alloc = buffer.get_allocator().get(); | |
194 | basic_memory_buffer<char, 5, std_allocator> buffer2(std::move(buffer)); | |
195 | // Move shouldn't destroy the inline content of the first buffer. | |
196 | EXPECT_EQ(str, std::string(&buffer[0], buffer.size())); | |
197 | EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size())); | |
198 | EXPECT_EQ(5u, buffer2.capacity()); | |
199 | // Move should transfer allocator. | |
200 | EXPECT_EQ(nullptr, buffer.get_allocator().get()); | |
201 | EXPECT_EQ(alloc, buffer2.get_allocator().get()); | |
202 | }; | |
203 | ||
204 | auto alloc = std::allocator<char>(); | |
205 | basic_memory_buffer<char, 5, std_allocator> buffer((std_allocator(&alloc))); | |
11fdf7f2 | 206 | const char test[] = "test"; |
20effc67 | 207 | buffer.append(string_view(test, 4)); |
11fdf7f2 TL |
208 | check_move_buffer("test", buffer); |
209 | // Adding one more character fills the inline buffer, but doesn't cause | |
210 | // dynamic allocation. | |
211 | buffer.push_back('a'); | |
212 | check_move_buffer("testa", buffer); | |
f67539c2 TL |
213 | } |
214 | ||
20effc67 TL |
215 | TEST(memory_buffer_test, move_ctor_dynamic_buffer) { |
216 | auto alloc = std::allocator<char>(); | |
217 | basic_memory_buffer<char, 4, std_allocator> buffer((std_allocator(&alloc))); | |
f67539c2 TL |
218 | const char test[] = "test"; |
219 | buffer.append(test, test + 4); | |
9f95a23c | 220 | const char* inline_buffer_ptr = &buffer[0]; |
11fdf7f2 TL |
221 | // Adding one more character causes the content to move from the inline to |
222 | // a dynamically allocated buffer. | |
f67539c2 | 223 | buffer.push_back('a'); |
20effc67 | 224 | basic_memory_buffer<char, 4, std_allocator> buffer2(std::move(buffer)); |
11fdf7f2 TL |
225 | // Move should rip the guts of the first buffer. |
226 | EXPECT_EQ(inline_buffer_ptr, &buffer[0]); | |
f67539c2 TL |
227 | EXPECT_EQ("testa", std::string(&buffer2[0], buffer2.size())); |
228 | EXPECT_GT(buffer2.capacity(), 4u); | |
11fdf7f2 TL |
229 | } |
230 | ||
20effc67 TL |
231 | void check_move_assign_buffer(const char* str, |
232 | basic_memory_buffer<char, 5>& buffer) { | |
11fdf7f2 TL |
233 | basic_memory_buffer<char, 5> buffer2; |
234 | buffer2 = std::move(buffer); | |
235 | // Move shouldn't destroy the inline content of the first buffer. | |
236 | EXPECT_EQ(str, std::string(&buffer[0], buffer.size())); | |
237 | EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size())); | |
238 | EXPECT_EQ(5u, buffer2.capacity()); | |
239 | } | |
240 | ||
20effc67 | 241 | TEST(memory_buffer_test, move_assignment) { |
11fdf7f2 TL |
242 | basic_memory_buffer<char, 5> buffer; |
243 | const char test[] = "test"; | |
244 | buffer.append(test, test + 4); | |
245 | check_move_assign_buffer("test", buffer); | |
246 | // Adding one more character fills the inline buffer, but doesn't cause | |
247 | // dynamic allocation. | |
248 | buffer.push_back('a'); | |
249 | check_move_assign_buffer("testa", buffer); | |
9f95a23c | 250 | const char* inline_buffer_ptr = &buffer[0]; |
11fdf7f2 TL |
251 | // Adding one more character causes the content to move from the inline to |
252 | // a dynamically allocated buffer. | |
253 | buffer.push_back('b'); | |
254 | basic_memory_buffer<char, 5> buffer2; | |
255 | buffer2 = std::move(buffer); | |
256 | // Move should rip the guts of the first buffer. | |
257 | EXPECT_EQ(inline_buffer_ptr, &buffer[0]); | |
258 | EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size())); | |
259 | EXPECT_GT(buffer2.capacity(), 5u); | |
260 | } | |
261 | ||
20effc67 | 262 | TEST(memory_buffer_test, grow) { |
9f95a23c | 263 | typedef allocator_ref<mock_allocator<int>> Allocator; |
11fdf7f2 | 264 | mock_allocator<int> alloc; |
20effc67 | 265 | basic_memory_buffer<int, 10, Allocator> buffer((Allocator(&alloc))); |
11fdf7f2 | 266 | buffer.resize(7); |
f67539c2 | 267 | using fmt::detail::to_unsigned; |
9f95a23c | 268 | for (int i = 0; i < 7; ++i) buffer[to_unsigned(i)] = i * i; |
11fdf7f2 TL |
269 | EXPECT_EQ(10u, buffer.capacity()); |
270 | int mem[20]; | |
271 | mem[7] = 0xdead; | |
272 | EXPECT_CALL(alloc, allocate(20)).WillOnce(Return(mem)); | |
20effc67 | 273 | buffer.try_reserve(20); |
11fdf7f2 TL |
274 | EXPECT_EQ(20u, buffer.capacity()); |
275 | // Check if size elements have been copied | |
9f95a23c | 276 | for (int i = 0; i < 7; ++i) EXPECT_EQ(i * i, buffer[to_unsigned(i)]); |
11fdf7f2 TL |
277 | // and no more than that. |
278 | EXPECT_EQ(0xdead, buffer[7]); | |
279 | EXPECT_CALL(alloc, deallocate(mem, 20)); | |
280 | } | |
281 | ||
20effc67 TL |
282 | TEST(memory_buffer_test, allocator) { |
283 | using test_allocator = allocator_ref<mock_allocator<char>>; | |
284 | basic_memory_buffer<char, 10, test_allocator> buffer; | |
f67539c2 | 285 | EXPECT_EQ(nullptr, buffer.get_allocator().get()); |
9f95a23c | 286 | StrictMock<mock_allocator<char>> alloc; |
11fdf7f2 TL |
287 | char mem; |
288 | { | |
20effc67 TL |
289 | basic_memory_buffer<char, 10, test_allocator> buffer2( |
290 | (test_allocator(&alloc))); | |
11fdf7f2 | 291 | EXPECT_EQ(&alloc, buffer2.get_allocator().get()); |
f67539c2 | 292 | size_t size = 2 * fmt::inline_buffer_size; |
11fdf7f2 TL |
293 | EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem)); |
294 | buffer2.reserve(size); | |
295 | EXPECT_CALL(alloc, deallocate(&mem, size)); | |
296 | } | |
297 | } | |
298 | ||
20effc67 TL |
299 | TEST(memory_buffer_test, exception_in_deallocate) { |
300 | using test_allocator = allocator_ref<mock_allocator<char>>; | |
9f95a23c | 301 | StrictMock<mock_allocator<char>> alloc; |
20effc67 TL |
302 | basic_memory_buffer<char, 10, test_allocator> buffer( |
303 | (test_allocator(&alloc))); | |
f67539c2 | 304 | size_t size = 2 * fmt::inline_buffer_size; |
20effc67 | 305 | auto mem = std::vector<char>(size); |
11fdf7f2 TL |
306 | { |
307 | EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0])); | |
308 | buffer.resize(size); | |
309 | std::fill(&buffer[0], &buffer[0] + size, 'x'); | |
310 | } | |
20effc67 | 311 | auto mem2 = std::vector<char>(2 * size); |
11fdf7f2 TL |
312 | { |
313 | EXPECT_CALL(alloc, allocate(2 * size)).WillOnce(Return(&mem2[0])); | |
20effc67 | 314 | auto e = std::exception(); |
11fdf7f2 TL |
315 | EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e)); |
316 | EXPECT_THROW(buffer.reserve(2 * size), std::exception); | |
317 | EXPECT_EQ(&mem2[0], &buffer[0]); | |
318 | // Check that the data has been copied. | |
f67539c2 | 319 | for (size_t i = 0; i < size; ++i) EXPECT_EQ('x', buffer[i]); |
11fdf7f2 TL |
320 | } |
321 | EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size)); | |
322 | } | |
323 | ||
20effc67 TL |
324 | template <typename Allocator, size_t MaxSize> |
325 | class max_size_allocator : public Allocator { | |
326 | public: | |
327 | using typename Allocator::value_type; | |
328 | size_t max_size() const FMT_NOEXCEPT { return MaxSize; } | |
329 | value_type* allocate(size_t n) { | |
330 | if (n > max_size()) { | |
331 | throw std::length_error("size > max_size"); | |
332 | } | |
333 | return std::allocator_traits<Allocator>::allocate( | |
334 | *static_cast<Allocator*>(this), n); | |
11fdf7f2 | 335 | } |
20effc67 TL |
336 | void deallocate(value_type* p, size_t n) { |
337 | std::allocator_traits<Allocator>::deallocate(*static_cast<Allocator*>(this), | |
338 | p, n); | |
f67539c2 | 339 | } |
20effc67 | 340 | }; |
11fdf7f2 | 341 | |
20effc67 TL |
342 | TEST(memory_buffer_test, max_size_allocator) { |
343 | // 160 = 128 + 32 | |
344 | using test_allocator = max_size_allocator<std::allocator<char>, 160>; | |
345 | basic_memory_buffer<char, 10, test_allocator> buffer; | |
346 | buffer.resize(128); | |
347 | // new_capacity = 128 + 128/2 = 192 > 160 | |
348 | buffer.resize(160); // Shouldn't throw. | |
eafe8130 TL |
349 | } |
350 | ||
20effc67 TL |
351 | TEST(memory_buffer_test, max_size_allocator_overflow) { |
352 | using test_allocator = max_size_allocator<std::allocator<char>, 160>; | |
353 | basic_memory_buffer<char, 10, test_allocator> buffer; | |
354 | EXPECT_THROW(buffer.resize(161), std::exception); | |
11fdf7f2 TL |
355 | } |
356 | ||
20effc67 TL |
357 | TEST(format_test, escape) { |
358 | EXPECT_EQ("{", fmt::format("{{")); | |
359 | EXPECT_EQ("before {", fmt::format("before {{")); | |
360 | EXPECT_EQ("{ after", fmt::format("{{ after")); | |
361 | EXPECT_EQ("before { after", fmt::format("before {{ after")); | |
11fdf7f2 | 362 | |
20effc67 TL |
363 | EXPECT_EQ("}", fmt::format("}}")); |
364 | EXPECT_EQ("before }", fmt::format("before }}")); | |
365 | EXPECT_EQ("} after", fmt::format("}} after")); | |
366 | EXPECT_EQ("before } after", fmt::format("before }} after")); | |
11fdf7f2 | 367 | |
20effc67 TL |
368 | EXPECT_EQ("{}", fmt::format("{{}}")); |
369 | EXPECT_EQ("{42}", fmt::format("{{{0}}}", 42)); | |
11fdf7f2 TL |
370 | } |
371 | ||
20effc67 TL |
372 | TEST(format_test, unmatched_braces) { |
373 | EXPECT_THROW_MSG(fmt::format(runtime("{")), format_error, | |
374 | "invalid format string"); | |
375 | EXPECT_THROW_MSG(fmt::format(runtime("}")), format_error, | |
376 | "unmatched '}' in format string"); | |
377 | EXPECT_THROW_MSG(fmt::format(runtime("{0{}")), format_error, | |
378 | "invalid format string"); | |
11fdf7f2 TL |
379 | } |
380 | ||
20effc67 | 381 | TEST(format_test, no_args) { EXPECT_EQ("test", fmt::format("test")); } |
11fdf7f2 | 382 | |
20effc67 TL |
383 | TEST(format_test, args_in_different_positions) { |
384 | EXPECT_EQ("42", fmt::format("{0}", 42)); | |
385 | EXPECT_EQ("before 42", fmt::format("before {0}", 42)); | |
386 | EXPECT_EQ("42 after", fmt::format("{0} after", 42)); | |
387 | EXPECT_EQ("before 42 after", fmt::format("before {0} after", 42)); | |
388 | EXPECT_EQ("answer = 42", fmt::format("{0} = {1}", "answer", 42)); | |
389 | EXPECT_EQ("42 is the answer", fmt::format("{1} is the {0}", "answer", 42)); | |
390 | EXPECT_EQ("abracadabra", fmt::format("{0}{1}{0}", "abra", "cad")); | |
11fdf7f2 TL |
391 | } |
392 | ||
20effc67 TL |
393 | TEST(format_test, arg_errors) { |
394 | EXPECT_THROW_MSG(fmt::format(runtime("{")), format_error, | |
395 | "invalid format string"); | |
396 | EXPECT_THROW_MSG(fmt::format(runtime("{?}")), format_error, | |
397 | "invalid format string"); | |
398 | EXPECT_THROW_MSG(fmt::format(runtime("{0")), format_error, | |
399 | "invalid format string"); | |
400 | EXPECT_THROW_MSG(fmt::format(runtime("{0}")), format_error, | |
401 | "argument not found"); | |
402 | EXPECT_THROW_MSG(fmt::format(runtime("{00}"), 42), format_error, | |
403 | "invalid format string"); | |
11fdf7f2 | 404 | |
20effc67 | 405 | char format_str[buffer_size]; |
11fdf7f2 | 406 | safe_sprintf(format_str, "{%u", INT_MAX); |
20effc67 TL |
407 | EXPECT_THROW_MSG(fmt::format(runtime(format_str)), format_error, |
408 | "invalid format string"); | |
11fdf7f2 | 409 | safe_sprintf(format_str, "{%u}", INT_MAX); |
20effc67 TL |
410 | EXPECT_THROW_MSG(fmt::format(runtime(format_str)), format_error, |
411 | "argument not found"); | |
11fdf7f2 TL |
412 | |
413 | safe_sprintf(format_str, "{%u", INT_MAX + 1u); | |
20effc67 TL |
414 | EXPECT_THROW_MSG(fmt::format(runtime(format_str)), format_error, |
415 | "invalid format string"); | |
11fdf7f2 | 416 | safe_sprintf(format_str, "{%u}", INT_MAX + 1u); |
20effc67 TL |
417 | EXPECT_THROW_MSG(fmt::format(runtime(format_str)), format_error, |
418 | "argument not found"); | |
11fdf7f2 TL |
419 | } |
420 | ||
20effc67 TL |
421 | template <int N> struct test_format { |
422 | template <typename... T> | |
423 | static std::string format(fmt::string_view fmt, const T&... args) { | |
424 | return test_format<N - 1>::format(fmt, N - 1, args...); | |
11fdf7f2 TL |
425 | } |
426 | }; | |
427 | ||
20effc67 TL |
428 | template <> struct test_format<0> { |
429 | template <typename... T> | |
430 | static std::string format(fmt::string_view fmt, const T&... args) { | |
431 | return fmt::format(runtime(fmt), args...); | |
11fdf7f2 TL |
432 | } |
433 | }; | |
434 | ||
20effc67 TL |
435 | TEST(format_test, many_args) { |
436 | EXPECT_EQ("19", test_format<20>::format("{19}")); | |
437 | EXPECT_THROW_MSG(test_format<20>::format("{20}"), format_error, | |
f67539c2 | 438 | "argument not found"); |
20effc67 | 439 | EXPECT_THROW_MSG(test_format<21>::format("{21}"), format_error, |
f67539c2 | 440 | "argument not found"); |
20effc67 | 441 | using fmt::detail::max_packed_args; |
11fdf7f2 | 442 | std::string format_str = fmt::format("{{{}}}", max_packed_args + 1); |
20effc67 | 443 | EXPECT_THROW_MSG(test_format<max_packed_args>::format(format_str), |
f67539c2 | 444 | format_error, "argument not found"); |
11fdf7f2 TL |
445 | } |
446 | ||
20effc67 TL |
447 | TEST(format_test, named_arg) { |
448 | EXPECT_EQ("1/a/A", fmt::format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'), | |
449 | fmt::arg("A_", "A"), fmt::arg("_1", 1))); | |
450 | EXPECT_EQ(" -42", fmt::format("{0:{width}}", -42, fmt::arg("width", 4))); | |
451 | EXPECT_EQ("st", | |
452 | fmt::format("{0:.{precision}}", "str", fmt::arg("precision", 2))); | |
453 | EXPECT_EQ("1 2", fmt::format("{} {two}", 1, fmt::arg("two", 2))); | |
454 | EXPECT_EQ("42", | |
455 | fmt::format("{c}", fmt::arg("a", 0), fmt::arg("b", 0), | |
456 | fmt::arg("c", 42), fmt::arg("d", 0), fmt::arg("e", 0), | |
457 | fmt::arg("f", 0), fmt::arg("g", 0), fmt::arg("h", 0), | |
458 | fmt::arg("i", 0), fmt::arg("j", 0), fmt::arg("k", 0), | |
459 | fmt::arg("l", 0), fmt::arg("m", 0), fmt::arg("n", 0), | |
460 | fmt::arg("o", 0), fmt::arg("p", 0))); | |
461 | EXPECT_THROW_MSG(fmt::format(runtime("{a}")), format_error, | |
462 | "argument not found"); | |
463 | EXPECT_THROW_MSG(fmt::format(runtime("{a}"), 42), format_error, | |
464 | "argument not found"); | |
465 | } | |
466 | ||
467 | TEST(format_test, auto_arg_index) { | |
468 | EXPECT_EQ("abc", fmt::format("{}{}{}", 'a', 'b', 'c')); | |
469 | EXPECT_THROW_MSG(fmt::format(runtime("{0}{}"), 'a', 'b'), format_error, | |
9f95a23c | 470 | "cannot switch from manual to automatic argument indexing"); |
20effc67 | 471 | EXPECT_THROW_MSG(fmt::format(runtime("{}{0}"), 'a', 'b'), format_error, |
9f95a23c | 472 | "cannot switch from automatic to manual argument indexing"); |
20effc67 TL |
473 | EXPECT_EQ("1.2", fmt::format("{:.{}}", 1.2345, 2)); |
474 | EXPECT_THROW_MSG(fmt::format(runtime("{0}:.{}"), 1.2345, 2), format_error, | |
9f95a23c | 475 | "cannot switch from manual to automatic argument indexing"); |
20effc67 | 476 | EXPECT_THROW_MSG(fmt::format(runtime("{:.{0}}"), 1.2345, 2), format_error, |
9f95a23c | 477 | "cannot switch from automatic to manual argument indexing"); |
20effc67 TL |
478 | EXPECT_THROW_MSG(fmt::format(runtime("{}")), format_error, |
479 | "argument not found"); | |
480 | } | |
11fdf7f2 | 481 | |
20effc67 TL |
482 | TEST(format_test, empty_specs) { EXPECT_EQ("42", fmt::format("{0:}", 42)); } |
483 | ||
484 | TEST(format_test, left_align) { | |
485 | EXPECT_EQ("42 ", fmt::format("{0:<4}", 42)); | |
486 | EXPECT_EQ("42 ", fmt::format("{0:<4o}", 042)); | |
487 | EXPECT_EQ("42 ", fmt::format("{0:<4x}", 0x42)); | |
488 | EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42)); | |
489 | EXPECT_EQ("42 ", fmt::format("{0:<5}", 42u)); | |
490 | EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42l)); | |
491 | EXPECT_EQ("42 ", fmt::format("{0:<5}", 42ul)); | |
492 | EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42ll)); | |
493 | EXPECT_EQ("42 ", fmt::format("{0:<5}", 42ull)); | |
494 | EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42.0)); | |
495 | EXPECT_EQ("-42 ", fmt::format("{0:<5}", -42.0l)); | |
496 | EXPECT_EQ("c ", fmt::format("{0:<5}", 'c')); | |
497 | EXPECT_EQ("abc ", fmt::format("{0:<5}", "abc")); | |
498 | EXPECT_EQ("0xface ", fmt::format("{0:<8}", reinterpret_cast<void*>(0xface))); | |
499 | } | |
500 | ||
501 | TEST(format_test, right_align) { | |
502 | EXPECT_EQ(" 42", fmt::format("{0:>4}", 42)); | |
503 | EXPECT_EQ(" 42", fmt::format("{0:>4o}", 042)); | |
504 | EXPECT_EQ(" 42", fmt::format("{0:>4x}", 0x42)); | |
505 | EXPECT_EQ(" -42", fmt::format("{0:>5}", -42)); | |
506 | EXPECT_EQ(" 42", fmt::format("{0:>5}", 42u)); | |
507 | EXPECT_EQ(" -42", fmt::format("{0:>5}", -42l)); | |
508 | EXPECT_EQ(" 42", fmt::format("{0:>5}", 42ul)); | |
509 | EXPECT_EQ(" -42", fmt::format("{0:>5}", -42ll)); | |
510 | EXPECT_EQ(" 42", fmt::format("{0:>5}", 42ull)); | |
511 | EXPECT_EQ(" -42", fmt::format("{0:>5}", -42.0)); | |
512 | EXPECT_EQ(" -42", fmt::format("{0:>5}", -42.0l)); | |
513 | EXPECT_EQ(" c", fmt::format("{0:>5}", 'c')); | |
514 | EXPECT_EQ(" abc", fmt::format("{0:>5}", "abc")); | |
515 | EXPECT_EQ(" 0xface", fmt::format("{0:>8}", reinterpret_cast<void*>(0xface))); | |
516 | } | |
517 | ||
518 | TEST(format_test, center_align) { | |
519 | EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42)); | |
520 | EXPECT_EQ(" 42 ", fmt::format("{0:^5o}", 042)); | |
521 | EXPECT_EQ(" 42 ", fmt::format("{0:^5x}", 0x42)); | |
522 | EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42)); | |
523 | EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42u)); | |
524 | EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42l)); | |
525 | EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42ul)); | |
526 | EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42ll)); | |
527 | EXPECT_EQ(" 42 ", fmt::format("{0:^5}", 42ull)); | |
528 | EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42.0)); | |
529 | EXPECT_EQ(" -42 ", fmt::format("{0:^5}", -42.0l)); | |
530 | EXPECT_EQ(" c ", fmt::format("{0:^5}", 'c')); | |
531 | EXPECT_EQ(" abc ", fmt::format("{0:^6}", "abc")); | |
532 | EXPECT_EQ(" 0xface ", fmt::format("{0:^8}", reinterpret_cast<void*>(0xface))); | |
533 | } | |
534 | ||
535 | TEST(format_test, fill) { | |
536 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{<5}"), 'c'), format_error, | |
9f95a23c | 537 | "invalid fill character '{'"); |
20effc67 | 538 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{<5}}"), 'c'), format_error, |
9f95a23c | 539 | "invalid fill character '{'"); |
20effc67 TL |
540 | EXPECT_EQ("**42", fmt::format("{0:*>4}", 42)); |
541 | EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42)); | |
542 | EXPECT_EQ("***42", fmt::format("{0:*>5}", 42u)); | |
543 | EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42l)); | |
544 | EXPECT_EQ("***42", fmt::format("{0:*>5}", 42ul)); | |
545 | EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42ll)); | |
546 | EXPECT_EQ("***42", fmt::format("{0:*>5}", 42ull)); | |
547 | EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42.0)); | |
548 | EXPECT_EQ("**-42", fmt::format("{0:*>5}", -42.0l)); | |
549 | EXPECT_EQ("c****", fmt::format("{0:*<5}", 'c')); | |
550 | EXPECT_EQ("abc**", fmt::format("{0:*<5}", "abc")); | |
551 | EXPECT_EQ("**0xface", | |
552 | fmt::format("{0:*>8}", reinterpret_cast<void*>(0xface))); | |
553 | EXPECT_EQ("foo=", fmt::format("{:}=", "foo")); | |
554 | EXPECT_EQ(std::string("\0\0\0*", 4), | |
555 | fmt::format(string_view("{:\0>4}", 6), '*')); | |
556 | EXPECT_EQ("жж42", fmt::format("{0:ж>4}", 42)); | |
557 | EXPECT_THROW_MSG(fmt::format(runtime("{:\x80\x80\x80\x80\x80>}"), 0), | |
558 | format_error, "missing '}' in format string"); | |
559 | } | |
560 | ||
561 | TEST(format_test, plus_sign) { | |
562 | EXPECT_EQ("+42", fmt::format("{0:+}", 42)); | |
563 | EXPECT_EQ("-42", fmt::format("{0:+}", -42)); | |
564 | EXPECT_EQ("+42", fmt::format("{0:+}", 42)); | |
565 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+}"), 42u), format_error, | |
9f95a23c | 566 | "format specifier requires signed argument"); |
20effc67 TL |
567 | EXPECT_EQ("+42", fmt::format("{0:+}", 42l)); |
568 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+}"), 42ul), format_error, | |
9f95a23c | 569 | "format specifier requires signed argument"); |
20effc67 TL |
570 | EXPECT_EQ("+42", fmt::format("{0:+}", 42ll)); |
571 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+}"), 42ull), format_error, | |
9f95a23c | 572 | "format specifier requires signed argument"); |
20effc67 TL |
573 | EXPECT_EQ("+42", fmt::format("{0:+}", 42.0)); |
574 | EXPECT_EQ("+42", fmt::format("{0:+}", 42.0l)); | |
575 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+"), 'c'), format_error, | |
9f95a23c | 576 | "missing '}' in format string"); |
20effc67 | 577 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+}"), 'c'), format_error, |
9f95a23c | 578 | "invalid format specifier for char"); |
20effc67 | 579 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+}"), "abc"), format_error, |
9f95a23c | 580 | "format specifier requires numeric argument"); |
20effc67 TL |
581 | EXPECT_THROW_MSG(fmt::format(runtime("{0:+}"), reinterpret_cast<void*>(0x42)), |
582 | format_error, "format specifier requires numeric argument"); | |
11fdf7f2 TL |
583 | } |
584 | ||
20effc67 TL |
585 | TEST(format_test, minus_sign) { |
586 | EXPECT_EQ("42", fmt::format("{0:-}", 42)); | |
587 | EXPECT_EQ("-42", fmt::format("{0:-}", -42)); | |
588 | EXPECT_EQ("42", fmt::format("{0:-}", 42)); | |
589 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-}"), 42u), format_error, | |
9f95a23c | 590 | "format specifier requires signed argument"); |
20effc67 TL |
591 | EXPECT_EQ("42", fmt::format("{0:-}", 42l)); |
592 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-}"), 42ul), format_error, | |
9f95a23c | 593 | "format specifier requires signed argument"); |
20effc67 TL |
594 | EXPECT_EQ("42", fmt::format("{0:-}", 42ll)); |
595 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-}"), 42ull), format_error, | |
9f95a23c | 596 | "format specifier requires signed argument"); |
20effc67 TL |
597 | EXPECT_EQ("42", fmt::format("{0:-}", 42.0)); |
598 | EXPECT_EQ("42", fmt::format("{0:-}", 42.0l)); | |
599 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-"), 'c'), format_error, | |
9f95a23c | 600 | "missing '}' in format string"); |
20effc67 | 601 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-}"), 'c'), format_error, |
9f95a23c | 602 | "invalid format specifier for char"); |
20effc67 | 603 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-}"), "abc"), format_error, |
9f95a23c | 604 | "format specifier requires numeric argument"); |
20effc67 TL |
605 | EXPECT_THROW_MSG(fmt::format(runtime("{0:-}"), reinterpret_cast<void*>(0x42)), |
606 | format_error, "format specifier requires numeric argument"); | |
11fdf7f2 TL |
607 | } |
608 | ||
20effc67 TL |
609 | TEST(format_test, space_sign) { |
610 | EXPECT_EQ(" 42", fmt::format("{0: }", 42)); | |
611 | EXPECT_EQ("-42", fmt::format("{0: }", -42)); | |
612 | EXPECT_EQ(" 42", fmt::format("{0: }", 42)); | |
613 | EXPECT_THROW_MSG(fmt::format(runtime("{0: }"), 42u), format_error, | |
9f95a23c | 614 | "format specifier requires signed argument"); |
20effc67 TL |
615 | EXPECT_EQ(" 42", fmt::format("{0: }", 42l)); |
616 | EXPECT_THROW_MSG(fmt::format(runtime("{0: }"), 42ul), format_error, | |
9f95a23c | 617 | "format specifier requires signed argument"); |
20effc67 TL |
618 | EXPECT_EQ(" 42", fmt::format("{0: }", 42ll)); |
619 | EXPECT_THROW_MSG(fmt::format(runtime("{0: }"), 42ull), format_error, | |
9f95a23c | 620 | "format specifier requires signed argument"); |
20effc67 TL |
621 | EXPECT_EQ(" 42", fmt::format("{0: }", 42.0)); |
622 | EXPECT_EQ(" 42", fmt::format("{0: }", 42.0l)); | |
623 | EXPECT_THROW_MSG(fmt::format(runtime("{0: "), 'c'), format_error, | |
9f95a23c | 624 | "missing '}' in format string"); |
20effc67 | 625 | EXPECT_THROW_MSG(fmt::format(runtime("{0: }"), 'c'), format_error, |
9f95a23c | 626 | "invalid format specifier for char"); |
20effc67 | 627 | EXPECT_THROW_MSG(fmt::format(runtime("{0: }"), "abc"), format_error, |
9f95a23c | 628 | "format specifier requires numeric argument"); |
20effc67 TL |
629 | EXPECT_THROW_MSG(fmt::format(runtime("{0: }"), reinterpret_cast<void*>(0x42)), |
630 | format_error, "format specifier requires numeric argument"); | |
11fdf7f2 TL |
631 | } |
632 | ||
20effc67 TL |
633 | TEST(format_test, hash_flag) { |
634 | EXPECT_EQ("42", fmt::format("{0:#}", 42)); | |
635 | EXPECT_EQ("-42", fmt::format("{0:#}", -42)); | |
636 | EXPECT_EQ("0b101010", fmt::format("{0:#b}", 42)); | |
637 | EXPECT_EQ("0B101010", fmt::format("{0:#B}", 42)); | |
638 | EXPECT_EQ("-0b101010", fmt::format("{0:#b}", -42)); | |
639 | EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42)); | |
640 | EXPECT_EQ("0X42", fmt::format("{0:#X}", 0x42)); | |
641 | EXPECT_EQ("-0x42", fmt::format("{0:#x}", -0x42)); | |
642 | EXPECT_EQ("0", fmt::format("{0:#o}", 0)); | |
643 | EXPECT_EQ("042", fmt::format("{0:#o}", 042)); | |
644 | EXPECT_EQ("-042", fmt::format("{0:#o}", -042)); | |
645 | EXPECT_EQ("42", fmt::format("{0:#}", 42u)); | |
646 | EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42u)); | |
647 | EXPECT_EQ("042", fmt::format("{0:#o}", 042u)); | |
648 | ||
649 | EXPECT_EQ("-42", fmt::format("{0:#}", -42l)); | |
650 | EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42l)); | |
651 | EXPECT_EQ("-0x42", fmt::format("{0:#x}", -0x42l)); | |
652 | EXPECT_EQ("042", fmt::format("{0:#o}", 042l)); | |
653 | EXPECT_EQ("-042", fmt::format("{0:#o}", -042l)); | |
654 | EXPECT_EQ("42", fmt::format("{0:#}", 42ul)); | |
655 | EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42ul)); | |
656 | EXPECT_EQ("042", fmt::format("{0:#o}", 042ul)); | |
657 | ||
658 | EXPECT_EQ("-42", fmt::format("{0:#}", -42ll)); | |
659 | EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42ll)); | |
660 | EXPECT_EQ("-0x42", fmt::format("{0:#x}", -0x42ll)); | |
661 | EXPECT_EQ("042", fmt::format("{0:#o}", 042ll)); | |
662 | EXPECT_EQ("-042", fmt::format("{0:#o}", -042ll)); | |
663 | EXPECT_EQ("42", fmt::format("{0:#}", 42ull)); | |
664 | EXPECT_EQ("0x42", fmt::format("{0:#x}", 0x42ull)); | |
665 | EXPECT_EQ("042", fmt::format("{0:#o}", 042ull)); | |
666 | ||
667 | EXPECT_EQ("-42.0", fmt::format("{0:#}", -42.0)); | |
668 | EXPECT_EQ("-42.0", fmt::format("{0:#}", -42.0l)); | |
669 | EXPECT_EQ("4.e+01", fmt::format("{:#.0e}", 42.0)); | |
670 | EXPECT_EQ("0.", fmt::format("{:#.0f}", 0.01)); | |
671 | EXPECT_EQ("0.50", fmt::format("{:#.2g}", 0.5)); | |
672 | EXPECT_EQ("0.", fmt::format("{:#.0f}", 0.5)); | |
673 | EXPECT_THROW_MSG(fmt::format(runtime("{0:#"), 'c'), format_error, | |
9f95a23c | 674 | "missing '}' in format string"); |
20effc67 | 675 | EXPECT_THROW_MSG(fmt::format(runtime("{0:#}"), 'c'), format_error, |
9f95a23c | 676 | "invalid format specifier for char"); |
20effc67 | 677 | EXPECT_THROW_MSG(fmt::format(runtime("{0:#}"), "abc"), format_error, |
9f95a23c | 678 | "format specifier requires numeric argument"); |
20effc67 TL |
679 | EXPECT_THROW_MSG(fmt::format(runtime("{0:#}"), reinterpret_cast<void*>(0x42)), |
680 | format_error, "format specifier requires numeric argument"); | |
11fdf7f2 TL |
681 | } |
682 | ||
20effc67 TL |
683 | TEST(format_test, zero_flag) { |
684 | EXPECT_EQ("42", fmt::format("{0:0}", 42)); | |
685 | EXPECT_EQ("-0042", fmt::format("{0:05}", -42)); | |
686 | EXPECT_EQ("00042", fmt::format("{0:05}", 42u)); | |
687 | EXPECT_EQ("-0042", fmt::format("{0:05}", -42l)); | |
688 | EXPECT_EQ("00042", fmt::format("{0:05}", 42ul)); | |
689 | EXPECT_EQ("-0042", fmt::format("{0:05}", -42ll)); | |
690 | EXPECT_EQ("00042", fmt::format("{0:05}", 42ull)); | |
691 | EXPECT_EQ("-000042", fmt::format("{0:07}", -42.0)); | |
692 | EXPECT_EQ("-000042", fmt::format("{0:07}", -42.0l)); | |
693 | EXPECT_THROW_MSG(fmt::format(runtime("{0:0"), 'c'), format_error, | |
9f95a23c | 694 | "missing '}' in format string"); |
20effc67 | 695 | EXPECT_THROW_MSG(fmt::format(runtime("{0:05}"), 'c'), format_error, |
9f95a23c | 696 | "invalid format specifier for char"); |
20effc67 | 697 | EXPECT_THROW_MSG(fmt::format(runtime("{0:05}"), "abc"), format_error, |
9f95a23c | 698 | "format specifier requires numeric argument"); |
20effc67 TL |
699 | EXPECT_THROW_MSG( |
700 | fmt::format(runtime("{0:05}"), reinterpret_cast<void*>(0x42)), | |
701 | format_error, "format specifier requires numeric argument"); | |
11fdf7f2 TL |
702 | } |
703 | ||
20effc67 TL |
704 | TEST(format_test, width) { |
705 | char format_str[buffer_size]; | |
11fdf7f2 TL |
706 | safe_sprintf(format_str, "{0:%u", UINT_MAX); |
707 | increment(format_str + 3); | |
20effc67 TL |
708 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
709 | "number is too big"); | |
f67539c2 | 710 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
711 | format_str[size] = '}'; |
712 | format_str[size + 1] = 0; | |
20effc67 TL |
713 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
714 | "number is too big"); | |
11fdf7f2 TL |
715 | |
716 | safe_sprintf(format_str, "{0:%u", INT_MAX + 1u); | |
20effc67 TL |
717 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
718 | "number is too big"); | |
11fdf7f2 | 719 | safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u); |
20effc67 TL |
720 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
721 | "number is too big"); | |
722 | EXPECT_EQ(" -42", fmt::format("{0:4}", -42)); | |
723 | EXPECT_EQ(" 42", fmt::format("{0:5}", 42u)); | |
724 | EXPECT_EQ(" -42", fmt::format("{0:6}", -42l)); | |
725 | EXPECT_EQ(" 42", fmt::format("{0:7}", 42ul)); | |
726 | EXPECT_EQ(" -42", fmt::format("{0:6}", -42ll)); | |
727 | EXPECT_EQ(" 42", fmt::format("{0:7}", 42ull)); | |
728 | EXPECT_EQ(" -1.23", fmt::format("{0:8}", -1.23)); | |
729 | EXPECT_EQ(" -1.23", fmt::format("{0:9}", -1.23l)); | |
730 | EXPECT_EQ(" 0xcafe", | |
731 | fmt::format("{0:10}", reinterpret_cast<void*>(0xcafe))); | |
732 | EXPECT_EQ("x ", fmt::format("{0:11}", 'x')); | |
733 | EXPECT_EQ("str ", fmt::format("{0:12}", "str")); | |
734 | EXPECT_EQ(fmt::format("{:*^6}", "🤡"), "**🤡**"); | |
735 | EXPECT_EQ(fmt::format("{:*^8}", "你好"), "**你好**"); | |
736 | EXPECT_EQ(fmt::format("{:#6}", 42.0), " 42.0"); | |
737 | EXPECT_EQ(fmt::format("{:6c}", static_cast<int>('x')), "x "); | |
738 | EXPECT_EQ(fmt::format("{:>06.0f}", 0.00884311), "000000"); | |
739 | } | |
740 | ||
741 | TEST(format_test, runtime_width) { | |
742 | char format_str[buffer_size]; | |
11fdf7f2 TL |
743 | safe_sprintf(format_str, "{0:{%u", UINT_MAX); |
744 | increment(format_str + 4); | |
20effc67 TL |
745 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
746 | "invalid format string"); | |
f67539c2 | 747 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
748 | format_str[size] = '}'; |
749 | format_str[size + 1] = 0; | |
20effc67 TL |
750 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
751 | "argument not found"); | |
11fdf7f2 TL |
752 | format_str[size + 1] = '}'; |
753 | format_str[size + 2] = 0; | |
20effc67 TL |
754 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
755 | "argument not found"); | |
11fdf7f2 | 756 | |
20effc67 TL |
757 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{"), 0), format_error, |
758 | "invalid format string"); | |
759 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{}"), 0), format_error, | |
9f95a23c | 760 | "cannot switch from manual to automatic argument indexing"); |
20effc67 TL |
761 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{?}}"), 0), format_error, |
762 | "invalid format string"); | |
763 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0), format_error, | |
764 | "argument not found"); | |
9f95a23c | 765 | |
20effc67 | 766 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{0:}}"), 0), format_error, |
9f95a23c TL |
767 | "invalid format string"); |
768 | ||
20effc67 TL |
769 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, -1), format_error, |
770 | "negative width"); | |
771 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, (INT_MAX + 1u)), | |
772 | format_error, "number is too big"); | |
773 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, -1l), format_error, | |
774 | "negative width"); | |
775 | if (fmt::detail::const_check(sizeof(long) > sizeof(int))) { | |
11fdf7f2 | 776 | long value = INT_MAX; |
20effc67 TL |
777 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, (value + 1)), |
778 | format_error, "number is too big"); | |
11fdf7f2 | 779 | } |
20effc67 TL |
780 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, (INT_MAX + 1ul)), |
781 | format_error, "number is too big"); | |
11fdf7f2 | 782 | |
20effc67 | 783 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, '0'), format_error, |
9f95a23c | 784 | "width is not integer"); |
20effc67 | 785 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{1}}"), 0, 0.0), format_error, |
9f95a23c | 786 | "width is not integer"); |
11fdf7f2 | 787 | |
20effc67 TL |
788 | EXPECT_EQ(" -42", fmt::format("{0:{1}}", -42, 4)); |
789 | EXPECT_EQ(" 42", fmt::format("{0:{1}}", 42u, 5)); | |
790 | EXPECT_EQ(" -42", fmt::format("{0:{1}}", -42l, 6)); | |
791 | EXPECT_EQ(" 42", fmt::format("{0:{1}}", 42ul, 7)); | |
792 | EXPECT_EQ(" -42", fmt::format("{0:{1}}", -42ll, 6)); | |
793 | EXPECT_EQ(" 42", fmt::format("{0:{1}}", 42ull, 7)); | |
794 | EXPECT_EQ(" -1.23", fmt::format("{0:{1}}", -1.23, 8)); | |
795 | EXPECT_EQ(" -1.23", fmt::format("{0:{1}}", -1.23l, 9)); | |
11fdf7f2 | 796 | EXPECT_EQ(" 0xcafe", |
20effc67 TL |
797 | fmt::format("{0:{1}}", reinterpret_cast<void*>(0xcafe), 10)); |
798 | EXPECT_EQ("x ", fmt::format("{0:{1}}", 'x', 11)); | |
799 | EXPECT_EQ("str ", fmt::format("{0:{1}}", "str", 12)); | |
11fdf7f2 TL |
800 | } |
801 | ||
20effc67 TL |
802 | TEST(format_test, precision) { |
803 | char format_str[buffer_size]; | |
11fdf7f2 TL |
804 | safe_sprintf(format_str, "{0:.%u", UINT_MAX); |
805 | increment(format_str + 4); | |
20effc67 TL |
806 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
807 | "number is too big"); | |
f67539c2 | 808 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
809 | format_str[size] = '}'; |
810 | format_str[size + 1] = 0; | |
20effc67 TL |
811 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
812 | "number is too big"); | |
11fdf7f2 TL |
813 | |
814 | safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u); | |
20effc67 TL |
815 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
816 | "number is too big"); | |
11fdf7f2 | 817 | safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u); |
20effc67 TL |
818 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
819 | "number is too big"); | |
11fdf7f2 | 820 | |
20effc67 | 821 | EXPECT_THROW_MSG(fmt::format(runtime("{0:."), 0), format_error, |
9f95a23c | 822 | "missing precision specifier"); |
20effc67 | 823 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.}"), 0), format_error, |
9f95a23c TL |
824 | "missing precision specifier"); |
825 | ||
20effc67 | 826 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2"), 0), format_error, |
9f95a23c | 827 | "precision not allowed for this argument type"); |
20effc67 | 828 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2}"), 42), format_error, |
9f95a23c | 829 | "precision not allowed for this argument type"); |
20effc67 | 830 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2f}"), 42), format_error, |
9f95a23c | 831 | "precision not allowed for this argument type"); |
20effc67 | 832 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2}"), 42u), format_error, |
9f95a23c | 833 | "precision not allowed for this argument type"); |
20effc67 | 834 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2f}"), 42u), format_error, |
9f95a23c | 835 | "precision not allowed for this argument type"); |
20effc67 | 836 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2}"), 42l), format_error, |
9f95a23c | 837 | "precision not allowed for this argument type"); |
20effc67 | 838 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2f}"), 42l), format_error, |
9f95a23c | 839 | "precision not allowed for this argument type"); |
20effc67 | 840 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2}"), 42ul), format_error, |
9f95a23c | 841 | "precision not allowed for this argument type"); |
20effc67 | 842 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2f}"), 42ul), format_error, |
9f95a23c | 843 | "precision not allowed for this argument type"); |
20effc67 | 844 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2}"), 42ll), format_error, |
9f95a23c | 845 | "precision not allowed for this argument type"); |
20effc67 | 846 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2f}"), 42ll), format_error, |
9f95a23c | 847 | "precision not allowed for this argument type"); |
20effc67 | 848 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2}"), 42ull), format_error, |
9f95a23c | 849 | "precision not allowed for this argument type"); |
20effc67 | 850 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.2f}"), 42ull), format_error, |
9f95a23c | 851 | "precision not allowed for this argument type"); |
20effc67 | 852 | EXPECT_THROW_MSG(fmt::format(runtime("{0:3.0}"), 'x'), format_error, |
9f95a23c | 853 | "precision not allowed for this argument type"); |
20effc67 TL |
854 | EXPECT_EQ("1.2", fmt::format("{0:.2}", 1.2345)); |
855 | EXPECT_EQ("1.2", fmt::format("{0:.2}", 1.2345l)); | |
856 | EXPECT_EQ("1.2e+56", fmt::format("{:.2}", 1.234e56)); | |
857 | EXPECT_EQ("1.1", fmt::format("{0:.3}", 1.1)); | |
858 | EXPECT_EQ("1e+00", fmt::format("{:.0e}", 1.0L)); | |
859 | EXPECT_EQ(" 0.0e+00", fmt::format("{:9.1e}", 0.0)); | |
f67539c2 | 860 | EXPECT_EQ( |
20effc67 | 861 | fmt::format("{:.494}", 4.9406564584124654E-324), |
f67539c2 TL |
862 | "4.9406564584124654417656879286822137236505980261432476442558568250067550" |
863 | "727020875186529983636163599237979656469544571773092665671035593979639877" | |
864 | "479601078187812630071319031140452784581716784898210368871863605699873072" | |
865 | "305000638740915356498438731247339727316961514003171538539807412623856559" | |
866 | "117102665855668676818703956031062493194527159149245532930545654440112748" | |
867 | "012970999954193198940908041656332452475714786901472678015935523861155013" | |
20effc67 TL |
868 | "480352649347201937902681071074917033322268447533357208324319361e-324"); |
869 | ||
870 | std::string outputs[] = { | |
f67539c2 TL |
871 | "-0X1.41FE3FFE71C9E000000000000000000000000000000000000000000000000000000" |
872 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
873 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
874 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
875 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
876 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
877 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
878 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
879 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
880 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
881 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
882 | "000000000000000000000000000000000000000000000000000P+127", | |
20effc67 TL |
883 | "-0XA.0FF1FFF38E4F0000000000000000000000000000000000000000000000000000000" |
884 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
885 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
886 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
887 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
888 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
889 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
890 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
891 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
892 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
893 | "000000000000000000000000000000000000000000000000000000000000000000000000" | |
894 | "000000000000000000000000000000000000000000000000000P+124"}; | |
895 | EXPECT_THAT(outputs, | |
896 | testing::Contains(fmt::format("{:.838A}", -2.14001164E+38))); | |
11fdf7f2 | 897 | |
20effc67 TL |
898 | EXPECT_EQ("123.", fmt::format("{:#.0f}", 123.0)); |
899 | EXPECT_EQ("1.23", fmt::format("{:.02f}", 1.234)); | |
900 | EXPECT_EQ("0.001", fmt::format("{:.1g}", 0.001)); | |
901 | EXPECT_EQ("1019666400", fmt::format("{}", 1019666432.0f)); | |
902 | EXPECT_EQ("1e+01", fmt::format("{:.0e}", 9.5)); | |
903 | EXPECT_EQ("1.0e-34", fmt::format("{:.1e}", 1e-34)); | |
904 | ||
905 | EXPECT_THROW_MSG( | |
906 | fmt::format(runtime("{0:.2}"), reinterpret_cast<void*>(0xcafe)), | |
907 | format_error, "precision not allowed for this argument type"); | |
908 | EXPECT_THROW_MSG( | |
909 | fmt::format(runtime("{0:.2f}"), reinterpret_cast<void*>(0xcafe)), | |
910 | format_error, "precision not allowed for this argument type"); | |
911 | EXPECT_THROW_MSG( | |
912 | fmt::format(runtime("{:.{}e}"), 42.0, fmt::detail::max_value<int>()), | |
913 | format_error, "number is too big"); | |
11fdf7f2 | 914 | |
20effc67 | 915 | EXPECT_EQ("st", fmt::format("{0:.2}", "str")); |
11fdf7f2 TL |
916 | } |
917 | ||
20effc67 TL |
918 | TEST(format_test, runtime_precision) { |
919 | char format_str[buffer_size]; | |
11fdf7f2 TL |
920 | safe_sprintf(format_str, "{0:.{%u", UINT_MAX); |
921 | increment(format_str + 5); | |
20effc67 TL |
922 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
923 | "invalid format string"); | |
f67539c2 | 924 | size_t size = std::strlen(format_str); |
11fdf7f2 TL |
925 | format_str[size] = '}'; |
926 | format_str[size + 1] = 0; | |
20effc67 TL |
927 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
928 | "argument not found"); | |
11fdf7f2 TL |
929 | format_str[size + 1] = '}'; |
930 | format_str[size + 2] = 0; | |
20effc67 TL |
931 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), 0), format_error, |
932 | "argument not found"); | |
11fdf7f2 | 933 | |
20effc67 TL |
934 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{"), 0), format_error, |
935 | "invalid format string"); | |
936 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{}"), 0), format_error, | |
9f95a23c | 937 | "cannot switch from manual to automatic argument indexing"); |
20effc67 | 938 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{?}}"), 0), format_error, |
9f95a23c | 939 | "invalid format string"); |
20effc67 | 940 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}"), 0, 0), format_error, |
9f95a23c | 941 | "precision not allowed for this argument type"); |
20effc67 TL |
942 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0), format_error, |
943 | "argument not found"); | |
9f95a23c | 944 | |
20effc67 | 945 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{0:}}"), 0), format_error, |
9f95a23c TL |
946 | "invalid format string"); |
947 | ||
20effc67 | 948 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, -1), format_error, |
9f95a23c | 949 | "negative precision"); |
20effc67 TL |
950 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, (INT_MAX + 1u)), |
951 | format_error, "number is too big"); | |
952 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, -1l), format_error, | |
9f95a23c | 953 | "negative precision"); |
20effc67 | 954 | if (fmt::detail::const_check(sizeof(long) > sizeof(int))) { |
11fdf7f2 | 955 | long value = INT_MAX; |
20effc67 TL |
956 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, (value + 1)), |
957 | format_error, "number is too big"); | |
11fdf7f2 | 958 | } |
20effc67 TL |
959 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, (INT_MAX + 1ul)), |
960 | format_error, "number is too big"); | |
9f95a23c | 961 | |
20effc67 | 962 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, '0'), format_error, |
9f95a23c | 963 | "precision is not integer"); |
20effc67 | 964 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 0, 0.0), format_error, |
9f95a23c TL |
965 | "precision is not integer"); |
966 | ||
20effc67 | 967 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 42, 2), format_error, |
9f95a23c | 968 | "precision not allowed for this argument type"); |
20effc67 | 969 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}f}"), 42, 2), format_error, |
9f95a23c | 970 | "precision not allowed for this argument type"); |
20effc67 | 971 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 42u, 2), format_error, |
9f95a23c | 972 | "precision not allowed for this argument type"); |
20effc67 | 973 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}f}"), 42u, 2), format_error, |
9f95a23c | 974 | "precision not allowed for this argument type"); |
20effc67 | 975 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 42l, 2), format_error, |
9f95a23c | 976 | "precision not allowed for this argument type"); |
20effc67 | 977 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}f}"), 42l, 2), format_error, |
9f95a23c | 978 | "precision not allowed for this argument type"); |
20effc67 | 979 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 42ul, 2), format_error, |
9f95a23c | 980 | "precision not allowed for this argument type"); |
20effc67 | 981 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}f}"), 42ul, 2), format_error, |
9f95a23c | 982 | "precision not allowed for this argument type"); |
20effc67 | 983 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 42ll, 2), format_error, |
9f95a23c | 984 | "precision not allowed for this argument type"); |
20effc67 | 985 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}f}"), 42ll, 2), format_error, |
9f95a23c | 986 | "precision not allowed for this argument type"); |
20effc67 | 987 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}}"), 42ull, 2), format_error, |
9f95a23c | 988 | "precision not allowed for this argument type"); |
20effc67 | 989 | EXPECT_THROW_MSG(fmt::format(runtime("{0:.{1}f}"), 42ull, 2), format_error, |
9f95a23c | 990 | "precision not allowed for this argument type"); |
20effc67 | 991 | EXPECT_THROW_MSG(fmt::format(runtime("{0:3.{1}}"), 'x', 0), format_error, |
9f95a23c | 992 | "precision not allowed for this argument type"); |
20effc67 TL |
993 | EXPECT_EQ("1.2", fmt::format("{0:.{1}}", 1.2345, 2)); |
994 | EXPECT_EQ("1.2", fmt::format("{1:.{0}}", 2, 1.2345l)); | |
11fdf7f2 | 995 | |
20effc67 TL |
996 | EXPECT_THROW_MSG( |
997 | fmt::format(runtime("{0:.{1}}"), reinterpret_cast<void*>(0xcafe), 2), | |
998 | format_error, "precision not allowed for this argument type"); | |
999 | EXPECT_THROW_MSG( | |
1000 | fmt::format(runtime("{0:.{1}f}"), reinterpret_cast<void*>(0xcafe), 2), | |
1001 | format_error, "precision not allowed for this argument type"); | |
1002 | ||
1003 | EXPECT_EQ("st", fmt::format("{0:.{1}}", "str", 2)); | |
1004 | } | |
11fdf7f2 | 1005 | |
20effc67 TL |
1006 | TEST(format_test, format_bool) { |
1007 | EXPECT_EQ("true", fmt::format("{}", true)); | |
1008 | EXPECT_EQ("false", fmt::format("{}", false)); | |
1009 | EXPECT_EQ("1", fmt::format("{:d}", true)); | |
1010 | EXPECT_EQ("true ", fmt::format("{:5}", true)); | |
1011 | EXPECT_EQ("true", fmt::format("{:s}", true)); | |
1012 | EXPECT_EQ("false", fmt::format("{:s}", false)); | |
1013 | EXPECT_EQ("false ", fmt::format("{:6s}", false)); | |
1014 | } | |
1015 | ||
1016 | TEST(format_test, format_short) { | |
1017 | short s = 42; | |
1018 | EXPECT_EQ("42", fmt::format("{0:d}", s)); | |
1019 | unsigned short us = 42; | |
1020 | EXPECT_EQ("42", fmt::format("{0:d}", us)); | |
11fdf7f2 TL |
1021 | } |
1022 | ||
1023 | template <typename T> | |
9f95a23c | 1024 | void check_unknown_types(const T& value, const char* types, const char*) { |
20effc67 TL |
1025 | char format_str[buffer_size]; |
1026 | const char* special = ".0123456789L}"; | |
11fdf7f2 TL |
1027 | for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) { |
1028 | char c = static_cast<char>(i); | |
1029 | if (std::strchr(types, c) || std::strchr(special, c) || !c) continue; | |
1030 | safe_sprintf(format_str, "{0:10%c}", c); | |
9f95a23c | 1031 | const char* message = "invalid type specifier"; |
20effc67 TL |
1032 | EXPECT_THROW_MSG(fmt::format(runtime(format_str), value), format_error, |
1033 | message) | |
9f95a23c | 1034 | << format_str << " " << message; |
11fdf7f2 TL |
1035 | } |
1036 | } | |
1037 | ||
20effc67 TL |
1038 | TEST(format_test, format_int) { |
1039 | EXPECT_THROW_MSG(fmt::format(runtime("{0:v"), 42), format_error, | |
9f95a23c | 1040 | "missing '}' in format string"); |
f67539c2 | 1041 | check_unknown_types(42, "bBdoxXnLc", "integer"); |
20effc67 TL |
1042 | EXPECT_EQ("x", fmt::format("{:c}", static_cast<int>('x'))); |
1043 | } | |
1044 | ||
1045 | TEST(format_test, format_bin) { | |
1046 | EXPECT_EQ("0", fmt::format("{0:b}", 0)); | |
1047 | EXPECT_EQ("101010", fmt::format("{0:b}", 42)); | |
1048 | EXPECT_EQ("101010", fmt::format("{0:b}", 42u)); | |
1049 | EXPECT_EQ("-101010", fmt::format("{0:b}", -42)); | |
1050 | EXPECT_EQ("11000000111001", fmt::format("{0:b}", 12345)); | |
1051 | EXPECT_EQ("10010001101000101011001111000", fmt::format("{0:b}", 0x12345678)); | |
1052 | EXPECT_EQ("10010000101010111100110111101111", | |
1053 | fmt::format("{0:b}", 0x90ABCDEF)); | |
11fdf7f2 | 1054 | EXPECT_EQ("11111111111111111111111111111111", |
20effc67 | 1055 | fmt::format("{0:b}", max_value<uint32_t>())); |
11fdf7f2 TL |
1056 | } |
1057 | ||
f67539c2 TL |
1058 | #if FMT_USE_INT128 |
1059 | constexpr auto int128_max = static_cast<__int128_t>( | |
1060 | (static_cast<__uint128_t>(1) << ((__SIZEOF_INT128__ * CHAR_BIT) - 1)) - 1); | |
1061 | constexpr auto int128_min = -int128_max - 1; | |
1062 | ||
1063 | constexpr auto uint128_max = ~static_cast<__uint128_t>(0); | |
1064 | #endif | |
1065 | ||
20effc67 TL |
1066 | TEST(format_test, format_dec) { |
1067 | EXPECT_EQ("0", fmt::format("{0}", 0)); | |
1068 | EXPECT_EQ("42", fmt::format("{0}", 42)); | |
1069 | EXPECT_EQ("42", fmt::format("{0:d}", 42)); | |
1070 | EXPECT_EQ("42", fmt::format("{0}", 42u)); | |
1071 | EXPECT_EQ("-42", fmt::format("{0}", -42)); | |
1072 | EXPECT_EQ("12345", fmt::format("{0}", 12345)); | |
1073 | EXPECT_EQ("67890", fmt::format("{0}", 67890)); | |
f67539c2 | 1074 | #if FMT_USE_INT128 |
20effc67 TL |
1075 | EXPECT_EQ("0", fmt::format("{0}", static_cast<__int128_t>(0))); |
1076 | EXPECT_EQ("0", fmt::format("{0}", static_cast<__uint128_t>(0))); | |
f67539c2 | 1077 | EXPECT_EQ("9223372036854775808", |
20effc67 | 1078 | fmt::format("{0}", static_cast<__int128_t>(INT64_MAX) + 1)); |
f67539c2 | 1079 | EXPECT_EQ("-9223372036854775809", |
20effc67 | 1080 | fmt::format("{0}", static_cast<__int128_t>(INT64_MIN) - 1)); |
f67539c2 | 1081 | EXPECT_EQ("18446744073709551616", |
20effc67 | 1082 | fmt::format("{0}", static_cast<__int128_t>(UINT64_MAX) + 1)); |
f67539c2 | 1083 | EXPECT_EQ("170141183460469231731687303715884105727", |
20effc67 | 1084 | fmt::format("{0}", int128_max)); |
f67539c2 | 1085 | EXPECT_EQ("-170141183460469231731687303715884105728", |
20effc67 | 1086 | fmt::format("{0}", int128_min)); |
f67539c2 | 1087 | EXPECT_EQ("340282366920938463463374607431768211455", |
20effc67 | 1088 | fmt::format("{0}", uint128_max)); |
f67539c2 TL |
1089 | #endif |
1090 | ||
20effc67 | 1091 | char buffer[buffer_size]; |
11fdf7f2 | 1092 | safe_sprintf(buffer, "%d", INT_MIN); |
20effc67 | 1093 | EXPECT_EQ(buffer, fmt::format("{0}", INT_MIN)); |
11fdf7f2 | 1094 | safe_sprintf(buffer, "%d", INT_MAX); |
20effc67 | 1095 | EXPECT_EQ(buffer, fmt::format("{0}", INT_MAX)); |
11fdf7f2 | 1096 | safe_sprintf(buffer, "%u", UINT_MAX); |
20effc67 | 1097 | EXPECT_EQ(buffer, fmt::format("{0}", UINT_MAX)); |
11fdf7f2 | 1098 | safe_sprintf(buffer, "%ld", 0 - static_cast<unsigned long>(LONG_MIN)); |
20effc67 | 1099 | EXPECT_EQ(buffer, fmt::format("{0}", LONG_MIN)); |
11fdf7f2 | 1100 | safe_sprintf(buffer, "%ld", LONG_MAX); |
20effc67 | 1101 | EXPECT_EQ(buffer, fmt::format("{0}", LONG_MAX)); |
11fdf7f2 | 1102 | safe_sprintf(buffer, "%lu", ULONG_MAX); |
20effc67 TL |
1103 | EXPECT_EQ(buffer, fmt::format("{0}", ULONG_MAX)); |
1104 | } | |
1105 | ||
1106 | TEST(format_test, format_hex) { | |
1107 | EXPECT_EQ("0", fmt::format("{0:x}", 0)); | |
1108 | EXPECT_EQ("42", fmt::format("{0:x}", 0x42)); | |
1109 | EXPECT_EQ("42", fmt::format("{0:x}", 0x42u)); | |
1110 | EXPECT_EQ("-42", fmt::format("{0:x}", -0x42)); | |
1111 | EXPECT_EQ("12345678", fmt::format("{0:x}", 0x12345678)); | |
1112 | EXPECT_EQ("90abcdef", fmt::format("{0:x}", 0x90abcdef)); | |
1113 | EXPECT_EQ("12345678", fmt::format("{0:X}", 0x12345678)); | |
1114 | EXPECT_EQ("90ABCDEF", fmt::format("{0:X}", 0x90ABCDEF)); | |
f67539c2 | 1115 | #if FMT_USE_INT128 |
20effc67 TL |
1116 | EXPECT_EQ("0", fmt::format("{0:x}", static_cast<__int128_t>(0))); |
1117 | EXPECT_EQ("0", fmt::format("{0:x}", static_cast<__uint128_t>(0))); | |
f67539c2 | 1118 | EXPECT_EQ("8000000000000000", |
20effc67 | 1119 | fmt::format("{0:x}", static_cast<__int128_t>(INT64_MAX) + 1)); |
f67539c2 | 1120 | EXPECT_EQ("-8000000000000001", |
20effc67 | 1121 | fmt::format("{0:x}", static_cast<__int128_t>(INT64_MIN) - 1)); |
f67539c2 | 1122 | EXPECT_EQ("10000000000000000", |
20effc67 TL |
1123 | fmt::format("{0:x}", static_cast<__int128_t>(UINT64_MAX) + 1)); |
1124 | EXPECT_EQ("7fffffffffffffffffffffffffffffff", | |
1125 | fmt::format("{0:x}", int128_max)); | |
1126 | EXPECT_EQ("-80000000000000000000000000000000", | |
1127 | fmt::format("{0:x}", int128_min)); | |
1128 | EXPECT_EQ("ffffffffffffffffffffffffffffffff", | |
1129 | fmt::format("{0:x}", uint128_max)); | |
f67539c2 | 1130 | #endif |
11fdf7f2 | 1131 | |
20effc67 | 1132 | char buffer[buffer_size]; |
11fdf7f2 | 1133 | safe_sprintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN)); |
20effc67 | 1134 | EXPECT_EQ(buffer, fmt::format("{0:x}", INT_MIN)); |
11fdf7f2 | 1135 | safe_sprintf(buffer, "%x", INT_MAX); |
20effc67 | 1136 | EXPECT_EQ(buffer, fmt::format("{0:x}", INT_MAX)); |
11fdf7f2 | 1137 | safe_sprintf(buffer, "%x", UINT_MAX); |
20effc67 | 1138 | EXPECT_EQ(buffer, fmt::format("{0:x}", UINT_MAX)); |
11fdf7f2 | 1139 | safe_sprintf(buffer, "-%lx", 0 - static_cast<unsigned long>(LONG_MIN)); |
20effc67 | 1140 | EXPECT_EQ(buffer, fmt::format("{0:x}", LONG_MIN)); |
11fdf7f2 | 1141 | safe_sprintf(buffer, "%lx", LONG_MAX); |
20effc67 | 1142 | EXPECT_EQ(buffer, fmt::format("{0:x}", LONG_MAX)); |
11fdf7f2 | 1143 | safe_sprintf(buffer, "%lx", ULONG_MAX); |
20effc67 | 1144 | EXPECT_EQ(buffer, fmt::format("{0:x}", ULONG_MAX)); |
11fdf7f2 TL |
1145 | } |
1146 | ||
20effc67 TL |
1147 | TEST(format_test, format_oct) { |
1148 | EXPECT_EQ("0", fmt::format("{0:o}", 0)); | |
1149 | EXPECT_EQ("42", fmt::format("{0:o}", 042)); | |
1150 | EXPECT_EQ("42", fmt::format("{0:o}", 042u)); | |
1151 | EXPECT_EQ("-42", fmt::format("{0:o}", -042)); | |
1152 | EXPECT_EQ("12345670", fmt::format("{0:o}", 012345670)); | |
f67539c2 | 1153 | #if FMT_USE_INT128 |
20effc67 TL |
1154 | EXPECT_EQ("0", fmt::format("{0:o}", static_cast<__int128_t>(0))); |
1155 | EXPECT_EQ("0", fmt::format("{0:o}", static_cast<__uint128_t>(0))); | |
f67539c2 | 1156 | EXPECT_EQ("1000000000000000000000", |
20effc67 | 1157 | fmt::format("{0:o}", static_cast<__int128_t>(INT64_MAX) + 1)); |
f67539c2 | 1158 | EXPECT_EQ("-1000000000000000000001", |
20effc67 | 1159 | fmt::format("{0:o}", static_cast<__int128_t>(INT64_MIN) - 1)); |
f67539c2 | 1160 | EXPECT_EQ("2000000000000000000000", |
20effc67 | 1161 | fmt::format("{0:o}", static_cast<__int128_t>(UINT64_MAX) + 1)); |
f67539c2 | 1162 | EXPECT_EQ("1777777777777777777777777777777777777777777", |
20effc67 | 1163 | fmt::format("{0:o}", int128_max)); |
f67539c2 | 1164 | EXPECT_EQ("-2000000000000000000000000000000000000000000", |
20effc67 | 1165 | fmt::format("{0:o}", int128_min)); |
f67539c2 | 1166 | EXPECT_EQ("3777777777777777777777777777777777777777777", |
20effc67 | 1167 | fmt::format("{0:o}", uint128_max)); |
f67539c2 TL |
1168 | #endif |
1169 | ||
20effc67 | 1170 | char buffer[buffer_size]; |
11fdf7f2 | 1171 | safe_sprintf(buffer, "-%o", 0 - static_cast<unsigned>(INT_MIN)); |
20effc67 | 1172 | EXPECT_EQ(buffer, fmt::format("{0:o}", INT_MIN)); |
11fdf7f2 | 1173 | safe_sprintf(buffer, "%o", INT_MAX); |
20effc67 | 1174 | EXPECT_EQ(buffer, fmt::format("{0:o}", INT_MAX)); |
11fdf7f2 | 1175 | safe_sprintf(buffer, "%o", UINT_MAX); |
20effc67 | 1176 | EXPECT_EQ(buffer, fmt::format("{0:o}", UINT_MAX)); |
11fdf7f2 | 1177 | safe_sprintf(buffer, "-%lo", 0 - static_cast<unsigned long>(LONG_MIN)); |
20effc67 | 1178 | EXPECT_EQ(buffer, fmt::format("{0:o}", LONG_MIN)); |
11fdf7f2 | 1179 | safe_sprintf(buffer, "%lo", LONG_MAX); |
20effc67 | 1180 | EXPECT_EQ(buffer, fmt::format("{0:o}", LONG_MAX)); |
11fdf7f2 | 1181 | safe_sprintf(buffer, "%lo", ULONG_MAX); |
20effc67 | 1182 | EXPECT_EQ(buffer, fmt::format("{0:o}", ULONG_MAX)); |
11fdf7f2 TL |
1183 | } |
1184 | ||
20effc67 TL |
1185 | TEST(format_test, format_int_locale) { |
1186 | EXPECT_EQ("1234", fmt::format("{:L}", 1234)); | |
11fdf7f2 TL |
1187 | } |
1188 | ||
20effc67 TL |
1189 | TEST(format_test, format_float) { |
1190 | EXPECT_EQ("0", fmt::format("{}", 0.0f)); | |
1191 | EXPECT_EQ("392.500000", fmt::format("{0:f}", 392.5f)); | |
11fdf7f2 TL |
1192 | } |
1193 | ||
20effc67 TL |
1194 | TEST(format_test, format_double) { |
1195 | EXPECT_EQ("0", fmt::format("{}", 0.0)); | |
f67539c2 | 1196 | check_unknown_types(1.2, "eEfFgGaAnL%", "double"); |
20effc67 TL |
1197 | EXPECT_EQ("0", fmt::format("{:}", 0.0)); |
1198 | EXPECT_EQ("0.000000", fmt::format("{:f}", 0.0)); | |
1199 | EXPECT_EQ("0", fmt::format("{:g}", 0.0)); | |
1200 | EXPECT_EQ("392.65", fmt::format("{:}", 392.65)); | |
1201 | EXPECT_EQ("392.65", fmt::format("{:g}", 392.65)); | |
1202 | EXPECT_EQ("392.65", fmt::format("{:G}", 392.65)); | |
1203 | EXPECT_EQ("4.9014e+06", fmt::format("{:g}", 4.9014e6)); | |
1204 | EXPECT_EQ("392.650000", fmt::format("{:f}", 392.65)); | |
1205 | EXPECT_EQ("392.650000", fmt::format("{:F}", 392.65)); | |
1206 | EXPECT_EQ("42", fmt::format("{:L}", 42.0)); | |
1207 | EXPECT_EQ(" 0x1.0cccccccccccdp+2", fmt::format("{:24a}", 4.2)); | |
1208 | EXPECT_EQ("0x1.0cccccccccccdp+2 ", fmt::format("{:<24a}", 4.2)); | |
1209 | char buffer[buffer_size]; | |
11fdf7f2 | 1210 | safe_sprintf(buffer, "%e", 392.65); |
20effc67 | 1211 | EXPECT_EQ(buffer, fmt::format("{0:e}", 392.65)); |
11fdf7f2 | 1212 | safe_sprintf(buffer, "%E", 392.65); |
20effc67 TL |
1213 | EXPECT_EQ(buffer, fmt::format("{0:E}", 392.65)); |
1214 | EXPECT_EQ("+0000392.6", fmt::format("{0:+010.4g}", 392.65)); | |
11fdf7f2 | 1215 | safe_sprintf(buffer, "%a", -42.0); |
20effc67 | 1216 | EXPECT_EQ(buffer, fmt::format("{:a}", -42.0)); |
11fdf7f2 | 1217 | safe_sprintf(buffer, "%A", -42.0); |
20effc67 TL |
1218 | EXPECT_EQ(buffer, fmt::format("{:A}", -42.0)); |
1219 | EXPECT_EQ("9223372036854775808.000000", | |
1220 | fmt::format("{:f}", 9223372036854775807.0)); | |
1221 | } | |
1222 | ||
1223 | TEST(format_test, precision_rounding) { | |
1224 | EXPECT_EQ("0", fmt::format("{:.0f}", 0.0)); | |
1225 | EXPECT_EQ("0", fmt::format("{:.0f}", 0.01)); | |
1226 | EXPECT_EQ("0", fmt::format("{:.0f}", 0.1)); | |
1227 | EXPECT_EQ("0.000", fmt::format("{:.3f}", 0.00049)); | |
1228 | EXPECT_EQ("0.001", fmt::format("{:.3f}", 0.0005)); | |
1229 | EXPECT_EQ("0.001", fmt::format("{:.3f}", 0.00149)); | |
1230 | EXPECT_EQ("0.002", fmt::format("{:.3f}", 0.0015)); | |
1231 | EXPECT_EQ("1.000", fmt::format("{:.3f}", 0.9999)); | |
1232 | EXPECT_EQ("0.00123", fmt::format("{:.3}", 0.00123)); | |
1233 | EXPECT_EQ("0.1", fmt::format("{:.16g}", 0.1)); | |
1234 | EXPECT_EQ("1", fmt::format("{:.0}", 1.0)); | |
1235 | EXPECT_EQ("225.51575035152063720", | |
1236 | fmt::format("{:.17f}", 225.51575035152064)); | |
1237 | EXPECT_EQ("-761519619559038.2", fmt::format("{:.1f}", -761519619559038.2)); | |
1238 | EXPECT_EQ("1.9156918820264798e-56", | |
1239 | fmt::format("{}", 1.9156918820264798e-56)); | |
1240 | EXPECT_EQ("0.0000", fmt::format("{:.4f}", 7.2809479766055470e-15)); | |
1241 | ||
1242 | // Trigger a rounding error in Grisu by a specially chosen number. | |
1243 | EXPECT_EQ("3788512123356.985352", fmt::format("{:f}", 3788512123356.985352)); | |
1244 | } | |
1245 | ||
1246 | TEST(format_test, prettify_float) { | |
1247 | EXPECT_EQ("0.0001", fmt::format("{}", 1e-4)); | |
1248 | EXPECT_EQ("1e-05", fmt::format("{}", 1e-5)); | |
1249 | EXPECT_EQ("1000000000000000", fmt::format("{}", 1e15)); | |
1250 | EXPECT_EQ("1e+16", fmt::format("{}", 1e16)); | |
1251 | EXPECT_EQ("9.999e-05", fmt::format("{}", 9.999e-5)); | |
1252 | EXPECT_EQ("10000000000", fmt::format("{}", 1e10)); | |
1253 | EXPECT_EQ("100000000000", fmt::format("{}", 1e11)); | |
1254 | EXPECT_EQ("12340000000", fmt::format("{}", 1234e7)); | |
1255 | EXPECT_EQ("12.34", fmt::format("{}", 1234e-2)); | |
1256 | EXPECT_EQ("0.001234", fmt::format("{}", 1234e-6)); | |
1257 | EXPECT_EQ("0.1", fmt::format("{}", 0.1f)); | |
1258 | EXPECT_EQ("0.10000000149011612", fmt::format("{}", double(0.1f))); | |
1259 | EXPECT_EQ("1.3563156e-19", fmt::format("{}", 1.35631564e-19f)); | |
1260 | } | |
1261 | ||
1262 | TEST(format_test, format_nan) { | |
11fdf7f2 | 1263 | double nan = std::numeric_limits<double>::quiet_NaN(); |
20effc67 TL |
1264 | EXPECT_EQ("nan", fmt::format("{}", nan)); |
1265 | EXPECT_EQ("+nan", fmt::format("{:+}", nan)); | |
1266 | EXPECT_EQ(" +nan", fmt::format("{:+06}", nan)); | |
1267 | EXPECT_EQ("+nan ", fmt::format("{:<+06}", nan)); | |
1268 | EXPECT_EQ(" +nan ", fmt::format("{:^+06}", nan)); | |
1269 | EXPECT_EQ(" +nan", fmt::format("{:>+06}", nan)); | |
1270 | if (std::signbit(-nan)) { | |
1271 | EXPECT_EQ("-nan", fmt::format("{}", -nan)); | |
1272 | EXPECT_EQ(" -nan", fmt::format("{:+06}", -nan)); | |
1273 | } else { | |
1274 | fmt::print("Warning: compiler doesn't handle negative NaN correctly"); | |
1275 | } | |
1276 | EXPECT_EQ(" nan", fmt::format("{: }", nan)); | |
1277 | EXPECT_EQ("NAN", fmt::format("{:F}", nan)); | |
1278 | EXPECT_EQ("nan ", fmt::format("{:<7}", nan)); | |
1279 | EXPECT_EQ(" nan ", fmt::format("{:^7}", nan)); | |
1280 | EXPECT_EQ(" nan", fmt::format("{:>7}", nan)); | |
11fdf7f2 TL |
1281 | } |
1282 | ||
20effc67 | 1283 | TEST(format_test, format_infinity) { |
11fdf7f2 | 1284 | double inf = std::numeric_limits<double>::infinity(); |
20effc67 TL |
1285 | EXPECT_EQ("inf", fmt::format("{}", inf)); |
1286 | EXPECT_EQ("+inf", fmt::format("{:+}", inf)); | |
1287 | EXPECT_EQ("-inf", fmt::format("{}", -inf)); | |
1288 | EXPECT_EQ(" +inf", fmt::format("{:+06}", inf)); | |
1289 | EXPECT_EQ(" -inf", fmt::format("{:+06}", -inf)); | |
1290 | EXPECT_EQ("+inf ", fmt::format("{:<+06}", inf)); | |
1291 | EXPECT_EQ(" +inf ", fmt::format("{:^+06}", inf)); | |
1292 | EXPECT_EQ(" +inf", fmt::format("{:>+06}", inf)); | |
1293 | EXPECT_EQ(" inf", fmt::format("{: }", inf)); | |
1294 | EXPECT_EQ("INF", fmt::format("{:F}", inf)); | |
1295 | EXPECT_EQ("inf ", fmt::format("{:<7}", inf)); | |
1296 | EXPECT_EQ(" inf ", fmt::format("{:^7}", inf)); | |
1297 | EXPECT_EQ(" inf", fmt::format("{:>7}", inf)); | |
1298 | } | |
1299 | ||
1300 | TEST(format_test, format_long_double) { | |
1301 | EXPECT_EQ("0", fmt::format("{0:}", 0.0l)); | |
1302 | EXPECT_EQ("0.000000", fmt::format("{0:f}", 0.0l)); | |
1303 | EXPECT_EQ("392.65", fmt::format("{0:}", 392.65l)); | |
1304 | EXPECT_EQ("392.65", fmt::format("{0:g}", 392.65l)); | |
1305 | EXPECT_EQ("392.65", fmt::format("{0:G}", 392.65l)); | |
1306 | EXPECT_EQ("392.650000", fmt::format("{0:f}", 392.65l)); | |
1307 | EXPECT_EQ("392.650000", fmt::format("{0:F}", 392.65l)); | |
1308 | char buffer[buffer_size]; | |
11fdf7f2 | 1309 | safe_sprintf(buffer, "%Le", 392.65l); |
20effc67 TL |
1310 | EXPECT_EQ(buffer, fmt::format("{0:e}", 392.65l)); |
1311 | EXPECT_EQ("+0000392.6", fmt::format("{0:+010.4g}", 392.64l)); | |
f67539c2 | 1312 | safe_sprintf(buffer, "%La", 3.31l); |
20effc67 | 1313 | EXPECT_EQ(buffer, fmt::format("{:a}", 3.31l)); |
11fdf7f2 TL |
1314 | } |
1315 | ||
20effc67 TL |
1316 | TEST(format_test, format_char) { |
1317 | const char types[] = "cbBdoxX"; | |
11fdf7f2 | 1318 | check_unknown_types('a', types, "char"); |
20effc67 TL |
1319 | EXPECT_EQ("a", fmt::format("{0}", 'a')); |
1320 | EXPECT_EQ("z", fmt::format("{0:c}", 'z')); | |
11fdf7f2 | 1321 | int n = 'x'; |
9f95a23c | 1322 | for (const char* type = types + 1; *type; ++type) { |
11fdf7f2 | 1323 | std::string format_str = fmt::format("{{:{}}}", *type); |
20effc67 TL |
1324 | EXPECT_EQ(fmt::format(runtime(format_str), n), |
1325 | fmt::format(runtime(format_str), 'x')) | |
1326 | << format_str; | |
11fdf7f2 TL |
1327 | } |
1328 | EXPECT_EQ(fmt::format("{:02X}", n), fmt::format("{:02X}", 'x')); | |
1329 | } | |
1330 | ||
20effc67 | 1331 | TEST(format_test, format_volatile_char) { |
f67539c2 | 1332 | volatile char c = 'x'; |
20effc67 | 1333 | EXPECT_EQ("x", fmt::format("{}", c)); |
11fdf7f2 TL |
1334 | } |
1335 | ||
20effc67 TL |
1336 | TEST(format_test, format_unsigned_char) { |
1337 | EXPECT_EQ("42", fmt::format("{}", static_cast<unsigned char>(42))); | |
1338 | EXPECT_EQ("42", fmt::format("{}", static_cast<uint8_t>(42))); | |
11fdf7f2 TL |
1339 | } |
1340 | ||
20effc67 | 1341 | TEST(format_test, format_cstring) { |
11fdf7f2 | 1342 | check_unknown_types("test", "sp", "string"); |
20effc67 TL |
1343 | EXPECT_EQ("test", fmt::format("{0}", "test")); |
1344 | EXPECT_EQ("test", fmt::format("{0:s}", "test")); | |
11fdf7f2 | 1345 | char nonconst[] = "nonconst"; |
20effc67 TL |
1346 | EXPECT_EQ("nonconst", fmt::format("{0}", nonconst)); |
1347 | EXPECT_THROW_MSG( | |
1348 | fmt::format(runtime("{0}"), static_cast<const char*>(nullptr)), | |
1349 | format_error, "string pointer is null"); | |
11fdf7f2 TL |
1350 | } |
1351 | ||
20effc67 | 1352 | TEST(format_test, format_schar_string) { |
11fdf7f2 | 1353 | signed char str[] = "test"; |
20effc67 | 1354 | EXPECT_EQ("test", fmt::format("{0:s}", str)); |
9f95a23c | 1355 | const signed char* const_str = str; |
20effc67 | 1356 | EXPECT_EQ("test", fmt::format("{0:s}", const_str)); |
11fdf7f2 TL |
1357 | } |
1358 | ||
20effc67 | 1359 | TEST(format_test, format_uchar_string) { |
11fdf7f2 | 1360 | unsigned char str[] = "test"; |
20effc67 | 1361 | EXPECT_EQ("test", fmt::format("{0:s}", str)); |
9f95a23c | 1362 | const unsigned char* const_str = str; |
20effc67 | 1363 | EXPECT_EQ("test", fmt::format("{0:s}", const_str)); |
9f95a23c | 1364 | unsigned char* ptr = str; |
20effc67 | 1365 | EXPECT_EQ("test", fmt::format("{0:s}", ptr)); |
11fdf7f2 TL |
1366 | } |
1367 | ||
20effc67 TL |
1368 | void function_pointer_test(int, double, std::string) {} |
1369 | ||
1370 | TEST(format_test, format_pointer) { | |
11fdf7f2 | 1371 | check_unknown_types(reinterpret_cast<void*>(0x1234), "p", "pointer"); |
20effc67 TL |
1372 | EXPECT_EQ("0x0", fmt::format("{0}", static_cast<void*>(nullptr))); |
1373 | EXPECT_EQ("0x1234", fmt::format("{0}", reinterpret_cast<void*>(0x1234))); | |
1374 | EXPECT_EQ("0x1234", fmt::format("{0:p}", reinterpret_cast<void*>(0x1234))); | |
11fdf7f2 | 1375 | EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'), |
20effc67 TL |
1376 | fmt::format("{0}", reinterpret_cast<void*>(~uintptr_t()))); |
1377 | EXPECT_EQ("0x1234", | |
1378 | fmt::format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234)))); | |
f67539c2 | 1379 | std::unique_ptr<int> up(new int(1)); |
20effc67 TL |
1380 | EXPECT_EQ(fmt::format("{}", fmt::ptr(up.get())), |
1381 | fmt::format("{}", fmt::ptr(up))); | |
f67539c2 | 1382 | std::shared_ptr<int> sp(new int(1)); |
20effc67 TL |
1383 | EXPECT_EQ(fmt::format("{}", fmt::ptr(sp.get())), |
1384 | fmt::format("{}", fmt::ptr(sp))); | |
1385 | EXPECT_EQ(fmt::format("{}", fmt::detail::bit_cast<const void*>( | |
1386 | &function_pointer_test)), | |
1387 | fmt::format("{}", fmt::ptr(function_pointer_test))); | |
1388 | EXPECT_EQ("0x0", fmt::format("{}", nullptr)); | |
11fdf7f2 TL |
1389 | } |
1390 | ||
20effc67 TL |
1391 | TEST(format_test, format_string) { |
1392 | EXPECT_EQ("test", fmt::format("{0}", std::string("test"))); | |
11fdf7f2 TL |
1393 | } |
1394 | ||
20effc67 TL |
1395 | TEST(format_test, format_string_view) { |
1396 | EXPECT_EQ("test", fmt::format("{}", string_view("test"))); | |
1397 | EXPECT_EQ("", fmt::format("{}", string_view())); | |
11fdf7f2 TL |
1398 | } |
1399 | ||
f67539c2 TL |
1400 | #ifdef FMT_USE_STRING_VIEW |
1401 | struct string_viewable {}; | |
1402 | ||
1403 | FMT_BEGIN_NAMESPACE | |
1404 | template <> struct formatter<string_viewable> : formatter<std::string_view> { | |
1405 | auto format(string_viewable, format_context& ctx) -> decltype(ctx.out()) { | |
1406 | return formatter<std::string_view>::format("foo", ctx); | |
1407 | } | |
1408 | }; | |
1409 | FMT_END_NAMESPACE | |
1410 | ||
20effc67 TL |
1411 | TEST(format_test, format_std_string_view) { |
1412 | EXPECT_EQ("test", fmt::format("{}", std::string_view("test"))); | |
1413 | EXPECT_EQ("foo", fmt::format("{}", string_viewable())); | |
f67539c2 TL |
1414 | } |
1415 | ||
1416 | struct explicitly_convertible_to_std_string_view { | |
1417 | explicit operator std::string_view() const { return "foo"; } | |
1418 | }; | |
1419 | ||
f67539c2 | 1420 | template <> |
20effc67 | 1421 | struct fmt::formatter<explicitly_convertible_to_std_string_view> |
f67539c2 | 1422 | : formatter<std::string_view> { |
20effc67 TL |
1423 | auto format(explicitly_convertible_to_std_string_view v, format_context& ctx) |
1424 | -> decltype(ctx.out()) { | |
f67539c2 TL |
1425 | return format_to(ctx.out(), "'{}'", std::string_view(v)); |
1426 | } | |
1427 | }; | |
f67539c2 | 1428 | |
20effc67 | 1429 | TEST(format_test, format_explicitly_convertible_to_std_string_view) { |
f67539c2 TL |
1430 | EXPECT_EQ("'foo'", |
1431 | fmt::format("{}", explicitly_convertible_to_std_string_view())); | |
1432 | } | |
1433 | #endif | |
1434 | ||
20effc67 TL |
1435 | struct converible_to_anything { |
1436 | template <typename T> operator T() const { return T(); } | |
f67539c2 TL |
1437 | }; |
1438 | ||
20effc67 TL |
1439 | FMT_BEGIN_NAMESPACE |
1440 | template <> struct formatter<converible_to_anything> { | |
1441 | FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | |
1442 | return ctx.begin(); | |
1443 | } | |
f67539c2 | 1444 | |
20effc67 TL |
1445 | auto format(converible_to_anything, format_context& ctx) |
1446 | -> decltype(ctx.out()) { | |
1447 | return format_to(ctx.out(), "foo"); | |
1448 | } | |
f67539c2 | 1449 | }; |
20effc67 | 1450 | FMT_END_NAMESPACE |
f67539c2 | 1451 | |
20effc67 TL |
1452 | TEST(format_test, format_convertible_to_anything) { |
1453 | EXPECT_EQ("foo", fmt::format("{}", converible_to_anything())); | |
f67539c2 | 1454 | } |
f67539c2 | 1455 | |
20effc67 | 1456 | class Answer {}; |
f67539c2 | 1457 | |
11fdf7f2 | 1458 | FMT_BEGIN_NAMESPACE |
20effc67 | 1459 | template <> struct formatter<date> { |
11fdf7f2 | 1460 | template <typename ParseContext> |
9f95a23c | 1461 | FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { |
11fdf7f2 | 1462 | auto it = ctx.begin(); |
20effc67 | 1463 | if (it != ctx.end() && *it == 'd') ++it; |
11fdf7f2 TL |
1464 | return it; |
1465 | } | |
1466 | ||
20effc67 | 1467 | auto format(const date& d, format_context& ctx) -> decltype(ctx.out()) { |
11fdf7f2 TL |
1468 | format_to(ctx.out(), "{}-{}-{}", d.year(), d.month(), d.day()); |
1469 | return ctx.out(); | |
1470 | } | |
1471 | }; | |
11fdf7f2 | 1472 | |
9f95a23c | 1473 | template <> struct formatter<Answer> : formatter<int> { |
11fdf7f2 | 1474 | template <typename FormatContext> |
9f95a23c | 1475 | auto format(Answer, FormatContext& ctx) -> decltype(ctx.out()) { |
11fdf7f2 TL |
1476 | return formatter<int>::format(42, ctx); |
1477 | } | |
1478 | }; | |
1479 | FMT_END_NAMESPACE | |
1480 | ||
20effc67 TL |
1481 | TEST(format_test, format_custom) { |
1482 | EXPECT_THROW_MSG(fmt::format(runtime("{:s}"), date(2012, 12, 9)), | |
1483 | format_error, "unknown format specifier"); | |
1484 | EXPECT_EQ("42", fmt::format("{0}", Answer())); | |
1485 | EXPECT_EQ("0042", fmt::format("{:04}", Answer())); | |
11fdf7f2 TL |
1486 | } |
1487 | ||
20effc67 | 1488 | TEST(format_test, format_to_custom) { |
11fdf7f2 | 1489 | char buf[10] = {}; |
9f95a23c | 1490 | auto end = |
f67539c2 | 1491 | &*fmt::format_to(fmt::detail::make_checked(buf, 10), "{}", Answer()); |
11fdf7f2 TL |
1492 | EXPECT_EQ(end, buf + 2); |
1493 | EXPECT_STREQ(buf, "42"); | |
1494 | } | |
1495 | ||
20effc67 | 1496 | TEST(format_test, format_string_from_speed_test) { |
11fdf7f2 | 1497 | EXPECT_EQ("1.2340000000:0042:+3.13:str:0x3e8:X:%", |
20effc67 TL |
1498 | fmt::format("{0:0.10f}:{1:04}:{2:+g}:{3}:{4}:{5}:%", 1.234, 42, |
1499 | 3.13, "str", reinterpret_cast<void*>(1000), 'X')); | |
11fdf7f2 TL |
1500 | } |
1501 | ||
20effc67 TL |
1502 | TEST(format_test, format_examples) { |
1503 | std::string message = fmt::format("The answer is {}", 42); | |
11fdf7f2 TL |
1504 | EXPECT_EQ("The answer is 42", message); |
1505 | ||
20effc67 | 1506 | EXPECT_EQ("42", fmt::format("{}", 42)); |
11fdf7f2 TL |
1507 | |
1508 | memory_buffer out; | |
20effc67 | 1509 | format_to(std::back_inserter(out), "The answer is {}.", 42); |
11fdf7f2 TL |
1510 | EXPECT_EQ("The answer is 42.", to_string(out)); |
1511 | ||
9f95a23c TL |
1512 | const char* filename = "nonexistent"; |
1513 | FILE* ftest = safe_fopen(filename, "r"); | |
11fdf7f2 TL |
1514 | if (ftest) fclose(ftest); |
1515 | int error_code = errno; | |
f67539c2 | 1516 | EXPECT_TRUE(ftest == nullptr); |
9f95a23c TL |
1517 | EXPECT_SYSTEM_ERROR( |
1518 | { | |
1519 | FILE* f = safe_fopen(filename, "r"); | |
1520 | if (!f) | |
1521 | throw fmt::system_error(errno, "Cannot open file '{}'", filename); | |
1522 | fclose(f); | |
1523 | }, | |
1524 | error_code, "Cannot open file 'nonexistent'"); | |
11fdf7f2 | 1525 | |
11fdf7f2 | 1526 | EXPECT_EQ("First, thou shalt count to three", |
20effc67 TL |
1527 | fmt::format("First, thou shalt count to {0}", "three")); |
1528 | EXPECT_EQ("Bring me a shrubbery", fmt::format("Bring me a {}", "shrubbery")); | |
1529 | EXPECT_EQ("From 1 to 3", fmt::format("From {} to {}", 1, 3)); | |
11fdf7f2 | 1530 | |
20effc67 | 1531 | char buffer[buffer_size]; |
11fdf7f2 | 1532 | safe_sprintf(buffer, "%03.2f", -1.2); |
20effc67 | 1533 | EXPECT_EQ(buffer, fmt::format("{:03.2f}", -1.2)); |
11fdf7f2 | 1534 | |
20effc67 TL |
1535 | EXPECT_EQ("a, b, c", fmt::format("{0}, {1}, {2}", 'a', 'b', 'c')); |
1536 | EXPECT_EQ("a, b, c", fmt::format("{}, {}, {}", 'a', 'b', 'c')); | |
1537 | EXPECT_EQ("c, b, a", fmt::format("{2}, {1}, {0}", 'a', 'b', 'c')); | |
1538 | EXPECT_EQ("abracadabra", fmt::format("{0}{1}{0}", "abra", "cad")); | |
11fdf7f2 | 1539 | |
20effc67 TL |
1540 | EXPECT_EQ("left aligned ", |
1541 | fmt::format("{:<30}", "left aligned")); | |
11fdf7f2 | 1542 | EXPECT_EQ(" right aligned", |
20effc67 TL |
1543 | fmt::format("{:>30}", "right aligned")); |
1544 | EXPECT_EQ(" centered ", | |
1545 | fmt::format("{:^30}", "centered")); | |
1546 | EXPECT_EQ("***********centered***********", | |
1547 | fmt::format("{:*^30}", "centered")); | |
9f95a23c | 1548 | |
20effc67 TL |
1549 | EXPECT_EQ("+3.140000; -3.140000", fmt::format("{:+f}; {:+f}", 3.14, -3.14)); |
1550 | EXPECT_EQ(" 3.140000; -3.140000", fmt::format("{: f}; {: f}", 3.14, -3.14)); | |
1551 | EXPECT_EQ("3.140000; -3.140000", fmt::format("{:-f}; {:-f}", 3.14, -3.14)); | |
11fdf7f2 TL |
1552 | |
1553 | EXPECT_EQ("int: 42; hex: 2a; oct: 52", | |
20effc67 | 1554 | fmt::format("int: {0:d}; hex: {0:x}; oct: {0:o}", 42)); |
11fdf7f2 | 1555 | EXPECT_EQ("int: 42; hex: 0x2a; oct: 052", |
20effc67 | 1556 | fmt::format("int: {0:d}; hex: {0:#x}; oct: {0:#o}", 42)); |
11fdf7f2 | 1557 | |
20effc67 TL |
1558 | EXPECT_EQ("The answer is 42", fmt::format("The answer is {}", 42)); |
1559 | EXPECT_THROW_MSG(fmt::format(runtime("The answer is {:d}"), "forty-two"), | |
1560 | format_error, "invalid type specifier"); | |
11fdf7f2 | 1561 | |
9f95a23c TL |
1562 | EXPECT_WRITE( |
1563 | stdout, fmt::print("{}", std::numeric_limits<double>::infinity()), "inf"); | |
11fdf7f2 TL |
1564 | } |
1565 | ||
20effc67 | 1566 | TEST(format_test, print) { |
11fdf7f2 | 1567 | EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!"); |
9f95a23c TL |
1568 | EXPECT_WRITE(stderr, fmt::print(stderr, "Don't {}!", "panic"), |
1569 | "Don't panic!"); | |
11fdf7f2 TL |
1570 | } |
1571 | ||
20effc67 TL |
1572 | TEST(format_test, variadic) { |
1573 | EXPECT_EQ("abc1", fmt::format("{}c{}", "ab", 1)); | |
11fdf7f2 TL |
1574 | } |
1575 | ||
20effc67 TL |
1576 | TEST(format_test, dynamic) { |
1577 | using ctx = fmt::format_context; | |
1578 | auto args = std::vector<fmt::basic_format_arg<ctx>>(); | |
f67539c2 TL |
1579 | args.emplace_back(fmt::detail::make_arg<ctx>(42)); |
1580 | args.emplace_back(fmt::detail::make_arg<ctx>("abc1")); | |
1581 | args.emplace_back(fmt::detail::make_arg<ctx>(1.5f)); | |
11fdf7f2 | 1582 | |
9f95a23c | 1583 | std::string result = fmt::vformat( |
f67539c2 | 1584 | "{} and {} and {}", |
20effc67 | 1585 | fmt::format_args(args.data(), static_cast<int>(args.size()))); |
11fdf7f2 | 1586 | |
9f95a23c | 1587 | EXPECT_EQ("42 and abc1 and 1.5", result); |
11fdf7f2 TL |
1588 | } |
1589 | ||
20effc67 | 1590 | TEST(format_test, bytes) { |
f67539c2 TL |
1591 | auto s = fmt::format("{:10}", fmt::bytes("ёжик")); |
1592 | EXPECT_EQ("ёжик ", s); | |
1593 | EXPECT_EQ(10, s.size()); | |
1594 | } | |
1595 | ||
20effc67 TL |
1596 | enum test_enum { foo, bar }; |
1597 | ||
1598 | TEST(format_test, join) { | |
11fdf7f2 | 1599 | using fmt::join; |
9f95a23c | 1600 | int v1[3] = {1, 2, 3}; |
20effc67 | 1601 | auto v2 = std::vector<float>(); |
11fdf7f2 TL |
1602 | v2.push_back(1.2f); |
1603 | v2.push_back(3.4f); | |
9f95a23c | 1604 | void* v3[2] = {&v1[0], &v1[1]}; |
11fdf7f2 | 1605 | |
20effc67 TL |
1606 | EXPECT_EQ("(1, 2, 3)", fmt::format("({})", join(v1, v1 + 3, ", "))); |
1607 | EXPECT_EQ("(1)", fmt::format("({})", join(v1, v1 + 1, ", "))); | |
1608 | EXPECT_EQ("()", fmt::format("({})", join(v1, v1, ", "))); | |
1609 | EXPECT_EQ("(001, 002, 003)", fmt::format("({:03})", join(v1, v1 + 3, ", "))); | |
11fdf7f2 | 1610 | EXPECT_EQ("(+01.20, +03.40)", |
20effc67 | 1611 | fmt::format("({:+06.2f})", join(v2.begin(), v2.end(), ", "))); |
11fdf7f2 | 1612 | |
20effc67 | 1613 | EXPECT_EQ("1, 2, 3", fmt::format("{0:{1}}", join(v1, v1 + 3, ", "), 1)); |
11fdf7f2 | 1614 | |
20effc67 TL |
1615 | EXPECT_EQ(fmt::format("{}, {}", v3[0], v3[1]), |
1616 | fmt::format("{}", join(v3, v3 + 2, ", "))); | |
11fdf7f2 | 1617 | |
20effc67 TL |
1618 | EXPECT_EQ("(1, 2, 3)", fmt::format("({})", join(v1, ", "))); |
1619 | EXPECT_EQ("(+01.20, +03.40)", fmt::format("({:+06.2f})", join(v2, ", "))); | |
11fdf7f2 | 1620 | |
20effc67 TL |
1621 | auto v4 = std::vector<test_enum>{foo, bar, foo}; |
1622 | EXPECT_EQ("0 1 0", fmt::format("{}", join(v4, " "))); | |
11fdf7f2 TL |
1623 | } |
1624 | ||
20effc67 TL |
1625 | #ifdef __cpp_lib_byte |
1626 | TEST(format_test, join_bytes) { | |
1627 | auto v = std::vector<std::byte>{std::byte(1), std::byte(2), std::byte(3)}; | |
1628 | EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join(v, ", "))); | |
11fdf7f2 | 1629 | } |
20effc67 | 1630 | #endif |
11fdf7f2 | 1631 | |
9f95a23c | 1632 | std::string vformat_message(int id, const char* format, fmt::format_args args) { |
20effc67 TL |
1633 | auto buffer = fmt::memory_buffer(); |
1634 | format_to(fmt::appender(buffer), "[{}] ", id); | |
1635 | vformat_to(fmt::appender(buffer), format, args); | |
11fdf7f2 TL |
1636 | return to_string(buffer); |
1637 | } | |
1638 | ||
1639 | template <typename... Args> | |
9f95a23c | 1640 | std::string format_message(int id, const char* format, const Args&... args) { |
11fdf7f2 TL |
1641 | auto va = fmt::make_format_args(args...); |
1642 | return vformat_message(id, format, va); | |
1643 | } | |
1644 | ||
20effc67 | 1645 | TEST(format_test, format_message_example) { |
11fdf7f2 | 1646 | EXPECT_EQ("[42] something happened", |
9f95a23c | 1647 | format_message(42, "{} happened", "something")); |
11fdf7f2 TL |
1648 | } |
1649 | ||
9f95a23c TL |
1650 | template <typename... Args> |
1651 | void print_error(const char* file, int line, const char* format, | |
1652 | const Args&... args) { | |
11fdf7f2 TL |
1653 | fmt::print("{}: {}: ", file, line); |
1654 | fmt::print(format, args...); | |
1655 | } | |
1656 | ||
20effc67 | 1657 | TEST(format_test, unpacked_args) { |
11fdf7f2 | 1658 | EXPECT_EQ("0123456789abcdefg", |
9f95a23c TL |
1659 | fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 0, 1, 2, 3, 4, 5, |
1660 | 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g')); | |
11fdf7f2 TL |
1661 | } |
1662 | ||
f67539c2 TL |
1663 | struct string_like {}; |
1664 | fmt::string_view to_string_view(string_like) { return "foo"; } | |
1665 | ||
1666 | constexpr char with_null[3] = {'{', '}', '\0'}; | |
1667 | constexpr char no_null[2] = {'{', '}'}; | |
20effc67 TL |
1668 | static FMT_CONSTEXPR_DECL const char static_with_null[3] = {'{', '}', '\0'}; |
1669 | static FMT_CONSTEXPR_DECL const char static_no_null[2] = {'{', '}'}; | |
f67539c2 | 1670 | |
20effc67 TL |
1671 | TEST(format_test, compile_time_string) { |
1672 | EXPECT_EQ("foo", fmt::format(FMT_STRING("foo"))); | |
f67539c2 | 1673 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42)); |
f67539c2 | 1674 | EXPECT_EQ("foo", fmt::format(FMT_STRING("{}"), string_like())); |
20effc67 TL |
1675 | |
1676 | #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | |
1677 | using namespace fmt::literals; | |
1678 | EXPECT_EQ("foobar", fmt::format(FMT_STRING("{foo}{bar}"), "bar"_a = "bar", | |
1679 | "foo"_a = "foo")); | |
1680 | EXPECT_EQ("", fmt::format(FMT_STRING(""))); | |
1681 | EXPECT_EQ("", fmt::format(FMT_STRING(""), "arg"_a = 42)); | |
1682 | #endif | |
1683 | ||
1684 | (void)static_with_null; | |
1685 | (void)static_no_null; | |
1686 | #ifndef _MSC_VER | |
1687 | EXPECT_EQ("42", fmt::format(FMT_STRING(static_with_null), 42)); | |
1688 | EXPECT_EQ("42", fmt::format(FMT_STRING(static_no_null), 42)); | |
1689 | #endif | |
1690 | ||
f67539c2 TL |
1691 | (void)with_null; |
1692 | (void)no_null; | |
1693 | #if __cplusplus >= 201703L | |
1694 | EXPECT_EQ("42", fmt::format(FMT_STRING(with_null), 42)); | |
1695 | EXPECT_EQ("42", fmt::format(FMT_STRING(no_null), 42)); | |
1696 | #endif | |
1697 | #if defined(FMT_USE_STRING_VIEW) && __cplusplus >= 201703L | |
1698 | EXPECT_EQ("42", fmt::format(FMT_STRING(std::string_view("{}")), 42)); | |
f67539c2 TL |
1699 | #endif |
1700 | } | |
1701 | ||
20effc67 | 1702 | TEST(format_test, custom_format_compile_time_string) { |
f67539c2 | 1703 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), Answer())); |
20effc67 | 1704 | auto answer = Answer(); |
f67539c2 TL |
1705 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), answer)); |
1706 | char buf[10] = {}; | |
1707 | fmt::format_to(buf, FMT_STRING("{}"), answer); | |
1708 | const Answer const_answer = Answer(); | |
1709 | EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), const_answer)); | |
1710 | } | |
1711 | ||
11fdf7f2 TL |
1712 | #if FMT_USE_USER_DEFINED_LITERALS |
1713 | // Passing user-defined literals directly to EXPECT_EQ causes problems | |
1714 | // with macro argument stringification (#) on some versions of GCC. | |
1715 | // Workaround: Assing the UDL result to a variable before the macro. | |
1716 | ||
1717 | using namespace fmt::literals; | |
1718 | ||
20effc67 TL |
1719 | TEST(format_test, format_udl) { |
1720 | EXPECT_EQ("{}c{}"_format("ab", 1), fmt::format("{}c{}", "ab", 1)); | |
1721 | EXPECT_EQ("foo"_format(), "foo"); | |
1722 | EXPECT_EQ("{0:10}"_format(42), " 42"); | |
1723 | EXPECT_EQ("{}"_format(date(2015, 10, 21)), "2015-10-21"); | |
f67539c2 TL |
1724 | } |
1725 | ||
20effc67 TL |
1726 | TEST(format_test, named_arg_udl) { |
1727 | auto udl_a = fmt::format("{first}{second}{first}{third}", "first"_a = "abra", | |
1728 | "second"_a = "cad", "third"_a = 99); | |
1729 | EXPECT_EQ( | |
1730 | fmt::format("{first}{second}{first}{third}", fmt::arg("first", "abra"), | |
1731 | fmt::arg("second", "cad"), fmt::arg("third", 99)), | |
1732 | udl_a); | |
11fdf7f2 | 1733 | } |
9f95a23c | 1734 | #endif // FMT_USE_USER_DEFINED_LITERALS |
11fdf7f2 | 1735 | |
20effc67 | 1736 | TEST(format_test, enum) { EXPECT_EQ("0", fmt::format("{}", foo)); } |
11fdf7f2 | 1737 | |
20effc67 TL |
1738 | TEST(format_test, formatter_not_specialized) { |
1739 | static_assert(!fmt::has_formatter<fmt::formatter<test_enum>, | |
1740 | fmt::format_context>::value, | |
1741 | ""); | |
11fdf7f2 TL |
1742 | } |
1743 | ||
1744 | #if FMT_HAS_FEATURE(cxx_strong_enums) | |
f67539c2 | 1745 | enum big_enum : unsigned long long { big_enum_value = 5000000000ULL }; |
11fdf7f2 | 1746 | |
20effc67 | 1747 | TEST(format_test, strong_enum) { |
f67539c2 TL |
1748 | EXPECT_EQ("5000000000", fmt::format("{}", big_enum_value)); |
1749 | } | |
11fdf7f2 TL |
1750 | #endif |
1751 | ||
20effc67 TL |
1752 | TEST(format_test, non_null_terminated_format_string) { |
1753 | EXPECT_EQ("42", fmt::format(string_view("{}foo", 2), 42)); | |
11fdf7f2 TL |
1754 | } |
1755 | ||
1756 | struct variant { | |
20effc67 TL |
1757 | enum { int_type, string_type } type; |
1758 | explicit variant(int) : type(int_type) {} | |
1759 | explicit variant(const char*) : type(string_type) {} | |
11fdf7f2 TL |
1760 | }; |
1761 | ||
1762 | FMT_BEGIN_NAMESPACE | |
9f95a23c | 1763 | template <> struct formatter<variant> : dynamic_formatter<> { |
11fdf7f2 | 1764 | auto format(variant value, format_context& ctx) -> decltype(ctx.out()) { |
20effc67 TL |
1765 | if (value.type == variant::int_type) |
1766 | return dynamic_formatter<>::format(42, ctx); | |
11fdf7f2 TL |
1767 | return dynamic_formatter<>::format("foo", ctx); |
1768 | } | |
1769 | }; | |
1770 | FMT_END_NAMESPACE | |
1771 | ||
20effc67 | 1772 | TEST(format_test, dynamic_formatter) { |
11fdf7f2 TL |
1773 | auto num = variant(42); |
1774 | auto str = variant("foo"); | |
20effc67 TL |
1775 | EXPECT_EQ("42", fmt::format("{:d}", num)); |
1776 | EXPECT_EQ("foo", fmt::format("{:s}", str)); | |
1777 | EXPECT_EQ(" 42 foo ", fmt::format("{:{}} {:{}}", num, 3, str, 4)); | |
1778 | EXPECT_THROW_MSG(fmt::format(runtime("{0:{}}"), num), format_error, | |
9f95a23c | 1779 | "cannot switch from manual to automatic argument indexing"); |
20effc67 | 1780 | EXPECT_THROW_MSG(fmt::format(runtime("{:{0}}"), num), format_error, |
9f95a23c | 1781 | "cannot switch from automatic to manual argument indexing"); |
20effc67 | 1782 | EXPECT_THROW_MSG(fmt::format(runtime("{:+}"), str), format_error, |
9f95a23c | 1783 | "format specifier requires numeric argument"); |
20effc67 | 1784 | EXPECT_THROW_MSG(fmt::format(runtime("{:-}"), str), format_error, |
9f95a23c | 1785 | "format specifier requires numeric argument"); |
20effc67 | 1786 | EXPECT_THROW_MSG(fmt::format(runtime("{: }"), str), format_error, |
9f95a23c | 1787 | "format specifier requires numeric argument"); |
20effc67 | 1788 | EXPECT_THROW_MSG(fmt::format(runtime("{:#}"), str), format_error, |
9f95a23c | 1789 | "format specifier requires numeric argument"); |
20effc67 | 1790 | EXPECT_THROW_MSG(fmt::format(runtime("{:0}"), str), format_error, |
9f95a23c | 1791 | "format specifier requires numeric argument"); |
20effc67 | 1792 | EXPECT_THROW_MSG(fmt::format(runtime("{:.2}"), num), format_error, |
9f95a23c | 1793 | "precision not allowed for this argument type"); |
11fdf7f2 TL |
1794 | } |
1795 | ||
20effc67 TL |
1796 | namespace adl_test { |
1797 | namespace fmt { | |
1798 | namespace detail { | |
1799 | struct foo {}; | |
1800 | template <typename, typename OutputIt> void write(OutputIt, foo) = delete; | |
1801 | } // namespace detail | |
1802 | } // namespace fmt | |
1803 | } // namespace adl_test | |
1804 | ||
1805 | FMT_BEGIN_NAMESPACE | |
1806 | template <> | |
1807 | struct formatter<adl_test::fmt::detail::foo> : formatter<std::string> { | |
1808 | template <typename FormatContext> | |
1809 | auto format(adl_test::fmt::detail::foo, FormatContext& ctx) | |
1810 | -> decltype(ctx.out()) { | |
1811 | return formatter<std::string>::format("foo", ctx); | |
1812 | } | |
1813 | }; | |
1814 | FMT_END_NAMESPACE | |
1815 | ||
1816 | TEST(format_test, to_string) { | |
11fdf7f2 TL |
1817 | EXPECT_EQ("42", fmt::to_string(42)); |
1818 | EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast<void*>(0x1234))); | |
20effc67 | 1819 | EXPECT_EQ("foo", fmt::to_string(adl_test::fmt::detail::foo())); |
11fdf7f2 | 1820 | |
20effc67 TL |
1821 | enum test_enum2 : unsigned char { test_value }; |
1822 | EXPECT_EQ("0", fmt::to_string(test_value)); | |
1823 | } | |
11fdf7f2 | 1824 | |
20effc67 | 1825 | TEST(format_test, output_iterators) { |
11fdf7f2 TL |
1826 | std::list<char> out; |
1827 | fmt::format_to(std::back_inserter(out), "{}", 42); | |
1828 | EXPECT_EQ("42", std::string(out.begin(), out.end())); | |
1829 | std::stringstream s; | |
1830 | fmt::format_to(std::ostream_iterator<char>(s), "{}", 42); | |
1831 | EXPECT_EQ("42", s.str()); | |
1832 | } | |
1833 | ||
20effc67 | 1834 | TEST(format_test, formatted_size) { |
11fdf7f2 TL |
1835 | EXPECT_EQ(2u, fmt::formatted_size("{}", 42)); |
1836 | } | |
1837 | ||
20effc67 TL |
1838 | TEST(format_test, format_to_no_args) { |
1839 | std::string s; | |
1840 | fmt::format_to(std::back_inserter(s), "test"); | |
1841 | EXPECT_EQ("test", s); | |
1842 | } | |
1843 | ||
1844 | TEST(format_test, format_to) { | |
1845 | std::string s; | |
1846 | fmt::format_to(std::back_inserter(s), "part{0}", 1); | |
1847 | EXPECT_EQ("part1", s); | |
1848 | fmt::format_to(std::back_inserter(s), "part{0}", 2); | |
1849 | EXPECT_EQ("part1part2", s); | |
1850 | } | |
1851 | ||
1852 | TEST(format_test, format_to_memory_buffer) { | |
1853 | auto buf = fmt::basic_memory_buffer<char, 100>(); | |
1854 | fmt::format_to(fmt::appender(buf), "{}", "foo"); | |
1855 | EXPECT_EQ("foo", to_string(buf)); | |
1856 | } | |
1857 | ||
1858 | TEST(format_test, format_to_vector) { | |
1859 | std::vector<char> v; | |
1860 | fmt::format_to(std::back_inserter(v), "{}", "foo"); | |
1861 | EXPECT_EQ(string_view(v.data(), v.size()), "foo"); | |
1862 | } | |
1863 | ||
1864 | struct nongrowing_container { | |
1865 | using value_type = char; | |
1866 | void push_back(char) { throw std::runtime_error("can't take it any more"); } | |
1867 | }; | |
1868 | ||
1869 | TEST(format_test, format_to_propagates_exceptions) { | |
1870 | auto c = nongrowing_container(); | |
1871 | EXPECT_THROW(fmt::format_to(std::back_inserter(c), "{}", 42), | |
1872 | std::runtime_error); | |
1873 | } | |
1874 | ||
1875 | TEST(format_test, format_to_n) { | |
11fdf7f2 TL |
1876 | char buffer[4]; |
1877 | buffer[3] = 'x'; | |
1878 | auto result = fmt::format_to_n(buffer, 3, "{}", 12345); | |
1879 | EXPECT_EQ(5u, result.size); | |
1880 | EXPECT_EQ(buffer + 3, result.out); | |
1881 | EXPECT_EQ("123x", fmt::string_view(buffer, 4)); | |
20effc67 | 1882 | |
11fdf7f2 TL |
1883 | result = fmt::format_to_n(buffer, 3, "{:s}", "foobar"); |
1884 | EXPECT_EQ(6u, result.size); | |
1885 | EXPECT_EQ(buffer + 3, result.out); | |
1886 | EXPECT_EQ("foox", fmt::string_view(buffer, 4)); | |
20effc67 | 1887 | |
9f95a23c TL |
1888 | buffer[0] = 'x'; |
1889 | buffer[1] = 'x'; | |
1890 | buffer[2] = 'x'; | |
1891 | result = fmt::format_to_n(buffer, 3, "{}", 'A'); | |
1892 | EXPECT_EQ(1u, result.size); | |
1893 | EXPECT_EQ(buffer + 1, result.out); | |
1894 | EXPECT_EQ("Axxx", fmt::string_view(buffer, 4)); | |
20effc67 | 1895 | |
9f95a23c TL |
1896 | result = fmt::format_to_n(buffer, 3, "{}{} ", 'B', 'C'); |
1897 | EXPECT_EQ(3u, result.size); | |
1898 | EXPECT_EQ(buffer + 3, result.out); | |
1899 | EXPECT_EQ("BC x", fmt::string_view(buffer, 4)); | |
11fdf7f2 | 1900 | |
20effc67 | 1901 | result = fmt::format_to_n(buffer, 4, "{}", "ABCDE"); |
11fdf7f2 | 1902 | EXPECT_EQ(5u, result.size); |
20effc67 TL |
1903 | EXPECT_EQ("ABCD", fmt::string_view(buffer, 4)); |
1904 | ||
1905 | buffer[3] = 'x'; | |
1906 | result = fmt::format_to_n(buffer, 3, "{}", std::string(1000, '*')); | |
1907 | EXPECT_EQ(1000u, result.size); | |
1908 | EXPECT_EQ("***x", fmt::string_view(buffer, 4)); | |
11fdf7f2 TL |
1909 | } |
1910 | ||
f67539c2 TL |
1911 | struct test_output_iterator { |
1912 | char* data; | |
1913 | ||
1914 | using iterator_category = std::output_iterator_tag; | |
1915 | using value_type = void; | |
1916 | using difference_type = void; | |
1917 | using pointer = void; | |
1918 | using reference = void; | |
1919 | ||
1920 | test_output_iterator& operator++() { | |
1921 | ++data; | |
1922 | return *this; | |
1923 | } | |
1924 | test_output_iterator operator++(int) { | |
1925 | auto tmp = *this; | |
1926 | ++data; | |
1927 | return tmp; | |
1928 | } | |
1929 | char& operator*() { return *data; } | |
1930 | }; | |
1931 | ||
20effc67 | 1932 | TEST(format_test, format_to_n_output_iterator) { |
f67539c2 TL |
1933 | char buf[10] = {}; |
1934 | fmt::format_to_n(test_output_iterator{buf}, 10, "{}", 42); | |
1935 | EXPECT_STREQ(buf, "42"); | |
1936 | } | |
1937 | ||
11fdf7f2 | 1938 | #if FMT_USE_CONSTEXPR |
11fdf7f2 | 1939 | struct test_error_handler { |
9f95a23c | 1940 | const char*& error; |
11fdf7f2 | 1941 | |
9f95a23c | 1942 | FMT_CONSTEXPR test_error_handler(const char*& err) : error(err) {} |
11fdf7f2 | 1943 | |
9f95a23c TL |
1944 | FMT_CONSTEXPR test_error_handler(const test_error_handler& other) |
1945 | : error(other.error) {} | |
11fdf7f2 | 1946 | |
9f95a23c TL |
1947 | FMT_CONSTEXPR void on_error(const char* message) { |
1948 | if (!error) error = message; | |
11fdf7f2 TL |
1949 | } |
1950 | }; | |
1951 | ||
9f95a23c | 1952 | FMT_CONSTEXPR size_t len(const char* s) { |
11fdf7f2 | 1953 | size_t len = 0; |
9f95a23c | 1954 | while (*s++) ++len; |
11fdf7f2 TL |
1955 | return len; |
1956 | } | |
1957 | ||
9f95a23c TL |
1958 | FMT_CONSTEXPR bool equal(const char* s1, const char* s2) { |
1959 | if (!s1 || !s2) return s1 == s2; | |
11fdf7f2 TL |
1960 | while (*s1 && *s1 == *s2) { |
1961 | ++s1; | |
1962 | ++s2; | |
1963 | } | |
1964 | return *s1 == *s2; | |
1965 | } | |
1966 | ||
1967 | template <typename... Args> | |
9f95a23c | 1968 | FMT_CONSTEXPR bool test_error(const char* fmt, const char* expected_error) { |
f67539c2 | 1969 | const char* actual_error = nullptr; |
20effc67 TL |
1970 | auto s = string_view(fmt, len(fmt)); |
1971 | auto checker = | |
1972 | fmt::detail::format_string_checker<char, test_error_handler, Args...>( | |
1973 | s, test_error_handler(actual_error)); | |
f67539c2 | 1974 | fmt::detail::parse_format_string<true>(s, checker); |
11fdf7f2 TL |
1975 | return equal(actual_error, expected_error); |
1976 | } | |
1977 | ||
9f95a23c TL |
1978 | # define EXPECT_ERROR_NOARGS(fmt, error) \ |
1979 | static_assert(test_error(fmt, error), "") | |
1980 | # define EXPECT_ERROR(fmt, error, ...) \ | |
1981 | static_assert(test_error<__VA_ARGS__>(fmt, error), "") | |
11fdf7f2 | 1982 | |
20effc67 | 1983 | TEST(format_test, format_string_errors) { |
f67539c2 | 1984 | EXPECT_ERROR_NOARGS("foo", nullptr); |
11fdf7f2 | 1985 | EXPECT_ERROR_NOARGS("}", "unmatched '}' in format string"); |
20effc67 | 1986 | EXPECT_ERROR("{0:s", "unknown format specifier", date); |
f67539c2 TL |
1987 | # if !FMT_MSC_VER || FMT_MSC_VER >= 1916 |
1988 | // This causes an detail compiler error in MSVC2017. | |
11fdf7f2 TL |
1989 | EXPECT_ERROR("{:{<}", "invalid fill character '{'", int); |
1990 | EXPECT_ERROR("{:10000000000}", "number is too big", int); | |
1991 | EXPECT_ERROR("{:.10000000000}", "number is too big", int); | |
f67539c2 | 1992 | EXPECT_ERROR_NOARGS("{:x}", "argument not found"); |
11fdf7f2 | 1993 | EXPECT_ERROR("{:+}", "format specifier requires numeric argument", |
9f95a23c | 1994 | const char*); |
11fdf7f2 | 1995 | EXPECT_ERROR("{:-}", "format specifier requires numeric argument", |
9f95a23c | 1996 | const char*); |
11fdf7f2 | 1997 | EXPECT_ERROR("{:#}", "format specifier requires numeric argument", |
9f95a23c | 1998 | const char*); |
11fdf7f2 | 1999 | EXPECT_ERROR("{: }", "format specifier requires numeric argument", |
9f95a23c | 2000 | const char*); |
11fdf7f2 | 2001 | EXPECT_ERROR("{:0}", "format specifier requires numeric argument", |
9f95a23c | 2002 | const char*); |
11fdf7f2 TL |
2003 | EXPECT_ERROR("{:+}", "format specifier requires signed argument", unsigned); |
2004 | EXPECT_ERROR("{:-}", "format specifier requires signed argument", unsigned); | |
2005 | EXPECT_ERROR("{: }", "format specifier requires signed argument", unsigned); | |
f67539c2 TL |
2006 | EXPECT_ERROR("{:{}}", "argument not found", int); |
2007 | EXPECT_ERROR("{:.{}}", "argument not found", double); | |
11fdf7f2 TL |
2008 | EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int); |
2009 | EXPECT_ERROR("{:s}", "invalid type specifier", int); | |
11fdf7f2 TL |
2010 | EXPECT_ERROR("{:s}", "invalid type specifier", char); |
2011 | EXPECT_ERROR("{:+}", "invalid format specifier for char", char); | |
2012 | EXPECT_ERROR("{:s}", "invalid type specifier", double); | |
9f95a23c | 2013 | EXPECT_ERROR("{:d}", "invalid type specifier", const char*); |
11fdf7f2 | 2014 | EXPECT_ERROR("{:d}", "invalid type specifier", std::string); |
9f95a23c | 2015 | EXPECT_ERROR("{:s}", "invalid type specifier", void*); |
f67539c2 TL |
2016 | # else |
2017 | fmt::print("warning: constexpr is broken in this version of MSVC\n"); | |
9f95a23c | 2018 | # endif |
20effc67 TL |
2019 | # if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS |
2020 | EXPECT_ERROR("{foo}", "named argument is not found", decltype("bar"_a = 42)); | |
2021 | EXPECT_ERROR("{foo}", "named argument is not found", | |
2022 | decltype(fmt::arg("foo", 42))); | |
2023 | # else | |
2024 | EXPECT_ERROR("{foo}", | |
2025 | "compile-time checks for named arguments require C++20 support", | |
9f95a23c | 2026 | int); |
20effc67 TL |
2027 | # endif |
2028 | EXPECT_ERROR_NOARGS("{10000000000}", "argument not found"); | |
11fdf7f2 TL |
2029 | EXPECT_ERROR_NOARGS("{0x}", "invalid format string"); |
2030 | EXPECT_ERROR_NOARGS("{-}", "invalid format string"); | |
2031 | EXPECT_ERROR("{:{0x}}", "invalid format string", int); | |
2032 | EXPECT_ERROR("{:{-}}", "invalid format string", int); | |
2033 | EXPECT_ERROR("{:.{0x}}", "invalid format string", int); | |
2034 | EXPECT_ERROR("{:.{-}}", "invalid format string", int); | |
2035 | EXPECT_ERROR("{:.x}", "missing precision specifier", int); | |
f67539c2 TL |
2036 | EXPECT_ERROR_NOARGS("{}", "argument not found"); |
2037 | EXPECT_ERROR("{1}", "argument not found", int); | |
11fdf7f2 | 2038 | EXPECT_ERROR("{1}{}", |
9f95a23c TL |
2039 | "cannot switch from manual to automatic argument indexing", int, |
2040 | int); | |
11fdf7f2 | 2041 | EXPECT_ERROR("{}{1}", |
9f95a23c TL |
2042 | "cannot switch from automatic to manual argument indexing", int, |
2043 | int); | |
11fdf7f2 | 2044 | } |
eafe8130 | 2045 | |
20effc67 TL |
2046 | TEST(format_test, vformat_to) { |
2047 | using context = fmt::format_context; | |
f67539c2 | 2048 | fmt::basic_format_arg<context> arg = fmt::detail::make_arg<context>(42); |
20effc67 TL |
2049 | auto args = fmt::basic_format_args<context>(&arg, 1); |
2050 | auto s = std::string(); | |
eafe8130 TL |
2051 | fmt::vformat_to(std::back_inserter(s), "{}", args); |
2052 | EXPECT_EQ("42", s); | |
2053 | s.clear(); | |
2054 | fmt::vformat_to(std::back_inserter(s), FMT_STRING("{}"), args); | |
2055 | EXPECT_EQ("42", s); | |
9f95a23c TL |
2056 | } |
2057 | ||
11fdf7f2 TL |
2058 | #endif // FMT_USE_CONSTEXPR |
2059 | ||
20effc67 | 2060 | TEST(format_test, char_traits_is_not_ambiguous) { |
f67539c2 TL |
2061 | // Test that we don't inject detail names into the std namespace. |
2062 | using namespace std; | |
20effc67 | 2063 | auto c = char_traits<char>::char_type(); |
f67539c2 TL |
2064 | (void)c; |
2065 | #if __cplusplus >= 201103L | |
20effc67 | 2066 | auto s = std::string(); |
f67539c2 TL |
2067 | auto lval = begin(s); |
2068 | (void)lval; | |
2069 | #endif | |
11fdf7f2 TL |
2070 | } |
2071 | ||
20effc67 | 2072 | struct check_back_appender {}; |
f67539c2 | 2073 | |
20effc67 TL |
2074 | FMT_BEGIN_NAMESPACE |
2075 | template <> struct formatter<check_back_appender> { | |
2076 | auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | |
2077 | return ctx.begin(); | |
2078 | } | |
f67539c2 | 2079 | |
20effc67 TL |
2080 | template <typename Context> |
2081 | auto format(check_back_appender, Context& ctx) -> decltype(ctx.out()) { | |
2082 | auto out = ctx.out(); | |
2083 | static_assert(std::is_same<decltype(++out), decltype(out)&>::value, | |
2084 | "needs to satisfy weakly_incrementable"); | |
2085 | *out = 'y'; | |
2086 | return ++out; | |
2087 | } | |
f67539c2 | 2088 | }; |
f67539c2 TL |
2089 | FMT_END_NAMESPACE |
2090 | ||
20effc67 TL |
2091 | TEST(format_test, back_insert_slicing) { |
2092 | EXPECT_EQ(fmt::format("{}", check_back_appender{}), "y"); | |
11fdf7f2 | 2093 | } |
eafe8130 | 2094 | |
20effc67 TL |
2095 | template <typename Char, typename T> bool check_enabled_formatter() { |
2096 | static_assert(std::is_default_constructible<fmt::formatter<T, Char>>::value, | |
2097 | ""); | |
2098 | return true; | |
eafe8130 | 2099 | } |
9f95a23c | 2100 | |
20effc67 TL |
2101 | template <typename Char, typename... T> void check_enabled_formatters() { |
2102 | auto dummy = {check_enabled_formatter<Char, T>()...}; | |
2103 | (void)dummy; | |
2104 | } | |
2105 | ||
2106 | TEST(format_test, test_formatters_enabled) { | |
2107 | check_enabled_formatters<char, bool, char, signed char, unsigned char, short, | |
2108 | unsigned short, int, unsigned, long, unsigned long, | |
2109 | long long, unsigned long long, float, double, | |
2110 | long double, void*, const void*, char*, const char*, | |
2111 | std::string, std::nullptr_t>(); | |
2112 | check_enabled_formatters<wchar_t, bool, wchar_t, signed char, unsigned char, | |
2113 | short, unsigned short, int, unsigned, long, | |
2114 | unsigned long, long long, unsigned long long, float, | |
2115 | double, long double, void*, const void*, wchar_t*, | |
2116 | const wchar_t*, std::wstring, std::nullptr_t>(); | |
2117 | } | |
2118 | ||
2119 | TEST(format_int_test, data) { | |
2120 | fmt::format_int format_int(42); | |
2121 | EXPECT_EQ("42", std::string(format_int.data(), format_int.size())); | |
2122 | } | |
2123 | ||
2124 | TEST(format_int_test, format_int) { | |
2125 | EXPECT_EQ("42", fmt::format_int(42).str()); | |
2126 | EXPECT_EQ(2u, fmt::format_int(42).size()); | |
2127 | EXPECT_EQ("-42", fmt::format_int(-42).str()); | |
2128 | EXPECT_EQ(3u, fmt::format_int(-42).size()); | |
2129 | EXPECT_EQ("42", fmt::format_int(42ul).str()); | |
2130 | EXPECT_EQ("-42", fmt::format_int(-42l).str()); | |
2131 | EXPECT_EQ("42", fmt::format_int(42ull).str()); | |
2132 | EXPECT_EQ("-42", fmt::format_int(-42ll).str()); | |
2133 | std::ostringstream os; | |
2134 | os << max_value<int64_t>(); | |
2135 | EXPECT_EQ(os.str(), fmt::format_int(max_value<int64_t>()).str()); | |
9f95a23c | 2136 | } |