1 /*
2 Utility tests.
3
4 Copyright (c) 2012-2014, Victor Zverovich
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "test-assert.h"
29
30 #include <cfloat>
31 #include <climits>
32 #include <cstring>
33 #include <functional>
34 #include <limits>
35
36 #if FMT_USE_TYPE_TRAITS
37 # include <type_traits>
38 #endif
39
40 #include "gmock/gmock.h"
41 #include "gtest-extra.h"
42 #include "mock-allocator.h"
43 #include "util.h"
44
45 // Check if format.h compiles with windows.h included.
46 #ifdef _WIN32
47 # include <windows.h>
48 #endif
49
50 #include "fmt/format.h"
51
52 #undef max
53
54 using fmt::StringRef;
55 using fmt::internal::Arg;
56 using fmt::Buffer;
57 using fmt::internal::MemoryBuffer;
58
59 using testing::Return;
60 using testing::StrictMock;
61
62 namespace {
63
64 struct Test {};
65
66 template <typename Char>
format_arg(fmt::BasicFormatter<Char> & f,const Char *,Test)67 void format_arg(fmt::BasicFormatter<Char> &f, const Char *, Test) {
68 f.writer() << "test";
69 }
70
71 template <typename Char, typename T>
make_arg(const T & value)72 Arg make_arg(const T &value) {
73 typedef fmt::internal::MakeValue< fmt::BasicFormatter<Char> > MakeValue;
74 Arg arg = MakeValue(value);
75 arg.type = static_cast<Arg::Type>(MakeValue::type(value));
76 return arg;
77 }
78 } // namespace
79
CheckForwarding(MockAllocator<int> & alloc,AllocatorRef<MockAllocator<int>> & ref)80 void CheckForwarding(
81 MockAllocator<int> &alloc, AllocatorRef< MockAllocator<int> > &ref) {
82 int mem;
83 // Check if value_type is properly defined.
84 AllocatorRef< MockAllocator<int> >::value_type *ptr = &mem;
85 // Check forwarding.
86 EXPECT_CALL(alloc, allocate(42, 0)).WillOnce(Return(ptr));
87 ref.allocate(42, 0);
88 EXPECT_CALL(alloc, deallocate(ptr, 42));
89 ref.deallocate(ptr, 42);
90 }
91
TEST(AllocatorTest,AllocatorRef)92 TEST(AllocatorTest, AllocatorRef) {
93 StrictMock< MockAllocator<int> > alloc;
94 typedef AllocatorRef< MockAllocator<int> > TestAllocatorRef;
95 TestAllocatorRef ref(&alloc);
96 // Check if AllocatorRef forwards to the underlying allocator.
97 CheckForwarding(alloc, ref);
98 TestAllocatorRef ref2(ref);
99 CheckForwarding(alloc, ref2);
100 TestAllocatorRef ref3;
101 EXPECT_EQ(0, ref3.get());
102 ref3 = ref;
103 CheckForwarding(alloc, ref3);
104 }
105
106 #if FMT_USE_TYPE_TRAITS
TEST(BufferTest,Noncopyable)107 TEST(BufferTest, Noncopyable) {
108 EXPECT_FALSE(std::is_copy_constructible<Buffer<char> >::value);
109 EXPECT_FALSE(std::is_copy_assignable<Buffer<char> >::value);
110 }
111
TEST(BufferTest,Nonmoveable)112 TEST(BufferTest, Nonmoveable) {
113 EXPECT_FALSE(std::is_move_constructible<Buffer<char> >::value);
114 EXPECT_FALSE(std::is_move_assignable<Buffer<char> >::value);
115 }
116 #endif
117
118 // A test buffer with a dummy grow method.
119 template <typename T>
120 struct TestBuffer : Buffer<T> {
growTestBuffer121 void grow(std::size_t size) { this->capacity_ = size; }
122 };
123
124 template <typename T>
125 struct MockBuffer : Buffer<T> {
126 MOCK_METHOD1(do_grow, void (std::size_t size));
127
growMockBuffer128 void grow(std::size_t size) {
129 this->capacity_ = size;
130 do_grow(size);
131 }
132
MockBufferMockBuffer133 MockBuffer() {}
MockBufferMockBuffer134 MockBuffer(T *ptr) : Buffer<T>(ptr) {}
MockBufferMockBuffer135 MockBuffer(T *ptr, std::size_t capacity) : Buffer<T>(ptr, capacity) {}
136 };
137
TEST(BufferTest,Ctor)138 TEST(BufferTest, Ctor) {
139 {
140 MockBuffer<int> buffer;
141 EXPECT_EQ(0, &buffer[0]);
142 EXPECT_EQ(0u, buffer.size());
143 EXPECT_EQ(0u, buffer.capacity());
144 }
145 {
146 int dummy;
147 MockBuffer<int> buffer(&dummy);
148 EXPECT_EQ(&dummy, &buffer[0]);
149 EXPECT_EQ(0u, buffer.size());
150 EXPECT_EQ(0u, buffer.capacity());
151 }
152 {
153 int dummy;
154 std::size_t capacity = std::numeric_limits<std::size_t>::max();
155 MockBuffer<int> buffer(&dummy, capacity);
156 EXPECT_EQ(&dummy, &buffer[0]);
157 EXPECT_EQ(0u, buffer.size());
158 EXPECT_EQ(capacity, buffer.capacity());
159 }
160 }
161
162 struct DyingBuffer : TestBuffer<int> {
163 MOCK_METHOD0(die, void());
~DyingBufferDyingBuffer164 ~DyingBuffer() { die(); }
165 };
166
TEST(BufferTest,VirtualDtor)167 TEST(BufferTest, VirtualDtor) {
168 typedef StrictMock<DyingBuffer> StictMockBuffer;
169 StictMockBuffer *mock_buffer = new StictMockBuffer();
170 EXPECT_CALL(*mock_buffer, die());
171 Buffer<int> *buffer = mock_buffer;
172 delete buffer;
173 }
174
TEST(BufferTest,Access)175 TEST(BufferTest, Access) {
176 char data[10];
177 MockBuffer<char> buffer(data, sizeof(data));
178 buffer[0] = 11;
179 EXPECT_EQ(11, buffer[0]);
180 buffer[3] = 42;
181 EXPECT_EQ(42, *(&buffer[0] + 3));
182 const Buffer<char> &const_buffer = buffer;
183 EXPECT_EQ(42, const_buffer[3]);
184 }
185
TEST(BufferTest,Resize)186 TEST(BufferTest, Resize) {
187 char data[123];
188 MockBuffer<char> buffer(data, sizeof(data));
189 buffer[10] = 42;
190 EXPECT_EQ(42, buffer[10]);
191 buffer.resize(20);
192 EXPECT_EQ(20u, buffer.size());
193 EXPECT_EQ(123u, buffer.capacity());
194 EXPECT_EQ(42, buffer[10]);
195 buffer.resize(5);
196 EXPECT_EQ(5u, buffer.size());
197 EXPECT_EQ(123u, buffer.capacity());
198 EXPECT_EQ(42, buffer[10]);
199 // Check if resize calls grow.
200 EXPECT_CALL(buffer, do_grow(124));
201 buffer.resize(124);
202 EXPECT_CALL(buffer, do_grow(200));
203 buffer.resize(200);
204 }
205
TEST(BufferTest,Clear)206 TEST(BufferTest, Clear) {
207 TestBuffer<char> buffer;
208 buffer.resize(20);
209 buffer.clear();
210 EXPECT_EQ(0u, buffer.size());
211 EXPECT_EQ(20u, buffer.capacity());
212 }
213
TEST(BufferTest,PushBack)214 TEST(BufferTest, PushBack) {
215 int data[15];
216 MockBuffer<int> buffer(data, 10);
217 buffer.push_back(11);
218 EXPECT_EQ(11, buffer[0]);
219 EXPECT_EQ(1u, buffer.size());
220 buffer.resize(10);
221 EXPECT_CALL(buffer, do_grow(11));
222 buffer.push_back(22);
223 EXPECT_EQ(22, buffer[10]);
224 EXPECT_EQ(11u, buffer.size());
225 }
226
TEST(BufferTest,Append)227 TEST(BufferTest, Append) {
228 char data[15];
229 MockBuffer<char> buffer(data, 10);
230 const char *test = "test";
231 buffer.append(test, test + 5);
232 EXPECT_STREQ(test, &buffer[0]);
233 EXPECT_EQ(5u, buffer.size());
234 buffer.resize(10);
235 EXPECT_CALL(buffer, do_grow(12));
236 buffer.append(test, test + 2);
237 EXPECT_EQ('t', buffer[10]);
238 EXPECT_EQ('e', buffer[11]);
239 EXPECT_EQ(12u, buffer.size());
240 }
241
TEST(BufferTest,AppendAllocatesEnoughStorage)242 TEST(BufferTest, AppendAllocatesEnoughStorage) {
243 char data[19];
244 MockBuffer<char> buffer(data, 10);
245 const char *test = "abcdefgh";
246 buffer.resize(10);
247 EXPECT_CALL(buffer, do_grow(19));
248 buffer.append(test, test + 9);
249 }
250
TEST(MemoryBufferTest,Ctor)251 TEST(MemoryBufferTest, Ctor) {
252 MemoryBuffer<char, 123> buffer;
253 EXPECT_EQ(0u, buffer.size());
254 EXPECT_EQ(123u, buffer.capacity());
255 }
256
257 #if FMT_USE_RVALUE_REFERENCES
258
259 typedef AllocatorRef< std::allocator<char> > TestAllocator;
260
check_move_buffer(const char * str,MemoryBuffer<char,5,TestAllocator> & buffer)261 void check_move_buffer(const char *str,
262 MemoryBuffer<char, 5, TestAllocator> &buffer) {
263 std::allocator<char> *alloc = buffer.get_allocator().get();
264 MemoryBuffer<char, 5, TestAllocator> buffer2(std::move(buffer));
265 // Move shouldn't destroy the inline content of the first buffer.
266 EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
267 EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
268 EXPECT_EQ(5u, buffer2.capacity());
269 // Move should transfer allocator.
270 EXPECT_EQ(0, buffer.get_allocator().get());
271 EXPECT_EQ(alloc, buffer2.get_allocator().get());
272 }
273
TEST(MemoryBufferTest,MoveCtor)274 TEST(MemoryBufferTest, MoveCtor) {
275 std::allocator<char> alloc;
276 MemoryBuffer<char, 5, TestAllocator> buffer((TestAllocator(&alloc)));
277 const char test[] = "test";
278 buffer.append(test, test + 4);
279 check_move_buffer("test", buffer);
280 // Adding one more character fills the inline buffer, but doesn't cause
281 // dynamic allocation.
282 buffer.push_back('a');
283 check_move_buffer("testa", buffer);
284 const char *inline_buffer_ptr = &buffer[0];
285 // Adding one more character causes the content to move from the inline to
286 // a dynamically allocated buffer.
287 buffer.push_back('b');
288 MemoryBuffer<char, 5, TestAllocator> buffer2(std::move(buffer));
289 // Move should rip the guts of the first buffer.
290 EXPECT_EQ(inline_buffer_ptr, &buffer[0]);
291 EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size()));
292 EXPECT_GT(buffer2.capacity(), 5u);
293 }
294
check_move_assign_buffer(const char * str,MemoryBuffer<char,5> & buffer)295 void check_move_assign_buffer(const char *str, MemoryBuffer<char, 5> &buffer) {
296 MemoryBuffer<char, 5> buffer2;
297 buffer2 = std::move(buffer);
298 // Move shouldn't destroy the inline content of the first buffer.
299 EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
300 EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
301 EXPECT_EQ(5u, buffer2.capacity());
302 }
303
TEST(MemoryBufferTest,MoveAssignment)304 TEST(MemoryBufferTest, MoveAssignment) {
305 MemoryBuffer<char, 5> buffer;
306 const char test[] = "test";
307 buffer.append(test, test + 4);
308 check_move_assign_buffer("test", buffer);
309 // Adding one more character fills the inline buffer, but doesn't cause
310 // dynamic allocation.
311 buffer.push_back('a');
312 check_move_assign_buffer("testa", buffer);
313 const char *inline_buffer_ptr = &buffer[0];
314 // Adding one more character causes the content to move from the inline to
315 // a dynamically allocated buffer.
316 buffer.push_back('b');
317 MemoryBuffer<char, 5> buffer2;
318 buffer2 = std::move(buffer);
319 // Move should rip the guts of the first buffer.
320 EXPECT_EQ(inline_buffer_ptr, &buffer[0]);
321 EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size()));
322 EXPECT_GT(buffer2.capacity(), 5u);
323 }
324
325 #endif // FMT_USE_RVALUE_REFERENCES
326
TEST(MemoryBufferTest,Grow)327 TEST(MemoryBufferTest, Grow) {
328 typedef AllocatorRef< MockAllocator<int> > Allocator;
329 typedef MemoryBuffer<int, 10, Allocator> Base;
330 MockAllocator<int> alloc;
331 struct TestMemoryBuffer : Base {
332 TestMemoryBuffer(Allocator alloc) : Base(alloc) {}
333 void grow(std::size_t size) { Base::grow(size); }
334 } buffer((Allocator(&alloc)));
335 buffer.resize(7);
336 using fmt::internal::to_unsigned;
337 for (int i = 0; i < 7; ++i)
338 buffer[to_unsigned(i)] = i * i;
339 EXPECT_EQ(10u, buffer.capacity());
340 int mem[20];
341 mem[7] = 0xdead;
342 EXPECT_CALL(alloc, allocate(20, 0)).WillOnce(Return(mem));
343 buffer.grow(20);
344 EXPECT_EQ(20u, buffer.capacity());
345 // Check if size elements have been copied
346 for (int i = 0; i < 7; ++i)
347 EXPECT_EQ(i * i, buffer[to_unsigned(i)]);
348 // and no more than that.
349 EXPECT_EQ(0xdead, buffer[7]);
350 EXPECT_CALL(alloc, deallocate(mem, 20));
351 }
352
TEST(MemoryBufferTest,Allocator)353 TEST(MemoryBufferTest, Allocator) {
354 typedef AllocatorRef< MockAllocator<char> > TestAllocator;
355 MemoryBuffer<char, 10, TestAllocator> buffer;
356 EXPECT_EQ(0, buffer.get_allocator().get());
357 StrictMock< MockAllocator<char> > alloc;
358 char mem;
359 {
360 MemoryBuffer<char, 10, TestAllocator> buffer2((TestAllocator(&alloc)));
361 EXPECT_EQ(&alloc, buffer2.get_allocator().get());
362 std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
363 EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(Return(&mem));
364 buffer2.reserve(size);
365 EXPECT_CALL(alloc, deallocate(&mem, size));
366 }
367 }
368
TEST(MemoryBufferTest,ExceptionInDeallocate)369 TEST(MemoryBufferTest, ExceptionInDeallocate) {
370 typedef AllocatorRef< MockAllocator<char> > TestAllocator;
371 StrictMock< MockAllocator<char> > alloc;
372 MemoryBuffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc)));
373 std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
374 std::vector<char> mem(size);
375 {
376 EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(Return(&mem[0]));
377 buffer.resize(size);
378 std::fill(&buffer[0], &buffer[0] + size, 'x');
379 }
380 std::vector<char> mem2(2 * size);
381 {
382 EXPECT_CALL(alloc, allocate(2 * size, 0)).WillOnce(Return(&mem2[0]));
383 std::exception e;
384 EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e));
385 EXPECT_THROW(buffer.reserve(2 * size), std::exception);
386 EXPECT_EQ(&mem2[0], &buffer[0]);
387 // Check that the data has been copied.
388 for (std::size_t i = 0; i < size; ++i)
389 EXPECT_EQ('x', buffer[i]);
390 }
391 EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
392 }
393
TEST(UtilTest,Increment)394 TEST(UtilTest, Increment) {
395 char s[10] = "123";
396 increment(s);
397 EXPECT_STREQ("124", s);
398 s[2] = '8';
399 increment(s);
400 EXPECT_STREQ("129", s);
401 increment(s);
402 EXPECT_STREQ("130", s);
403 s[1] = s[2] = '9';
404 increment(s);
405 EXPECT_STREQ("200", s);
406 }
407
408 template <Arg::Type>
409 struct ArgInfo;
410
411 #define ARG_INFO(type_code, Type, field) \
412 template <> \
413 struct ArgInfo<Arg::type_code> { \
414 static Type get(const Arg &arg) { return arg.field; } \
415 }
416
417 ARG_INFO(INT, int, int_value);
418 ARG_INFO(UINT, unsigned, uint_value);
419 ARG_INFO(LONG_LONG, fmt::LongLong, long_long_value);
420 ARG_INFO(ULONG_LONG, fmt::ULongLong, ulong_long_value);
421 ARG_INFO(BOOL, int, int_value);
422 ARG_INFO(CHAR, int, int_value);
423 ARG_INFO(DOUBLE, double, double_value);
424 ARG_INFO(LONG_DOUBLE, long double, long_double_value);
425 ARG_INFO(CSTRING, const char *, string.value);
426 ARG_INFO(STRING, const char *, string.value);
427 ARG_INFO(WSTRING, const wchar_t *, wstring.value);
428 ARG_INFO(POINTER, const void *, pointer);
429 ARG_INFO(CUSTOM, Arg::CustomValue, custom);
430
431 #define CHECK_ARG_INFO(Type, field, value) { \
432 Arg arg = Arg(); \
433 arg.field = value; \
434 EXPECT_EQ(value, ArgInfo<Arg::Type>::get(arg)); \
435 }
436
TEST(ArgTest,ArgInfo)437 TEST(ArgTest, ArgInfo) {
438 CHECK_ARG_INFO(INT, int_value, 42);
439 CHECK_ARG_INFO(UINT, uint_value, 42u);
440 CHECK_ARG_INFO(LONG_LONG, long_long_value, 42);
441 CHECK_ARG_INFO(ULONG_LONG, ulong_long_value, 42u);
442 CHECK_ARG_INFO(DOUBLE, double_value, 4.2);
443 CHECK_ARG_INFO(LONG_DOUBLE, long_double_value, 4.2);
444 CHECK_ARG_INFO(CHAR, int_value, 'x');
445 const char STR[] = "abc";
446 CHECK_ARG_INFO(CSTRING, string.value, STR);
447 const wchar_t WSTR[] = L"abc";
448 CHECK_ARG_INFO(WSTRING, wstring.value, WSTR);
449 int p = 0;
450 CHECK_ARG_INFO(POINTER, pointer, &p);
451 Arg arg = Arg();
452 arg.custom.value = &p;
453 EXPECT_EQ(&p, ArgInfo<Arg::CUSTOM>::get(arg).value);
454 }
455
456 #define EXPECT_ARG_(Char, type_code, MakeArgType, ExpectedType, value) { \
457 MakeArgType input = static_cast<MakeArgType>(value); \
458 Arg arg = make_arg<Char>(input); \
459 EXPECT_EQ(Arg::type_code, arg.type); \
460 ExpectedType expected_value = static_cast<ExpectedType>(value); \
461 EXPECT_EQ(expected_value, ArgInfo<Arg::type_code>::get(arg)); \
462 }
463
464 #define EXPECT_ARG(type_code, Type, value) \
465 EXPECT_ARG_(char, type_code, Type, Type, value)
466
467 #define EXPECT_ARGW(type_code, Type, value) \
468 EXPECT_ARG_(wchar_t, type_code, Type, Type, value)
469
TEST(ArgTest,MakeArg)470 TEST(ArgTest, MakeArg) {
471 // Test bool.
472 EXPECT_ARG_(char, BOOL, bool, int, true);
473 EXPECT_ARG_(wchar_t, BOOL, bool, int, true);
474
475 // Test char.
476 EXPECT_ARG(CHAR, char, 'a');
477 EXPECT_ARG(CHAR, char, CHAR_MIN);
478 EXPECT_ARG(CHAR, char, CHAR_MAX);
479
480 // Test wchar_t.
481 EXPECT_ARGW(CHAR, wchar_t, L'a');
482 EXPECT_ARGW(CHAR, wchar_t, WCHAR_MIN);
483 EXPECT_ARGW(CHAR, wchar_t, WCHAR_MAX);
484
485 // Test signed/unsigned char.
486 EXPECT_ARG(INT, signed char, 42);
487 EXPECT_ARG(INT, signed char, SCHAR_MIN);
488 EXPECT_ARG(INT, signed char, SCHAR_MAX);
489 EXPECT_ARG(UINT, unsigned char, 42);
490 EXPECT_ARG(UINT, unsigned char, UCHAR_MAX );
491
492 // Test short.
493 EXPECT_ARG(INT, short, 42);
494 EXPECT_ARG(INT, short, SHRT_MIN);
495 EXPECT_ARG(INT, short, SHRT_MAX);
496 EXPECT_ARG(UINT, unsigned short, 42);
497 EXPECT_ARG(UINT, unsigned short, USHRT_MAX);
498
499 // Test int.
500 EXPECT_ARG(INT, int, 42);
501 EXPECT_ARG(INT, int, INT_MIN);
502 EXPECT_ARG(INT, int, INT_MAX);
503 EXPECT_ARG(UINT, unsigned, 42);
504 EXPECT_ARG(UINT, unsigned, UINT_MAX);
505
506 // Test long.
507 #if LONG_MAX == INT_MAX
508 # define LONG INT
509 # define ULONG UINT
510 # define long_value int_value
511 # define ulong_value uint_value
512 #else
513 # define LONG LONG_LONG
514 # define ULONG ULONG_LONG
515 # define long_value long_long_value
516 # define ulong_value ulong_long_value
517 #endif
518 EXPECT_ARG(LONG, long, 42);
519 EXPECT_ARG(LONG, long, LONG_MIN);
520 EXPECT_ARG(LONG, long, LONG_MAX);
521 EXPECT_ARG(ULONG, unsigned long, 42);
522 EXPECT_ARG(ULONG, unsigned long, ULONG_MAX);
523
524 // Test long long.
525 EXPECT_ARG(LONG_LONG, fmt::LongLong, 42);
526 EXPECT_ARG(LONG_LONG, fmt::LongLong, LLONG_MIN);
527 EXPECT_ARG(LONG_LONG, fmt::LongLong, LLONG_MAX);
528 EXPECT_ARG(ULONG_LONG, fmt::ULongLong, 42);
529 EXPECT_ARG(ULONG_LONG, fmt::ULongLong, ULLONG_MAX);
530
531 // Test float.
532 EXPECT_ARG(DOUBLE, float, 4.2);
533 EXPECT_ARG(DOUBLE, float, FLT_MIN);
534 EXPECT_ARG(DOUBLE, float, FLT_MAX);
535
536 // Test double.
537 EXPECT_ARG(DOUBLE, double, 4.2);
538 EXPECT_ARG(DOUBLE, double, DBL_MIN);
539 EXPECT_ARG(DOUBLE, double, DBL_MAX);
540
541 // Test long double.
542 EXPECT_ARG(LONG_DOUBLE, long double, 4.2);
543 EXPECT_ARG(LONG_DOUBLE, long double, LDBL_MIN);
544 EXPECT_ARG(LONG_DOUBLE, long double, LDBL_MAX);
545
546 // Test string.
547 char STR[] = "test";
548 EXPECT_ARG(CSTRING, char*, STR);
549 EXPECT_ARG(CSTRING, const char*, STR);
550 EXPECT_ARG(STRING, std::string, STR);
551 EXPECT_ARG(STRING, fmt::StringRef, STR);
552
553 // Test wide string.
554 wchar_t WSTR[] = L"test";
555 EXPECT_ARGW(WSTRING, wchar_t*, WSTR);
556 EXPECT_ARGW(WSTRING, const wchar_t*, WSTR);
557 EXPECT_ARGW(WSTRING, std::wstring, WSTR);
558 EXPECT_ARGW(WSTRING, fmt::WStringRef, WSTR);
559
560 int n = 42;
561 EXPECT_ARG(POINTER, void*, &n);
562 EXPECT_ARG(POINTER, const void*, &n);
563
564 ::Test t;
565 Arg arg = make_arg<char>(t);
566 EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type);
567 EXPECT_EQ(&t, arg.custom.value);
568 fmt::MemoryWriter w;
569 fmt::BasicFormatter<char> formatter(fmt::ArgList(), w);
570 const char *s = "}";
571 arg.custom.format(&formatter, &t, &s);
572 EXPECT_EQ("test", w.str());
573 }
574
TEST(UtilTest,ArgList)575 TEST(UtilTest, ArgList) {
576 fmt::ArgList args;
577 EXPECT_EQ(Arg::NONE, args[1].type);
578 }
579
580 struct CustomFormatter {
581 typedef char Char;
582 };
583
format_arg(CustomFormatter &,const char * & s,const Test &)584 void format_arg(CustomFormatter &, const char *&s, const Test &) {
585 s = "custom_format";
586 }
587
TEST(UtilTest,MakeValueWithCustomFormatter)588 TEST(UtilTest, MakeValueWithCustomFormatter) {
589 ::Test t;
590 Arg arg = fmt::internal::MakeValue<CustomFormatter>(t);
591 CustomFormatter formatter;
592 const char *s = "";
593 arg.custom.format(&formatter, &t, &s);
594 EXPECT_STREQ("custom_format", s);
595 }
596
597 struct Result {
598 Arg arg;
599
ResultResult600 Result() : arg(make_arg<char>(0xdeadbeef)) {}
601
602 template <typename T>
ResultResult603 Result(const T& value) : arg(make_arg<char>(value)) {}
ResultResult604 Result(const wchar_t *s) : arg(make_arg<wchar_t>(s)) {}
605 };
606
607 struct TestVisitor : fmt::ArgVisitor<TestVisitor, Result> {
visit_intTestVisitor608 Result visit_int(int value) { return value; }
visit_uintTestVisitor609 Result visit_uint(unsigned value) { return value; }
visit_long_longTestVisitor610 Result visit_long_long(fmt::LongLong value) { return value; }
visit_ulong_longTestVisitor611 Result visit_ulong_long(fmt::ULongLong value) { return value; }
visit_doubleTestVisitor612 Result visit_double(double value) { return value; }
visit_long_doubleTestVisitor613 Result visit_long_double(long double value) { return value; }
visit_charTestVisitor614 Result visit_char(int value) { return static_cast<char>(value); }
visit_cstringTestVisitor615 Result visit_cstring(const char *s) { return s; }
visit_stringTestVisitor616 Result visit_string(fmt::internal::Arg::StringValue<char> s) {
617 return s.value;
618 }
visit_wstringTestVisitor619 Result visit_wstring(fmt::internal::Arg::StringValue<wchar_t> s) {
620 return s.value;
621 }
visit_pointerTestVisitor622 Result visit_pointer(const void *p) { return p; }
visit_customTestVisitor623 Result visit_custom(fmt::internal::Arg::CustomValue c) {
624 return *static_cast<const ::Test*>(c.value);
625 }
626 };
627
628 #define EXPECT_RESULT_(Char, type_code, value) { \
629 Arg arg = make_arg<Char>(value); \
630 Result result = TestVisitor().visit(arg); \
631 EXPECT_EQ(Arg::type_code, result.arg.type); \
632 EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
633 }
634
635 #define EXPECT_RESULT(type_code, value) \
636 EXPECT_RESULT_(char, type_code, value)
637 #define EXPECT_RESULTW(type_code, value) \
638 EXPECT_RESULT_(wchar_t, type_code, value)
639
TEST(ArgVisitorTest,VisitAll)640 TEST(ArgVisitorTest, VisitAll) {
641 EXPECT_RESULT(INT, 42);
642 EXPECT_RESULT(UINT, 42u);
643 EXPECT_RESULT(LONG_LONG, 42ll);
644 EXPECT_RESULT(ULONG_LONG, 42ull);
645 EXPECT_RESULT(DOUBLE, 4.2);
646 EXPECT_RESULT(LONG_DOUBLE, 4.2l);
647 EXPECT_RESULT(CHAR, 'x');
648 const char STR[] = "abc";
649 EXPECT_RESULT(CSTRING, STR);
650 const wchar_t WSTR[] = L"abc";
651 EXPECT_RESULTW(WSTRING, WSTR);
652 const void *p = STR;
653 EXPECT_RESULT(POINTER, p);
654 ::Test t;
655 Result result = TestVisitor().visit(make_arg<char>(t));
656 EXPECT_EQ(Arg::CUSTOM, result.arg.type);
657 EXPECT_EQ(&t, result.arg.custom.value);
658 }
659
660 struct TestAnyVisitor : fmt::ArgVisitor<TestAnyVisitor, Result> {
661 template <typename T>
visit_any_intTestAnyVisitor662 Result visit_any_int(T value) { return value; }
663
664 template <typename T>
visit_any_doubleTestAnyVisitor665 Result visit_any_double(T value) { return value; }
666 };
667
668 #undef EXPECT_RESULT
669 #define EXPECT_RESULT(type_code, value) { \
670 Result result = TestAnyVisitor().visit(make_arg<char>(value)); \
671 EXPECT_EQ(Arg::type_code, result.arg.type); \
672 EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
673 }
674
TEST(ArgVisitorTest,VisitAny)675 TEST(ArgVisitorTest, VisitAny) {
676 EXPECT_RESULT(INT, 42);
677 EXPECT_RESULT(UINT, 42u);
678 EXPECT_RESULT(LONG_LONG, 42ll);
679 EXPECT_RESULT(ULONG_LONG, 42ull);
680 EXPECT_RESULT(DOUBLE, 4.2);
681 EXPECT_RESULT(LONG_DOUBLE, 4.2l);
682 }
683
684 struct TestUnhandledVisitor :
685 fmt::ArgVisitor<TestUnhandledVisitor, const char *> {
visit_unhandled_argTestUnhandledVisitor686 const char *visit_unhandled_arg() { return "test"; }
687 };
688
689 #define EXPECT_UNHANDLED(value) \
690 EXPECT_STREQ("test", TestUnhandledVisitor().visit(make_arg<wchar_t>(value)));
691
TEST(ArgVisitorTest,VisitUnhandledArg)692 TEST(ArgVisitorTest, VisitUnhandledArg) {
693 EXPECT_UNHANDLED(42);
694 EXPECT_UNHANDLED(42u);
695 EXPECT_UNHANDLED(42ll);
696 EXPECT_UNHANDLED(42ull);
697 EXPECT_UNHANDLED(4.2);
698 EXPECT_UNHANDLED(4.2l);
699 EXPECT_UNHANDLED('x');
700 const char STR[] = "abc";
701 EXPECT_UNHANDLED(STR);
702 const wchar_t WSTR[] = L"abc";
703 EXPECT_UNHANDLED(WSTR);
704 const void *p = STR;
705 EXPECT_UNHANDLED(p);
706 EXPECT_UNHANDLED(::Test());
707 }
708
TEST(ArgVisitorTest,VisitInvalidArg)709 TEST(ArgVisitorTest, VisitInvalidArg) {
710 Arg arg = Arg();
711 arg.type = static_cast<Arg::Type>(Arg::NONE);
712 EXPECT_ASSERT(TestVisitor().visit(arg), "invalid argument type");
713 }
714
715 // Tests fmt::internal::count_digits for integer type Int.
716 template <typename Int>
test_count_digits()717 void test_count_digits() {
718 for (Int i = 0; i < 10; ++i)
719 EXPECT_EQ(1u, fmt::internal::count_digits(i));
720 for (Int i = 1, n = 1,
721 end = std::numeric_limits<Int>::max() / 10; n <= end; ++i) {
722 n *= 10;
723 EXPECT_EQ(i, fmt::internal::count_digits(n - 1));
724 EXPECT_EQ(i + 1, fmt::internal::count_digits(n));
725 }
726 }
727
TEST(UtilTest,StringRef)728 TEST(UtilTest, StringRef) {
729 // Test that StringRef::size() returns string length, not buffer size.
730 char str[100] = "some string";
731 EXPECT_EQ(std::strlen(str), StringRef(str).size());
732 EXPECT_LT(std::strlen(str), sizeof(str));
733 }
734
735 // Check StringRef's comparison operator.
736 template <template <typename> class Op>
CheckOp()737 void CheckOp() {
738 const char *inputs[] = {"foo", "fop", "fo"};
739 std::size_t num_inputs = sizeof(inputs) / sizeof(*inputs);
740 for (std::size_t i = 0; i < num_inputs; ++i) {
741 for (std::size_t j = 0; j < num_inputs; ++j) {
742 StringRef lhs(inputs[i]), rhs(inputs[j]);
743 EXPECT_EQ(Op<int>()(lhs.compare(rhs), 0), Op<StringRef>()(lhs, rhs));
744 }
745 }
746 }
747
TEST(UtilTest,StringRefCompare)748 TEST(UtilTest, StringRefCompare) {
749 EXPECT_EQ(0, StringRef("foo").compare(StringRef("foo")));
750 EXPECT_GT(StringRef("fop").compare(StringRef("foo")), 0);
751 EXPECT_LT(StringRef("foo").compare(StringRef("fop")), 0);
752 EXPECT_GT(StringRef("foo").compare(StringRef("fo")), 0);
753 EXPECT_LT(StringRef("fo").compare(StringRef("foo")), 0);
754 CheckOp<std::equal_to>();
755 CheckOp<std::not_equal_to>();
756 CheckOp<std::less>();
757 CheckOp<std::less_equal>();
758 CheckOp<std::greater>();
759 CheckOp<std::greater_equal>();
760 }
761
TEST(UtilTest,CountDigits)762 TEST(UtilTest, CountDigits) {
763 test_count_digits<uint32_t>();
764 test_count_digits<uint64_t>();
765 }
766
767 #ifdef _WIN32
TEST(UtilTest,UTF16ToUTF8)768 TEST(UtilTest, UTF16ToUTF8) {
769 std::string s = "ёжик";
770 fmt::internal::UTF16ToUTF8 u(L"\x0451\x0436\x0438\x043A");
771 EXPECT_EQ(s, u.str());
772 EXPECT_EQ(s.size(), u.size());
773 }
774
TEST(UtilTest,UTF8ToUTF16)775 TEST(UtilTest, UTF8ToUTF16) {
776 std::string s = "лошадка";
777 fmt::internal::UTF8ToUTF16 u(s.c_str());
778 EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
779 EXPECT_EQ(7, u.size());
780 }
781
782 template <typename Converter, typename Char>
check_utf_conversion_error(const char * message,fmt::BasicStringRef<Char> str=fmt::BasicStringRef<Char> (0,0))783 void check_utf_conversion_error(
784 const char *message,
785 fmt::BasicStringRef<Char> str = fmt::BasicStringRef<Char>(0, 0)) {
786 fmt::MemoryWriter out;
787 fmt::internal::format_windows_error(out, ERROR_INVALID_PARAMETER, message);
788 fmt::SystemError error(0, "");
789 try {
790 (Converter)(str);
791 } catch (const fmt::SystemError &e) {
792 error = e;
793 }
794 EXPECT_EQ(ERROR_INVALID_PARAMETER, error.error_code());
795 EXPECT_EQ(out.str(), error.what());
796 }
797
TEST(UtilTest,UTF16ToUTF8Error)798 TEST(UtilTest, UTF16ToUTF8Error) {
799 check_utf_conversion_error<fmt::internal::UTF16ToUTF8, wchar_t>(
800 "cannot convert string from UTF-16 to UTF-8");
801 }
802
TEST(UtilTest,UTF8ToUTF16Error)803 TEST(UtilTest, UTF8ToUTF16Error) {
804 const char *message = "cannot convert string from UTF-8 to UTF-16";
805 check_utf_conversion_error<fmt::internal::UTF8ToUTF16, char>(message);
806 check_utf_conversion_error<fmt::internal::UTF8ToUTF16, char>(
807 message, fmt::StringRef("foo", INT_MAX + 1u));
808 }
809
TEST(UtilTest,UTF16ToUTF8Convert)810 TEST(UtilTest, UTF16ToUTF8Convert) {
811 fmt::internal::UTF16ToUTF8 u;
812 EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(0, 0)));
813 EXPECT_EQ(ERROR_INVALID_PARAMETER,
814 u.convert(fmt::WStringRef(L"foo", INT_MAX + 1u)));
815 }
816 #endif // _WIN32
817
818 typedef void (*FormatErrorMessage)(
819 fmt::Writer &out, int error_code, StringRef message);
820
821 template <typename Error>
check_throw_error(int error_code,FormatErrorMessage format)822 void check_throw_error(int error_code, FormatErrorMessage format) {
823 fmt::SystemError error(0, "");
824 try {
825 throw Error(error_code, "test {}", "error");
826 } catch (const fmt::SystemError &e) {
827 error = e;
828 }
829 fmt::MemoryWriter message;
830 format(message, error_code, "test error");
831 EXPECT_EQ(message.str(), error.what());
832 EXPECT_EQ(error_code, error.error_code());
833 }
834
TEST(UtilTest,FormatSystemError)835 TEST(UtilTest, FormatSystemError) {
836 fmt::MemoryWriter message;
837 fmt::format_system_error(message, EDOM, "test");
838 EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), message.str());
839 message.clear();
840 fmt::format_system_error(
841 message, EDOM, fmt::StringRef(0, std::numeric_limits<size_t>::max()));
842 EXPECT_EQ(fmt::format("error {}", EDOM), message.str());
843 }
844
TEST(UtilTest,SystemError)845 TEST(UtilTest, SystemError) {
846 fmt::SystemError e(EDOM, "test");
847 EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), e.what());
848 EXPECT_EQ(EDOM, e.error_code());
849 check_throw_error<fmt::SystemError>(EDOM, fmt::format_system_error);
850 }
851
TEST(UtilTest,ReportSystemError)852 TEST(UtilTest, ReportSystemError) {
853 fmt::MemoryWriter out;
854 fmt::format_system_error(out, EDOM, "test error");
855 out << '\n';
856 EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"), out.str());
857 }
858
859 #ifdef _WIN32
860
TEST(UtilTest,FormatWindowsError)861 TEST(UtilTest, FormatWindowsError) {
862 LPWSTR message = 0;
863 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
864 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
865 ERROR_FILE_EXISTS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
866 reinterpret_cast<LPWSTR>(&message), 0, 0);
867 fmt::internal::UTF16ToUTF8 utf8_message(message);
868 LocalFree(message);
869 fmt::MemoryWriter actual_message;
870 fmt::internal::format_windows_error(
871 actual_message, ERROR_FILE_EXISTS, "test");
872 EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
873 actual_message.str());
874 actual_message.clear();
875 fmt::internal::format_windows_error(
876 actual_message, ERROR_FILE_EXISTS,
877 fmt::StringRef(0, std::numeric_limits<size_t>::max()));
878 EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS), actual_message.str());
879 }
880
TEST(UtilTest,FormatLongWindowsError)881 TEST(UtilTest, FormatLongWindowsError) {
882 LPWSTR message = 0;
883 // this error code is not available on all Windows platforms and
884 // Windows SDKs, so do not fail the test if the error string cannot
885 // be retrieved.
886 const int provisioning_not_allowed = 0x80284013L /*TBS_E_PROVISIONING_NOT_ALLOWED*/;
887 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
888 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
889 provisioning_not_allowed, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
890 reinterpret_cast<LPWSTR>(&message), 0, 0) == 0) {
891 return;
892 }
893 fmt::internal::UTF16ToUTF8 utf8_message(message);
894 LocalFree(message);
895 fmt::MemoryWriter actual_message;
896 fmt::internal::format_windows_error(
897 actual_message, provisioning_not_allowed, "test");
898 EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
899 actual_message.str());
900 }
901
TEST(UtilTest,WindowsError)902 TEST(UtilTest, WindowsError) {
903 check_throw_error<fmt::WindowsError>(
904 ERROR_FILE_EXISTS, fmt::internal::format_windows_error);
905 }
906
TEST(UtilTest,ReportWindowsError)907 TEST(UtilTest, ReportWindowsError) {
908 fmt::MemoryWriter out;
909 fmt::internal::format_windows_error(out, ERROR_FILE_EXISTS, "test error");
910 out << '\n';
911 EXPECT_WRITE(stderr,
912 fmt::report_windows_error(ERROR_FILE_EXISTS, "test error"), out.str());
913 }
914
915 #endif // _WIN32
916
917 enum TestEnum2 {};
918
TEST(UtilTest,ConvertToInt)919 TEST(UtilTest, ConvertToInt) {
920 EXPECT_TRUE(fmt::internal::ConvertToInt<char>::enable_conversion);
921 EXPECT_FALSE(fmt::internal::ConvertToInt<const char *>::enable_conversion);
922 EXPECT_TRUE(fmt::internal::ConvertToInt<TestEnum2>::value);
923 }
924
925 #if FMT_USE_ENUM_BASE
926 enum TestEnum : char {TestValue};
TEST(UtilTest,IsEnumConvertibleToInt)927 TEST(UtilTest, IsEnumConvertibleToInt) {
928 EXPECT_TRUE(fmt::internal::ConvertToInt<TestEnum>::enable_conversion);
929 }
930 #endif
931
932 template <typename T>
check_enable_if(typename fmt::internal::EnableIf<sizeof (T)==sizeof (int),T>::type *)933 bool check_enable_if(
934 typename fmt::internal::EnableIf<sizeof(T) == sizeof(int), T>::type *) {
935 return true;
936 }
937
938 template <typename T>
check_enable_if(typename fmt::internal::EnableIf<sizeof (T)!=sizeof (int),T>::type *)939 bool check_enable_if(
940 typename fmt::internal::EnableIf<sizeof(T) != sizeof(int), T>::type *) {
941 return false;
942 }
943
TEST(UtilTest,EnableIf)944 TEST(UtilTest, EnableIf) {
945 int i = 0;
946 EXPECT_TRUE(check_enable_if<int>(&i));
947 char c = 0;
948 EXPECT_FALSE(check_enable_if<char>(&c));
949 }
950
TEST(UtilTest,Conditional)951 TEST(UtilTest, Conditional) {
952 int i = 0;
953 fmt::internal::Conditional<true, int, char>::type *pi = &i;
954 (void)pi;
955 char c = 0;
956 fmt::internal::Conditional<false, int, char>::type *pc = &c;
957 (void)pc;
958 }
959
960 struct TestLConv {
961 char *thousands_sep;
962 };
963
964 struct EmptyLConv {};
965
TEST(UtilTest,ThousandsSep)966 TEST(UtilTest, ThousandsSep) {
967 char foo[] = "foo";
968 TestLConv lc = {foo};
969 EXPECT_EQ("foo", fmt::internal::thousands_sep(&lc).to_string());
970 EmptyLConv empty_lc;
971 EXPECT_EQ("", fmt::internal::thousands_sep(&empty_lc));
972 }
973