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