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
54using fmt::StringRef;
55using fmt::internal::Arg;
56using fmt::Buffer;
57using fmt::internal::MemoryBuffer;
58
59using testing::Return;
60using testing::StrictMock;
61
62namespace {
63
64struct Test {};
65
66template <typename Char>
67void format_arg(fmt::BasicFormatter<Char> &f, const Char *, Test) {
68  f.writer() << "test";
69}
70
71template <typename Char, typename T>
72Arg 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
80void 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
92TEST(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
107TEST(BufferTest, Noncopyable) {
108  EXPECT_FALSE(std::is_copy_constructible<Buffer<char> >::value);
109  EXPECT_FALSE(std::is_copy_assignable<Buffer<char> >::value);
110}
111
112TEST(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.
119template <typename T>
120struct TestBuffer : Buffer<T> {
121  void grow(std::size_t size) { this->capacity_ = size; }
122};
123
124template <typename T>
125struct MockBuffer : Buffer<T> {
126  MOCK_METHOD1(do_grow, void (std::size_t size));
127
128  void grow(std::size_t size) {
129    this->capacity_ = size;
130    do_grow(size);
131  }
132
133  MockBuffer() {}
134  MockBuffer(T *ptr) : Buffer<T>(ptr) {}
135  MockBuffer(T *ptr, std::size_t capacity) : Buffer<T>(ptr, capacity) {}
136};
137
138TEST(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
162struct DyingBuffer : TestBuffer<int> {
163  MOCK_METHOD0(die, void());
164  ~DyingBuffer() { die(); }
165};
166
167TEST(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
175TEST(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
186TEST(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
206TEST(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
214TEST(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
227TEST(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
242TEST(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
251TEST(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
259typedef AllocatorRef< std::allocator<char> > TestAllocator;
260
261void 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
274TEST(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
295void 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
304TEST(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
327TEST(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
353TEST(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
369TEST(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
394TEST(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
408template <Arg::Type>
409struct 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
417ARG_INFO(INT, int, int_value);
418ARG_INFO(UINT, unsigned, uint_value);
419ARG_INFO(LONG_LONG, fmt::LongLong, long_long_value);
420ARG_INFO(ULONG_LONG, fmt::ULongLong, ulong_long_value);
421ARG_INFO(BOOL, int, int_value);
422ARG_INFO(CHAR, int, int_value);
423ARG_INFO(DOUBLE, double, double_value);
424ARG_INFO(LONG_DOUBLE, long double, long_double_value);
425ARG_INFO(CSTRING, const char *, string.value);
426ARG_INFO(STRING, const char *, string.value);
427ARG_INFO(WSTRING, const wchar_t *, wstring.value);
428ARG_INFO(POINTER, const void *, pointer);
429ARG_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
437TEST(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
470TEST(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
575TEST(UtilTest, ArgList) {
576  fmt::ArgList args;
577  EXPECT_EQ(Arg::NONE, args[1].type);
578}
579
580struct CustomFormatter {
581  typedef char Char;
582};
583
584void format_arg(CustomFormatter &, const char *&s, const Test &) {
585  s = "custom_format";
586}
587
588TEST(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
597struct Result {
598  Arg arg;
599
600  Result() : arg(make_arg<char>(0xdeadbeef)) {}
601
602  template <typename T>
603  Result(const T& value) : arg(make_arg<char>(value)) {}
604  Result(const wchar_t *s) : arg(make_arg<wchar_t>(s)) {}
605};
606
607struct TestVisitor : fmt::ArgVisitor<TestVisitor, Result> {
608  Result visit_int(int value) { return value; }
609  Result visit_uint(unsigned value) { return value; }
610  Result visit_long_long(fmt::LongLong value) { return value; }
611  Result visit_ulong_long(fmt::ULongLong value) { return value; }
612  Result visit_double(double value) { return value; }
613  Result visit_long_double(long double value) { return value; }
614  Result visit_char(int value) { return static_cast<char>(value); }
615  Result visit_cstring(const char *s) { return s; }
616  Result visit_string(fmt::internal::Arg::StringValue<char> s) {
617    return s.value;
618  }
619  Result visit_wstring(fmt::internal::Arg::StringValue<wchar_t> s) {
620    return s.value;
621  }
622  Result visit_pointer(const void *p) { return p; }
623  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
640TEST(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
660struct TestAnyVisitor : fmt::ArgVisitor<TestAnyVisitor, Result> {
661  template <typename T>
662  Result visit_any_int(T value) { return value; }
663
664  template <typename T>
665  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
675TEST(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
684struct TestUnhandledVisitor :
685    fmt::ArgVisitor<TestUnhandledVisitor, const char *> {
686  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
692TEST(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
709TEST(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.
716template <typename Int>
717void 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
728TEST(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.
736template <template <typename> class Op>
737void 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
748TEST(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
762TEST(UtilTest, CountDigits) {
763  test_count_digits<uint32_t>();
764  test_count_digits<uint64_t>();
765}
766
767#ifdef _WIN32
768TEST(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
775TEST(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
782template <typename Converter, typename Char>
783void 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
798TEST(UtilTest, UTF16ToUTF8Error) {
799  check_utf_conversion_error<fmt::internal::UTF16ToUTF8, wchar_t>(
800      "cannot convert string from UTF-16 to UTF-8");
801}
802
803TEST(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
810TEST(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
818typedef void (*FormatErrorMessage)(
819        fmt::Writer &out, int error_code, StringRef message);
820
821template <typename Error>
822void 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
835TEST(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
845TEST(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
852TEST(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
861TEST(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
881TEST(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
902TEST(UtilTest, WindowsError) {
903  check_throw_error<fmt::WindowsError>(
904      ERROR_FILE_EXISTS, fmt::internal::format_windows_error);
905}
906
907TEST(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
917enum TestEnum2 {};
918
919TEST(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
926enum TestEnum : char {TestValue};
927TEST(UtilTest, IsEnumConvertibleToInt) {
928  EXPECT_TRUE(fmt::internal::ConvertToInt<TestEnum>::enable_conversion);
929}
930#endif
931
932template <typename T>
933bool check_enable_if(
934    typename fmt::internal::EnableIf<sizeof(T) == sizeof(int), T>::type *) {
935  return true;
936}
937
938template <typename T>
939bool check_enable_if(
940    typename fmt::internal::EnableIf<sizeof(T) != sizeof(int), T>::type *) {
941  return false;
942}
943
944TEST(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
951TEST(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
960struct TestLConv {
961  char *thousands_sep;
962};
963
964struct EmptyLConv {};
965
966TEST(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