• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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