diff --git a/include/fmt/core.h b/include/fmt/core.h index 583a536d..a054f976 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -755,6 +755,54 @@ class basic_format_arg { bool is_arithmetic() const { return internal::is_arithmetic(type_); } }; +struct monostate {}; + +/** + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + ``vis(value)`` will be called with the value of type ``double``. + \endrst + */ +template +FMT_CONSTEXPR typename internal::result_of::type + visit(Visitor &&vis, const basic_format_arg &arg) { + typedef typename Context::char_type char_type; + switch (arg.type_) { + case internal::none_type: + break; + case internal::named_arg_type: + FMT_ASSERT(false, "invalid argument type"); + break; + case internal::int_type: + return vis(arg.value_.int_value); + case internal::uint_type: + return vis(arg.value_.uint_value); + case internal::long_long_type: + return vis(arg.value_.long_long_value); + case internal::ulong_long_type: + return vis(arg.value_.ulong_long_value); + case internal::bool_type: + return vis(arg.value_.int_value != 0); + case internal::char_type: + return vis(static_cast(arg.value_.int_value)); + case internal::double_type: + return vis(arg.value_.double_value); + case internal::long_double_type: + return vis(arg.value_.long_double_value); + case internal::cstring_type: + return vis(arg.value_.string.value); + case internal::string_type: + return vis(basic_string_view( + arg.value_.string.value, arg.value_.string.size)); + case internal::pointer_type: + return vis(arg.value_.pointer); + case internal::custom_type: + return vis(typename basic_format_arg::handle(arg.value_.custom)); + } + return vis(monostate()); +} + // Parsing context consisting of a format string range being parsed and an // argument counter for automatic indexing. template diff --git a/include/fmt/format.h b/include/fmt/format.h index 857eb889..f80f22e4 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1154,54 +1154,6 @@ template struct null {}; } // namespace internal -struct monostate {}; - -/** - \rst - Visits an argument dispatching to the appropriate visit method based on - the argument type. For example, if the argument type is ``double`` then - ``vis(value)`` will be called with the value of type ``double``. - \endrst - */ -template -FMT_CONSTEXPR typename internal::result_of::type - visit(Visitor &&vis, const basic_format_arg &arg) { - typedef typename Context::char_type char_type; - switch (arg.type_) { - case internal::none_type: - break; - case internal::named_arg_type: - FMT_ASSERT(false, "invalid argument type"); - break; - case internal::int_type: - return vis(arg.value_.int_value); - case internal::uint_type: - return vis(arg.value_.uint_value); - case internal::long_long_type: - return vis(arg.value_.long_long_value); - case internal::ulong_long_type: - return vis(arg.value_.ulong_long_value); - case internal::bool_type: - return vis(arg.value_.int_value != 0); - case internal::char_type: - return vis(static_cast(arg.value_.int_value)); - case internal::double_type: - return vis(arg.value_.double_value); - case internal::long_double_type: - return vis(arg.value_.long_double_value); - case internal::cstring_type: - return vis(arg.value_.string.value); - case internal::string_type: - return vis(basic_string_view( - arg.value_.string.value, arg.value_.string.size)); - case internal::pointer_type: - return vis(arg.value_.pointer); - case internal::custom_type: - return vis(typename basic_format_arg::handle(arg.value_.custom)); - } - return vis(monostate()); -} - enum alignment { ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC }; diff --git a/src/format.cc b/src/format.cc index e387dded..ab5663e1 100644 --- a/src/format.cc +++ b/src/format.cc @@ -14,33 +14,40 @@ template struct internal::basic_data; template FMT_API char internal::thousands_sep(locale_provider *lp); +template void internal::basic_buffer::append(const char *, const char *); + template void basic_fixed_buffer::grow(std::size_t); template void internal::arg_map::init( const basic_format_args &args); template FMT_API int internal::char_traits::format_float( - char *buffer, std::size_t size, const char *format, int precision, - double value); + char *, std::size_t, const char *, int, double); template FMT_API int internal::char_traits::format_float( - char *buffer, std::size_t size, const char *format, int precision, - long double value); + char *, std::size_t, const char *, int, long double); + +template FMT_API std::string internal::vformat( + string_view, basic_format_args); // Explicit instantiations for wchar_t. -template FMT_API wchar_t internal::thousands_sep(locale_provider *lp); +template FMT_API wchar_t internal::thousands_sep(locale_provider *); + +template void internal::basic_buffer::append( + const wchar_t *, const wchar_t *); template void basic_fixed_buffer::grow(std::size_t); template void internal::arg_map::init( - const basic_format_args &args); + const basic_format_args &); template FMT_API int internal::char_traits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - int precision, double value); + wchar_t *, std::size_t, const wchar_t *, int, double); template FMT_API int internal::char_traits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - int precision, long double value); + wchar_t *, std::size_t, const wchar_t *, int, long double); + +template FMT_API std::wstring internal::vformat( + wstring_view, basic_format_args); FMT_END_NAMESPACE diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3996ac4f..fa8402e1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -85,9 +85,9 @@ function(add_fmt_test name) endfunction() add_fmt_test(assert-test) -add_fmt_test(core-test mock-allocator.h) +add_fmt_test(core-test) add_fmt_test(gtest-extra-test) -add_fmt_test(format-test) +add_fmt_test(format-test mock-allocator.h) add_fmt_test(format-impl-test) add_fmt_test(ostream-test) add_fmt_test(printf-test) diff --git a/test/core-test.cc b/test/core-test.cc index 1711b17f..66475b03 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -1,28 +1,24 @@ -// Formatting library for C++ - utility tests +// Formatting library for C++ - core tests // // Copyright (c) 2012 - present, Victor Zverovich // All rights reserved. // // For the license information refer to format.h. -#include "test-assert.h" - -#include +#include #include #include #include +#include #include +#include +#include -#if FMT_USE_TYPE_TRAITS -# include -#endif +#include "test-assert.h" #include "gmock.h" -#include "gtest-extra.h" -#include "mock-allocator.h" -#include "util.h" -// Check if format.h compiles with windows.h included. +// Check if fmt/core.h compiles with windows.h included before it. #ifdef _WIN32 # include #endif @@ -34,17 +30,15 @@ using fmt::basic_format_arg; using fmt::internal::basic_buffer; -using fmt::basic_memory_buffer; -using fmt::string_view; using fmt::internal::value; +using fmt::string_view; using testing::_; -using testing::Return; using testing::StrictMock; namespace { -struct Test {}; +struct test_struct {}; template basic_format_arg make_arg(const T &value) { @@ -54,7 +48,7 @@ basic_format_arg make_arg(const T &value) { FMT_BEGIN_NAMESPACE template -struct formatter { +struct formatter { template auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { return ctx.begin(); @@ -62,7 +56,7 @@ struct formatter { typedef std::back_insert_iterator> iterator; - auto format(Test, basic_format_context &ctx) + auto format(test_struct, basic_format_context &ctx) -> decltype(ctx.out()) { const Char *test = "test"; return std::copy_n(test, std::strlen(test), ctx.out()); @@ -70,52 +64,30 @@ struct formatter { }; FMT_END_NAMESPACE -static void CheckForwarding( - MockAllocator &alloc, AllocatorRef> &ref) { - int mem; - // Check if value_type is properly defined. - AllocatorRef< MockAllocator >::value_type *ptr = &mem; - // Check forwarding. - EXPECT_CALL(alloc, allocate(42)).WillOnce(Return(ptr)); - ref.allocate(42); - EXPECT_CALL(alloc, deallocate(ptr, 42)); - ref.deallocate(ptr, 42); -} - -TEST(AllocatorTest, AllocatorRef) { - StrictMock< MockAllocator > alloc; - typedef AllocatorRef< MockAllocator > TestAllocatorRef; - TestAllocatorRef ref(&alloc); - // Check if AllocatorRef forwards to the underlying allocator. - CheckForwarding(alloc, ref); - TestAllocatorRef ref2(ref); - CheckForwarding(alloc, ref2); - TestAllocatorRef ref3; - EXPECT_EQ(nullptr, ref3.get()); - ref3 = ref; - CheckForwarding(alloc, ref3); -} - -#if FMT_USE_TYPE_TRAITS TEST(BufferTest, Noncopyable) { EXPECT_FALSE(std::is_copy_constructible >::value); +#if !FMT_MSC_VER + // std::is_copy_assignable is broken in MSVC2013. EXPECT_FALSE(std::is_copy_assignable >::value); +#endif } TEST(BufferTest, Nonmoveable) { EXPECT_FALSE(std::is_move_constructible >::value); +#if !FMT_MSC_VER + // std::is_move_assignable is broken in MSVC2013. EXPECT_FALSE(std::is_move_assignable >::value); -} #endif +} // A test buffer with a dummy grow method. template -struct TestBuffer : basic_buffer { +struct test_buffer : basic_buffer { void grow(std::size_t capacity) { this->set(nullptr, capacity); } }; template -struct MockBuffer : basic_buffer { +struct mock_buffer : basic_buffer { MOCK_METHOD1(do_grow, void (std::size_t capacity)); void grow(std::size_t capacity) { @@ -123,21 +95,21 @@ struct MockBuffer : basic_buffer { do_grow(capacity); } - MockBuffer() {} - MockBuffer(T *data) { this->set(data, 0); } - MockBuffer(T *data, std::size_t capacity) { this->set(data, capacity); } + mock_buffer() {} + mock_buffer(T *data) { this->set(data, 0); } + mock_buffer(T *data, std::size_t capacity) { this->set(data, capacity); } }; TEST(BufferTest, Ctor) { { - MockBuffer buffer; + mock_buffer buffer; EXPECT_EQ(nullptr, &buffer[0]); EXPECT_EQ(static_cast(0), buffer.size()); EXPECT_EQ(static_cast(0), buffer.capacity()); } { int dummy; - MockBuffer buffer(&dummy); + mock_buffer buffer(&dummy); EXPECT_EQ(&dummy, &buffer[0]); EXPECT_EQ(static_cast(0), buffer.size()); EXPECT_EQ(static_cast(0), buffer.capacity()); @@ -145,21 +117,21 @@ TEST(BufferTest, Ctor) { { int dummy; std::size_t capacity = std::numeric_limits::max(); - MockBuffer buffer(&dummy, capacity); + mock_buffer buffer(&dummy, capacity); EXPECT_EQ(&dummy, &buffer[0]); EXPECT_EQ(static_cast(0), buffer.size()); EXPECT_EQ(capacity, buffer.capacity()); } } -struct DyingBuffer : TestBuffer { +struct dying_buffer : test_buffer { MOCK_METHOD0(die, void()); - ~DyingBuffer() { die(); } + ~dying_buffer() { die(); } }; TEST(BufferTest, VirtualDtor) { - typedef StrictMock StictMockBuffer; - StictMockBuffer *mock_buffer = new StictMockBuffer(); + typedef StrictMock stict_mock_buffer; + stict_mock_buffer *mock_buffer = new stict_mock_buffer(); EXPECT_CALL(*mock_buffer, die()); basic_buffer *buffer = mock_buffer; delete buffer; @@ -167,7 +139,7 @@ TEST(BufferTest, VirtualDtor) { TEST(BufferTest, Access) { char data[10]; - MockBuffer buffer(data, sizeof(data)); + mock_buffer buffer(data, sizeof(data)); buffer[0] = 11; EXPECT_EQ(11, buffer[0]); buffer[3] = 42; @@ -178,7 +150,7 @@ TEST(BufferTest, Access) { TEST(BufferTest, Resize) { char data[123]; - MockBuffer buffer(data, sizeof(data)); + mock_buffer buffer(data, sizeof(data)); buffer[10] = 42; EXPECT_EQ(42, buffer[10]); buffer.resize(20); @@ -197,7 +169,7 @@ TEST(BufferTest, Resize) { } TEST(BufferTest, Clear) { - TestBuffer buffer; + test_buffer buffer; buffer.resize(20); buffer.resize(0); EXPECT_EQ(static_cast(0), buffer.size()); @@ -206,7 +178,7 @@ TEST(BufferTest, Clear) { TEST(BufferTest, Append) { char data[15]; - MockBuffer buffer(data, 10); + mock_buffer buffer(data, 10); const char *test = "test"; buffer.append(test, test + 5); EXPECT_STREQ(test, &buffer[0]); @@ -221,202 +193,14 @@ TEST(BufferTest, Append) { TEST(BufferTest, AppendAllocatesEnoughStorage) { char data[19]; - MockBuffer buffer(data, 10); + mock_buffer buffer(data, 10); const char *test = "abcdefgh"; buffer.resize(10); EXPECT_CALL(buffer, do_grow(19)); buffer.append(test, test + 9); } -TEST(MemoryBufferTest, Ctor) { - basic_memory_buffer buffer; - EXPECT_EQ(static_cast(0), buffer.size()); - EXPECT_EQ(123u, buffer.capacity()); -} - -typedef AllocatorRef< std::allocator > TestAllocator; - -static void check_move_buffer(const char *str, - basic_memory_buffer &buffer) { - std::allocator *alloc = buffer.get_allocator().get(); - basic_memory_buffer buffer2(std::move(buffer)); - // Move shouldn't destroy the inline content of the first buffer. - EXPECT_EQ(str, std::string(&buffer[0], buffer.size())); - EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size())); - EXPECT_EQ(5u, buffer2.capacity()); - // Move should transfer allocator. - EXPECT_EQ(nullptr, buffer.get_allocator().get()); - EXPECT_EQ(alloc, buffer2.get_allocator().get()); -} - -TEST(MemoryBufferTest, MoveCtor) { - std::allocator alloc; - basic_memory_buffer buffer((TestAllocator(&alloc))); - const char test[] = "test"; - buffer.append(test, test + 4); - check_move_buffer("test", buffer); - // Adding one more character fills the inline buffer, but doesn't cause - // dynamic allocation. - buffer.push_back('a'); - check_move_buffer("testa", buffer); - const char *inline_buffer_ptr = &buffer[0]; - // Adding one more character causes the content to move from the inline to - // a dynamically allocated buffer. - buffer.push_back('b'); - basic_memory_buffer buffer2(std::move(buffer)); - // Move should rip the guts of the first buffer. - EXPECT_EQ(inline_buffer_ptr, &buffer[0]); - EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size())); - EXPECT_GT(buffer2.capacity(), 5u); -} - -static void check_move_assign_buffer( - const char *str, basic_memory_buffer &buffer) { - basic_memory_buffer buffer2; - buffer2 = std::move(buffer); - // Move shouldn't destroy the inline content of the first buffer. - EXPECT_EQ(str, std::string(&buffer[0], buffer.size())); - EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size())); - EXPECT_EQ(5u, buffer2.capacity()); -} - -TEST(MemoryBufferTest, MoveAssignment) { - basic_memory_buffer buffer; - const char test[] = "test"; - buffer.append(test, test + 4); - check_move_assign_buffer("test", buffer); - // Adding one more character fills the inline buffer, but doesn't cause - // dynamic allocation. - buffer.push_back('a'); - check_move_assign_buffer("testa", buffer); - const char *inline_buffer_ptr = &buffer[0]; - // Adding one more character causes the content to move from the inline to - // a dynamically allocated buffer. - buffer.push_back('b'); - basic_memory_buffer buffer2; - buffer2 = std::move(buffer); - // Move should rip the guts of the first buffer. - EXPECT_EQ(inline_buffer_ptr, &buffer[0]); - EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size())); - EXPECT_GT(buffer2.capacity(), 5u); -} - -TEST(MemoryBufferTest, Grow) { - typedef AllocatorRef< MockAllocator > Allocator; - typedef basic_memory_buffer Base; - MockAllocator alloc; - struct TestMemoryBuffer : Base { - TestMemoryBuffer(Allocator alloc) : Base(alloc) {} - void grow(std::size_t size) { Base::grow(size); } - } buffer((Allocator(&alloc))); - buffer.resize(7); - using fmt::internal::to_unsigned; - for (int i = 0; i < 7; ++i) - buffer[to_unsigned(i)] = i * i; - EXPECT_EQ(10u, buffer.capacity()); - int mem[20]; - mem[7] = 0xdead; - EXPECT_CALL(alloc, allocate(20)).WillOnce(Return(mem)); - buffer.grow(20); - EXPECT_EQ(20u, buffer.capacity()); - // Check if size elements have been copied - for (int i = 0; i < 7; ++i) - EXPECT_EQ(i * i, buffer[to_unsigned(i)]); - // and no more than that. - EXPECT_EQ(0xdead, buffer[7]); - EXPECT_CALL(alloc, deallocate(mem, 20)); -} - -TEST(MemoryBufferTest, Allocator) { - typedef AllocatorRef< MockAllocator > TestAllocator; - basic_memory_buffer buffer; - EXPECT_EQ(nullptr, buffer.get_allocator().get()); - StrictMock< MockAllocator > alloc; - char mem; - { - basic_memory_buffer buffer2((TestAllocator(&alloc))); - EXPECT_EQ(&alloc, buffer2.get_allocator().get()); - std::size_t size = 2 * fmt::inline_buffer_size; - EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem)); - buffer2.reserve(size); - EXPECT_CALL(alloc, deallocate(&mem, size)); - } -} - -TEST(MemoryBufferTest, ExceptionInDeallocate) { - typedef AllocatorRef< MockAllocator > TestAllocator; - StrictMock< MockAllocator > alloc; - basic_memory_buffer buffer((TestAllocator(&alloc))); - std::size_t size = 2 * fmt::inline_buffer_size; - std::vector mem(size); - { - EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0])); - buffer.resize(size); - std::fill(&buffer[0], &buffer[0] + size, 'x'); - } - std::vector mem2(2 * size); - { - EXPECT_CALL(alloc, allocate(2 * size)).WillOnce(Return(&mem2[0])); - std::exception e; - EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e)); - EXPECT_THROW(buffer.reserve(2 * size), std::exception); - EXPECT_EQ(&mem2[0], &buffer[0]); - // Check that the data has been copied. - for (std::size_t i = 0; i < size; ++i) - EXPECT_EQ('x', buffer[i]); - } - EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size)); -} - -TEST(FixedBufferTest, Ctor) { - char array[10] = "garbage"; - fmt::basic_fixed_buffer buffer(array, sizeof(array)); - EXPECT_EQ(static_cast(0), buffer.size()); - EXPECT_EQ(10u, buffer.capacity()); - EXPECT_EQ(array, buffer.data()); -} - -TEST(FixedBufferTest, CompileTimeSizeCtor) { - char array[10] = "garbage"; - fmt::basic_fixed_buffer buffer(array); - EXPECT_EQ(static_cast(0), buffer.size()); - EXPECT_EQ(10u, buffer.capacity()); - EXPECT_EQ(array, buffer.data()); -} - -TEST(FixedBufferTest, BufferOverflow) { - char array[10]; - fmt::basic_fixed_buffer buffer(array); - buffer.resize(10); - EXPECT_THROW_MSG(buffer.resize(11), std::runtime_error, "buffer overflow"); -} - -struct uint32_pair { - uint32_t u[2]; -}; - -TEST(UtilTest, BitCast) { - auto s = fmt::internal::bit_cast(uint64_t{42}); - EXPECT_EQ(fmt::internal::bit_cast(s), 42ull); - s = fmt::internal::bit_cast(uint64_t(~0ull)); - EXPECT_EQ(fmt::internal::bit_cast(s), ~0ull); -} - -TEST(UtilTest, Increment) { - char s[10] = "123"; - increment(s); - EXPECT_STREQ("124", s); - s[2] = '8'; - increment(s); - EXPECT_STREQ("129", s); - increment(s); - EXPECT_STREQ("130", s); - s[1] = s[2] = '9'; - increment(s); - EXPECT_STREQ("200", s); -} - -TEST(UtilTest, FormatArgs) { +TEST(ArgTest, FormatArgs) { fmt::format_args args; EXPECT_FALSE(args.get(1)); } @@ -445,8 +229,8 @@ struct custom_context { void advance_to(const char *) {} }; -TEST(UtilTest, MakeValueWithCustomFormatter) { - ::Test t; +TEST(ArgTest, MakeValueWithCustomContext) { + test_struct t; fmt::internal::value arg = fmt::internal::make_value(t); custom_context ctx = {false}; @@ -456,7 +240,6 @@ TEST(UtilTest, MakeValueWithCustomFormatter) { FMT_BEGIN_NAMESPACE namespace internal { - template bool operator==(custom_value lhs, custom_value rhs) { return lhs.value == rhs.value; @@ -466,32 +249,35 @@ FMT_END_NAMESPACE // Use a unique result type to make sure that there are no undesirable // conversions. -struct Result {}; +struct test_result {}; template -struct MockVisitor: fmt::internal::function { - MockVisitor() { - ON_CALL(*this, visit(_)).WillByDefault(Return(Result())); +struct mock_visitor { + template + struct result { typedef test_result type; }; + + mock_visitor() { + ON_CALL(*this, visit(_)).WillByDefault(testing::Return(test_result())); } - MOCK_METHOD1_T(visit, Result (T value)); + MOCK_METHOD1_T(visit, test_result (T value)); MOCK_METHOD0_T(unexpected, void ()); - Result operator()(T value) { return visit(value); } + test_result operator()(T value) { return visit(value); } template - Result operator()(U) { + test_result operator()(U) { unexpected(); - return Result(); + return test_result(); } }; template -struct VisitType { typedef T Type; }; +struct visit_type { typedef T Type; }; -#define VISIT_TYPE(Type_, VisitType_) \ +#define VISIT_TYPE(Type_, visit_type_) \ template <> \ - struct VisitType { typedef VisitType_ Type; } + struct visit_type { typedef visit_type_ Type; } VISIT_TYPE(signed char, int); VISIT_TYPE(unsigned char, unsigned); @@ -509,7 +295,7 @@ VISIT_TYPE(unsigned long, unsigned long long); VISIT_TYPE(float, double); #define CHECK_ARG_(Char, expected, value) { \ - testing::StrictMock> visitor; \ + testing::StrictMock> visitor; \ EXPECT_CALL(visitor, visit(expected)); \ typedef std::back_insert_iterator> iterator; \ fmt::visit(visitor, \ @@ -518,7 +304,7 @@ VISIT_TYPE(float, double); #define CHECK_ARG(value, typename_) { \ typedef decltype(value) value_type; \ - typename_ VisitType::Type expected = value; \ + typename_ visit_type::Type expected = value; \ CHECK_ARG_(char, expected, value) \ CHECK_ARG_(wchar_t, expected, value) \ } @@ -549,13 +335,13 @@ TYPED_TEST(NumericArgTest, MakeAndVisit) { CHECK_ARG(std::numeric_limits::max(), typename); } -TEST(UtilTest, CharArg) { +TEST(ArgTest, CharArg) { CHECK_ARG_(char, 'a', 'a'); CHECK_ARG_(wchar_t, L'a', 'a'); CHECK_ARG_(wchar_t, L'a', L'a'); } -TEST(UtilTest, StringArg) { +TEST(ArgTest, StringArg) { char str_data[] = "test"; char *str = str_data; const char *cstr = str; @@ -565,7 +351,7 @@ TEST(UtilTest, StringArg) { CHECK_ARG_(char, sref, std::string(str)); } -TEST(UtilTest, WStringArg) { +TEST(ArgTest, WStringArg) { wchar_t str_data[] = L"test"; wchar_t *str = str_data; const wchar_t *cstr = str; @@ -577,7 +363,7 @@ TEST(UtilTest, WStringArg) { CHECK_ARG_(wchar_t, sref, fmt::wstring_view(str)); } -TEST(UtilTest, PointerArg) { +TEST(ArgTest, PointerArg) { void *p = nullptr; const void *cp = nullptr; CHECK_ARG_(char, cp, p); @@ -586,56 +372,48 @@ TEST(UtilTest, PointerArg) { } struct check_custom { - Result operator()(fmt::basic_format_arg::handle h) const { - fmt::memory_buffer buffer; + test_result operator()( + fmt::basic_format_arg::handle h) const { + struct test_buffer : fmt::internal::basic_buffer { + char data[10]; + test_buffer() : basic_buffer(data, 0, 10) {} + void grow(std::size_t) {} + } buffer; fmt::internal::basic_buffer &base = buffer; fmt::format_context ctx(std::back_inserter(base), "", fmt::format_args()); h.format(ctx); - EXPECT_EQ("test", std::string(buffer.data(), buffer.size())); - return Result(); + EXPECT_EQ("test", std::string(buffer.data, buffer.size())); + return test_result(); } }; -TEST(UtilTest, CustomArg) { - ::Test test; - typedef MockVisitor::handle> +TEST(ArgTest, CustomArg) { + test_struct test; + typedef mock_visitor::handle> visitor; testing::StrictMock v; EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke(check_custom())); fmt::visit(v, make_arg(test)); } -TEST(ArgVisitorTest, VisitInvalidArg) { - typedef MockVisitor Visitor; +TEST(ArgTest, VisitInvalidArg) { + typedef mock_visitor Visitor; testing::StrictMock visitor; EXPECT_CALL(visitor, visit(_)); fmt::basic_format_arg arg; visit(visitor, arg); } -// Tests fmt::internal::count_digits for integer type Int. -template -void test_count_digits() { - for (Int i = 0; i < 10; ++i) - EXPECT_EQ(1u, fmt::internal::count_digits(i)); - for (Int i = 1, n = 1, - end = std::numeric_limits::max() / 10; n <= end; ++i) { - n *= 10; - EXPECT_EQ(i, fmt::internal::count_digits(n - 1)); - EXPECT_EQ(i + 1, fmt::internal::count_digits(n)); - } -} - -TEST(UtilTest, StringRef) { +TEST(StringViewTest, Length) { // Test that StringRef::size() returns string length, not buffer size. char str[100] = "some string"; EXPECT_EQ(std::strlen(str), string_view(str).size()); EXPECT_LT(std::strlen(str), sizeof(str)); } -// Check StringRef's comparison operator. +// Check string_view's comparison operator. template