| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  | // Formatting library for C++ - core tests
 | 
					
						
							| 
									
										
										
										
											2018-03-04 09:16:51 -08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // Copyright (c) 2012 - present, Victor Zverovich
 | 
					
						
							|  |  |  | // All rights reserved.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // For the license information refer to format.h.
 | 
					
						
							| 
									
										
										
										
											2014-06-06 06:38:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | // clang-format off
 | 
					
						
							|  |  |  | #include "test-assert.h"
 | 
					
						
							|  |  |  | // clang-format on
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "fmt/core.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  | #include <algorithm>    // std::copy_n
 | 
					
						
							|  |  |  | #include <climits>      // INT_MAX
 | 
					
						
							|  |  |  | #include <cstring>      // std::strlen
 | 
					
						
							|  |  |  | #include <functional>   // std::equal_to
 | 
					
						
							|  |  |  | #include <iterator>     // std::back_insert_iterator
 | 
					
						
							|  |  |  | #include <limits>       // std::numeric_limits
 | 
					
						
							|  |  |  | #include <string>       // std::string
 | 
					
						
							|  |  |  | #include <type_traits>  // std::is_same
 | 
					
						
							| 
									
										
										
										
											2014-09-29 08:48:16 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-29 01:59:43 +03:00
										 |  |  | #include "gmock/gmock.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-06 07:29:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  | using fmt::string_view; | 
					
						
							| 
									
										
										
										
											2020-05-10 07:25:42 -07:00
										 |  |  | using fmt::detail::buffer; | 
					
						
							| 
									
										
										
										
											2014-09-29 08:48:16 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | using testing::_; | 
					
						
							| 
									
										
										
										
											2020-07-11 06:53:25 -07:00
										 |  |  | using testing::Invoke; | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  | using testing::Return; | 
					
						
							| 
									
										
										
										
											2014-06-06 06:38:37 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 09:25:12 -07:00
										 |  |  | #ifdef FMT_FORMAT_H_
 | 
					
						
							|  |  |  | #  error core-test includes format.h
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(string_view_test, value_type) { | 
					
						
							|  |  |  |   static_assert(std::is_same<string_view::value_type, char>::value, ""); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-05-06 07:37:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-30 17:02:14 -07:00
										 |  |  | TEST(string_view_test, ctor) { | 
					
						
							|  |  |  |   EXPECT_STREQ("abc", fmt::string_view("abc").data()); | 
					
						
							|  |  |  |   EXPECT_EQ(3u, fmt::string_view("abc").size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT_STREQ("defg", fmt::string_view(std::string("defg")).data()); | 
					
						
							|  |  |  |   EXPECT_EQ(4u, fmt::string_view(std::string("defg")).size()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(string_view_test, length) { | 
					
						
							|  |  |  |   // Test that string_view::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)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-13 13:09:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | // Check string_view's comparison operator.
 | 
					
						
							|  |  |  | template <template <typename> class Op> void check_op() { | 
					
						
							|  |  |  |   const char* inputs[] = {"foo", "fop", "fo"}; | 
					
						
							|  |  |  |   size_t num_inputs = sizeof(inputs) / sizeof(*inputs); | 
					
						
							|  |  |  |   for (size_t i = 0; i < num_inputs; ++i) { | 
					
						
							|  |  |  |     for (size_t j = 0; j < num_inputs; ++j) { | 
					
						
							|  |  |  |       string_view lhs(inputs[i]), rhs(inputs[j]); | 
					
						
							|  |  |  |       EXPECT_EQ(Op<int>()(lhs.compare(rhs), 0), Op<string_view>()(lhs, rhs)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-13 13:09:02 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(string_view_test, compare) { | 
					
						
							|  |  |  |   EXPECT_EQ(string_view("foo").compare(string_view("foo")), 0); | 
					
						
							|  |  |  |   EXPECT_GT(string_view("fop").compare(string_view("foo")), 0); | 
					
						
							|  |  |  |   EXPECT_LT(string_view("foo").compare(string_view("fop")), 0); | 
					
						
							|  |  |  |   EXPECT_GT(string_view("foo").compare(string_view("fo")), 0); | 
					
						
							|  |  |  |   EXPECT_LT(string_view("fo").compare(string_view("foo")), 0); | 
					
						
							| 
									
										
										
										
											2022-09-04 23:41:16 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   EXPECT_TRUE(string_view("foo").starts_with('f')); | 
					
						
							|  |  |  |   EXPECT_FALSE(string_view("foo").starts_with('o')); | 
					
						
							|  |  |  |   EXPECT_FALSE(string_view().starts_with('o')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT_TRUE(string_view("foo").starts_with("fo")); | 
					
						
							|  |  |  |   EXPECT_TRUE(string_view("foo").starts_with("foo")); | 
					
						
							|  |  |  |   EXPECT_FALSE(string_view("foo").starts_with("fooo")); | 
					
						
							|  |  |  |   EXPECT_FALSE(string_view().starts_with("fooo")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   check_op<std::equal_to>(); | 
					
						
							|  |  |  |   check_op<std::not_equal_to>(); | 
					
						
							|  |  |  |   check_op<std::less>(); | 
					
						
							|  |  |  |   check_op<std::less_equal>(); | 
					
						
							|  |  |  |   check_op<std::greater>(); | 
					
						
							|  |  |  |   check_op<std::greater_equal>(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-13 13:09:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-30 17:02:14 -07:00
										 |  |  | TEST(core_test, is_output_iterator) { | 
					
						
							|  |  |  |   EXPECT_TRUE((fmt::detail::is_output_iterator<char*, char>::value)); | 
					
						
							|  |  |  |   EXPECT_FALSE((fmt::detail::is_output_iterator<const char*, char>::value)); | 
					
						
							|  |  |  |   EXPECT_FALSE((fmt::detail::is_output_iterator<std::string, char>::value)); | 
					
						
							|  |  |  |   EXPECT_TRUE( | 
					
						
							|  |  |  |       (fmt::detail::is_output_iterator<std::back_insert_iterator<std::string>, | 
					
						
							|  |  |  |                                        char>::value)); | 
					
						
							|  |  |  |   EXPECT_TRUE( | 
					
						
							|  |  |  |       (fmt::detail::is_output_iterator<std::string::iterator, char>::value)); | 
					
						
							|  |  |  |   EXPECT_FALSE((fmt::detail::is_output_iterator<std::string::const_iterator, | 
					
						
							|  |  |  |                                                 char>::value)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(core_test, buffer_appender) { | 
					
						
							|  |  |  |   // back_insert_iterator is not default-constructible before C++20, so
 | 
					
						
							|  |  |  |   // buffer_appender can only be default-constructible when back_insert_iterator
 | 
					
						
							|  |  |  |   // is.
 | 
					
						
							|  |  |  |   static_assert( | 
					
						
							|  |  |  |       std::is_default_constructible< | 
					
						
							|  |  |  |           std::back_insert_iterator<fmt::detail::buffer<char>>>::value == | 
					
						
							|  |  |  |           std::is_default_constructible< | 
					
						
							|  |  |  |               fmt::detail::buffer_appender<char>>::value, | 
					
						
							|  |  |  |       ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __cpp_lib_ranges
 | 
					
						
							|  |  |  |   static_assert(std::output_iterator<fmt::detail::buffer_appender<char>, char>); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-24 06:34:28 -07:00
										 |  |  | #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 470
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, noncopyable) { | 
					
						
							| 
									
										
										
										
											2019-04-07 10:05:49 -07:00
										 |  |  |   EXPECT_FALSE(std::is_copy_constructible<buffer<char>>::value); | 
					
						
							| 
									
										
										
										
											2022-05-29 15:01:43 -07:00
										 |  |  | #  if !FMT_MSC_VERSION
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |   // std::is_copy_assignable is broken in MSVC2013.
 | 
					
						
							| 
									
										
										
										
											2019-04-07 10:05:49 -07:00
										 |  |  |   EXPECT_FALSE(std::is_copy_assignable<buffer<char>>::value); | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2014-09-29 08:48:16 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, nonmoveable) { | 
					
						
							| 
									
										
										
										
											2019-04-07 10:05:49 -07:00
										 |  |  |   EXPECT_FALSE(std::is_move_constructible<buffer<char>>::value); | 
					
						
							| 
									
										
										
										
											2022-05-29 15:01:43 -07:00
										 |  |  | #  if !FMT_MSC_VERSION
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |   // std::is_move_assignable is broken in MSVC2013.
 | 
					
						
							| 
									
										
										
										
											2019-04-07 10:05:49 -07:00
										 |  |  |   EXPECT_FALSE(std::is_move_assignable<buffer<char>>::value); | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-24 06:34:28 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-09-29 08:48:16 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, indestructible) { | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  |   static_assert(!std::is_destructible<fmt::detail::buffer<int>>(), | 
					
						
							|  |  |  |                 "buffer's destructor is protected"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 02:41:56 +02:00
										 |  |  | template <typename T> struct mock_buffer final : buffer<T> { | 
					
						
							| 
									
										
										
										
											2023-04-20 13:16:21 -07:00
										 |  |  |   MOCK_METHOD(size_t, do_grow, (size_t)); | 
					
						
							| 
									
										
										
										
											2014-10-01 09:32:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-09 08:05:02 -07:00
										 |  |  |   void grow(size_t capacity) override { | 
					
						
							|  |  |  |     this->set(this->data(), do_grow(capacity)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-27 21:55:44 -06:00
										 |  |  |   mock_buffer(T* data = nullptr, size_t buf_capacity = 0) { | 
					
						
							|  |  |  |     this->set(data, buf_capacity); | 
					
						
							| 
									
										
										
										
											2020-07-11 06:53:25 -07:00
										 |  |  |     ON_CALL(*this, do_grow(_)).WillByDefault(Invoke([](size_t capacity) { | 
					
						
							|  |  |  |       return capacity; | 
					
						
							|  |  |  |     })); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, ctor) { | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |     mock_buffer<int> buffer; | 
					
						
							| 
									
										
										
										
											2019-10-08 13:28:39 +00:00
										 |  |  |     EXPECT_EQ(nullptr, buffer.data()); | 
					
						
							| 
									
										
										
										
											2018-06-06 16:57:59 +03:00
										 |  |  |     EXPECT_EQ(static_cast<size_t>(0), buffer.size()); | 
					
						
							|  |  |  |     EXPECT_EQ(static_cast<size_t>(0), buffer.capacity()); | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |   } | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     int dummy; | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |     mock_buffer<int> buffer(&dummy); | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |     EXPECT_EQ(&dummy, &buffer[0]); | 
					
						
							| 
									
										
										
										
											2018-06-06 16:57:59 +03:00
										 |  |  |     EXPECT_EQ(static_cast<size_t>(0), buffer.size()); | 
					
						
							|  |  |  |     EXPECT_EQ(static_cast<size_t>(0), buffer.capacity()); | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |   } | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     int dummy; | 
					
						
							| 
									
										
										
										
											2020-05-07 15:59:46 -07:00
										 |  |  |     size_t capacity = std::numeric_limits<size_t>::max(); | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |     mock_buffer<int> buffer(&dummy, capacity); | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |     EXPECT_EQ(&dummy, &buffer[0]); | 
					
						
							| 
									
										
										
										
											2018-06-06 16:57:59 +03:00
										 |  |  |     EXPECT_EQ(static_cast<size_t>(0), buffer.size()); | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |     EXPECT_EQ(capacity, buffer.capacity()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, access) { | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |   char data[10]; | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |   mock_buffer<char> buffer(data, sizeof(data)); | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |   buffer[0] = 11; | 
					
						
							|  |  |  |   EXPECT_EQ(11, buffer[0]); | 
					
						
							|  |  |  |   buffer[3] = 42; | 
					
						
							|  |  |  |   EXPECT_EQ(42, *(&buffer[0] + 3)); | 
					
						
							| 
									
										
										
										
											2020-05-10 07:25:42 -07:00
										 |  |  |   const fmt::detail::buffer<char>& const_buffer = buffer; | 
					
						
							| 
									
										
										
										
											2014-09-30 07:30:27 -07:00
										 |  |  |   EXPECT_EQ(42, const_buffer[3]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, try_resize) { | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   char data[123]; | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |   mock_buffer<char> buffer(data, sizeof(data)); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   buffer[10] = 42; | 
					
						
							|  |  |  |   EXPECT_EQ(42, buffer[10]); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(20); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   EXPECT_EQ(20u, buffer.size()); | 
					
						
							|  |  |  |   EXPECT_EQ(123u, buffer.capacity()); | 
					
						
							|  |  |  |   EXPECT_EQ(42, buffer[10]); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(5); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   EXPECT_EQ(5u, buffer.size()); | 
					
						
							|  |  |  |   EXPECT_EQ(123u, buffer.capacity()); | 
					
						
							|  |  |  |   EXPECT_EQ(42, buffer[10]); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   // Check if try_resize calls grow.
 | 
					
						
							| 
									
										
										
										
											2014-10-01 09:32:31 -07:00
										 |  |  |   EXPECT_CALL(buffer, do_grow(124)); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(124); | 
					
						
							| 
									
										
										
										
											2014-10-01 09:32:31 -07:00
										 |  |  |   EXPECT_CALL(buffer, do_grow(200)); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(200); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, try_resize_partial) { | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   char data[10]; | 
					
						
							|  |  |  |   mock_buffer<char> buffer(data, sizeof(data)); | 
					
						
							|  |  |  |   EXPECT_CALL(buffer, do_grow(20)).WillOnce(Return(15)); | 
					
						
							|  |  |  |   buffer.try_resize(20); | 
					
						
							|  |  |  |   EXPECT_EQ(buffer.capacity(), 15); | 
					
						
							|  |  |  |   EXPECT_EQ(buffer.size(), 15); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, clear) { | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  |   mock_buffer<char> buffer; | 
					
						
							|  |  |  |   EXPECT_CALL(buffer, do_grow(20)); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(20); | 
					
						
							|  |  |  |   buffer.try_resize(0); | 
					
						
							| 
									
										
										
										
											2018-06-06 16:57:59 +03:00
										 |  |  |   EXPECT_EQ(static_cast<size_t>(0), buffer.size()); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   EXPECT_EQ(20u, buffer.capacity()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, append) { | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   char data[15]; | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |   mock_buffer<char> buffer(data, 10); | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  |   auto test = "test"; | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   buffer.append(test, test + 5); | 
					
						
							|  |  |  |   EXPECT_STREQ(test, &buffer[0]); | 
					
						
							|  |  |  |   EXPECT_EQ(5u, buffer.size()); | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(10); | 
					
						
							| 
									
										
										
										
											2014-10-01 09:32:31 -07:00
										 |  |  |   EXPECT_CALL(buffer, do_grow(12)); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   buffer.append(test, test + 2); | 
					
						
							|  |  |  |   EXPECT_EQ('t', buffer[10]); | 
					
						
							|  |  |  |   EXPECT_EQ('e', buffer[11]); | 
					
						
							|  |  |  |   EXPECT_EQ(12u, buffer.size()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, append_partial) { | 
					
						
							| 
									
										
										
										
											2020-07-11 06:53:25 -07:00
										 |  |  |   char data[10]; | 
					
						
							|  |  |  |   mock_buffer<char> buffer(data, sizeof(data)); | 
					
						
							|  |  |  |   testing::InSequence seq; | 
					
						
							|  |  |  |   EXPECT_CALL(buffer, do_grow(15)).WillOnce(Return(10)); | 
					
						
							|  |  |  |   EXPECT_CALL(buffer, do_grow(15)).WillOnce(Invoke([&buffer](size_t) { | 
					
						
							|  |  |  |     EXPECT_EQ(fmt::string_view(buffer.data(), buffer.size()), "0123456789"); | 
					
						
							|  |  |  |     buffer.clear(); | 
					
						
							|  |  |  |     return 10; | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  |   auto test = "0123456789abcde"; | 
					
						
							|  |  |  |   buffer.append(test, test + 15); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(buffer_test, append_allocates_enough_storage) { | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   char data[19]; | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |   mock_buffer<char> buffer(data, 10); | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  |   auto test = "abcdefgh"; | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |   buffer.try_resize(10); | 
					
						
							| 
									
										
										
										
											2014-10-01 09:32:31 -07:00
										 |  |  |   EXPECT_CALL(buffer, do_grow(19)); | 
					
						
							| 
									
										
										
										
											2014-10-01 08:12:10 -07:00
										 |  |  |   buffer.append(test, test + 9); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-14 11:00:27 -08:00
										 |  |  | struct custom_context { | 
					
						
							| 
									
										
										
										
											2020-04-12 07:38:54 -07:00
										 |  |  |   using char_type = char; | 
					
						
							|  |  |  |   using parse_context_type = fmt::format_parse_context; | 
					
						
							| 
									
										
										
										
											2017-08-13 13:09:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   bool called = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  |   template <typename T> struct formatter_type { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |     FMT_CONSTEXPR auto parse(fmt::format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2019-06-02 16:04:17 -07:00
										 |  |  |       return ctx.begin(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const char* format(const T&, custom_context& ctx) { | 
					
						
							|  |  |  |       ctx.called = true; | 
					
						
							|  |  |  |       return nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-13 13:09:02 -07:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  |   void advance_to(const char*) {} | 
					
						
							| 
									
										
										
										
											2017-08-13 13:09:02 -07:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-12-02 08:41:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | struct test_struct {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | FMT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | template <typename Char> struct formatter<test_struct, Char> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto format(test_struct, format_context& ctx) const -> decltype(ctx.out()) { | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |     auto test = string_view("test"); | 
					
						
							|  |  |  |     return std::copy_n(test.data(), test.size(), ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | FMT_END_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(arg_test, format_args) { | 
					
						
							|  |  |  |   auto args = fmt::format_args(); | 
					
						
							|  |  |  |   EXPECT_FALSE(args.get(1)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(arg_test, make_value_with_custom_context) { | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  |   auto t = test_struct(); | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto arg = fmt::detail::value<custom_context>( | 
					
						
							| 
									
										
										
										
											2020-05-10 07:25:42 -07:00
										 |  |  |       fmt::detail::arg_mapper<custom_context>().map(t)); | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   auto ctx = custom_context(); | 
					
						
							|  |  |  |   auto parse_ctx = fmt::format_parse_context(""); | 
					
						
							|  |  |  |   arg.custom.format(&t, parse_ctx, ctx); | 
					
						
							| 
									
										
										
										
											2016-11-06 16:11:24 -08:00
										 |  |  |   EXPECT_TRUE(ctx.called); | 
					
						
							| 
									
										
										
										
											2015-12-02 08:41:05 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-03 14:04:59 -08:00
										 |  |  | // Use a unique result type to make sure that there are no undesirable
 | 
					
						
							|  |  |  | // conversions.
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  | struct test_result {}; | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  | template <typename T> struct mock_visitor { | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  |   template <typename U> struct result { using type = test_result; }; | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   mock_visitor() { | 
					
						
							| 
									
										
										
										
											2020-07-10 07:50:37 -07:00
										 |  |  |     ON_CALL(*this, visit(_)).WillByDefault(Return(test_result())); | 
					
						
							| 
									
										
										
										
											2016-04-20 09:11:33 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-20 13:16:21 -07:00
										 |  |  |   MOCK_METHOD(test_result, visit, (T)); | 
					
						
							|  |  |  |   MOCK_METHOD(void, unexpected, ()); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto operator()(T value) -> test_result { return visit(value); } | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   template <typename U> auto operator()(U) -> test_result { | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  |     unexpected(); | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |     return test_result(); | 
					
						
							| 
									
										
										
										
											2014-07-14 07:27:07 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-07-14 06:55:29 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  | template <typename T> struct visit_type { using type = T; }; | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 20:54:15 -07:00
										 |  |  | #define VISIT_TYPE(type_, visit_type_) \
 | 
					
						
							|  |  |  |   template <> struct visit_type<type_> { using type = visit_type_; } | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | VISIT_TYPE(signed char, int); | 
					
						
							|  |  |  | VISIT_TYPE(unsigned char, unsigned); | 
					
						
							|  |  |  | VISIT_TYPE(short, int); | 
					
						
							|  |  |  | VISIT_TYPE(unsigned short, unsigned); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if LONG_MAX == INT_MAX
 | 
					
						
							|  |  |  | VISIT_TYPE(long, int); | 
					
						
							|  |  |  | VISIT_TYPE(unsigned long, unsigned); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-08-26 09:09:43 -07:00
										 |  |  | VISIT_TYPE(long, long long); | 
					
						
							|  |  |  | VISIT_TYPE(unsigned long, unsigned long long); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | #define CHECK_ARG(Char, expected, value)                                  \
 | 
					
						
							|  |  |  |   {                                                                       \ | 
					
						
							|  |  |  |     testing::StrictMock<mock_visitor<decltype(expected)>> visitor;        \ | 
					
						
							|  |  |  |     EXPECT_CALL(visitor, visit(expected));                                \ | 
					
						
							|  |  |  |     using iterator = std::back_insert_iterator<buffer<Char>>;             \ | 
					
						
							| 
									
										
										
										
											2023-05-11 18:37:33 -07:00
										 |  |  |     auto var = value;                                                     \ | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |     fmt::visit_format_arg(                                                \ | 
					
						
							|  |  |  |         visitor,                                                          \ | 
					
						
							|  |  |  |         fmt::detail::make_arg<fmt::basic_format_context<iterator, Char>>( \ | 
					
						
							| 
									
										
										
										
											2023-05-11 18:37:33 -07:00
										 |  |  |             var));                                                        \ | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | #define CHECK_ARG_SIMPLE(value)                             \
 | 
					
						
							|  |  |  |   {                                                         \ | 
					
						
							|  |  |  |     using value_type = decltype(value);                     \ | 
					
						
							|  |  |  |     typename visit_type<value_type>::type expected = value; \ | 
					
						
							|  |  |  |     CHECK_ARG(char, expected, value)                        \ | 
					
						
							|  |  |  |     CHECK_ARG(wchar_t, expected, value)                     \ | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | template <typename T> class numeric_arg_test : public testing::Test {}; | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:57:52 -07:00
										 |  |  | using test_types = | 
					
						
							| 
									
										
										
										
											2021-04-24 11:35:49 -07:00
										 |  |  |     testing::Types<bool, signed char, unsigned char, short, unsigned short, int, | 
					
						
							|  |  |  |                    unsigned, long, unsigned long, long long, unsigned long long, | 
					
						
							|  |  |  |                    float, double, long double>; | 
					
						
							| 
									
										
										
										
											2022-06-09 16:57:52 -07:00
										 |  |  | TYPED_TEST_SUITE(numeric_arg_test, test_types); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | template <typename T, fmt::enable_if_t<std::is_integral<T>::value, int> = 0> | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | auto test_value() -> T { | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  |   return static_cast<T>(42); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | template <typename T, | 
					
						
							|  |  |  |           fmt::enable_if_t<std::is_floating_point<T>::value, int> = 0> | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | auto test_value() -> T { | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  |   return static_cast<T>(4.2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TYPED_TEST(numeric_arg_test, make_and_visit) { | 
					
						
							|  |  |  |   CHECK_ARG_SIMPLE(test_value<TypeParam>()); | 
					
						
							|  |  |  |   CHECK_ARG_SIMPLE(std::numeric_limits<TypeParam>::min()); | 
					
						
							|  |  |  |   CHECK_ARG_SIMPLE(std::numeric_limits<TypeParam>::max()); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 15:47:44 -07:00
										 |  |  | TEST(arg_test, char_arg) { CHECK_ARG(char, 'a', 'a'); } | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(arg_test, string_arg) { | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  |   char str_data[] = "test"; | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  |   char* str = str_data; | 
					
						
							|  |  |  |   const char* cstr = str; | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   CHECK_ARG(char, cstr, str); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   auto sv = fmt::string_view(str); | 
					
						
							|  |  |  |   CHECK_ARG(char, sv, std::string(str)); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(arg_test, wstring_arg) { | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  |   wchar_t str_data[] = L"test"; | 
					
						
							| 
									
										
										
										
											2019-01-12 18:27:38 -08:00
										 |  |  |   wchar_t* str = str_data; | 
					
						
							|  |  |  |   const wchar_t* cstr = str; | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-21 17:37:07 -07:00
										 |  |  |   auto sv = fmt::basic_string_view<wchar_t>(str); | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   CHECK_ARG(wchar_t, cstr, str); | 
					
						
							|  |  |  |   CHECK_ARG(wchar_t, cstr, cstr); | 
					
						
							|  |  |  |   CHECK_ARG(wchar_t, sv, std::wstring(str)); | 
					
						
							| 
									
										
										
										
											2021-05-21 17:37:07 -07:00
										 |  |  |   CHECK_ARG(wchar_t, sv, fmt::basic_string_view<wchar_t>(str)); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(arg_test, pointer_arg) { | 
					
						
							| 
									
										
										
										
											2019-05-30 07:01:31 -07:00
										 |  |  |   void* p = nullptr; | 
					
						
							|  |  |  |   const void* cp = nullptr; | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   CHECK_ARG(char, cp, p); | 
					
						
							|  |  |  |   CHECK_ARG(wchar_t, cp, p); | 
					
						
							|  |  |  |   CHECK_ARG_SIMPLE(cp); | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-03 14:04:59 -08:00
										 |  |  | struct check_custom { | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto operator()(fmt::basic_format_arg<fmt::format_context>::handle h) const | 
					
						
							|  |  |  |       -> test_result { | 
					
						
							| 
									
										
										
										
											2020-10-16 02:41:56 +02:00
										 |  |  |     struct test_buffer final : fmt::detail::buffer<char> { | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |       char data[10]; | 
					
						
							| 
									
										
										
										
											2020-05-10 07:25:42 -07:00
										 |  |  |       test_buffer() : fmt::detail::buffer<char>(data, 0, 10) {} | 
					
						
							| 
									
										
										
										
											2021-07-09 08:05:02 -07:00
										 |  |  |       void grow(size_t) override {} | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |     } buffer; | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |     auto parse_ctx = fmt::format_parse_context(""); | 
					
						
							|  |  |  |     auto ctx = fmt::format_context(fmt::detail::buffer_appender<char>(buffer), | 
					
						
							|  |  |  |                                    fmt::format_args()); | 
					
						
							| 
									
										
										
										
											2019-02-09 19:34:42 -08:00
										 |  |  |     h.format(parse_ctx, ctx); | 
					
						
							| 
									
										
										
										
											2018-09-19 08:55:45 -07:00
										 |  |  |     EXPECT_EQ("test", std::string(buffer.data, buffer.size())); | 
					
						
							|  |  |  |     return test_result(); | 
					
						
							| 
									
										
										
										
											2018-03-03 14:04:59 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(arg_test, custom_arg) { | 
					
						
							|  |  |  |   auto test = test_struct(); | 
					
						
							| 
									
										
										
										
											2020-07-09 08:41:05 -07:00
										 |  |  |   using visitor = | 
					
						
							| 
									
										
										
										
											2020-07-09 09:04:46 -07:00
										 |  |  |       mock_visitor<fmt::basic_format_arg<fmt::format_context>::handle>; | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto&& v = testing::StrictMock<visitor>(); | 
					
						
							| 
									
										
										
										
											2020-07-11 06:53:25 -07:00
										 |  |  |   EXPECT_CALL(v, visit(_)).WillOnce(Invoke(check_custom())); | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   fmt::visit_format_arg(v, fmt::detail::make_arg<fmt::format_context>(test)); | 
					
						
							| 
									
										
										
										
											2014-07-14 06:55:29 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(arg_test, visit_invalid_arg) { | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto&& visitor = testing::StrictMock<mock_visitor<fmt::monostate>>(); | 
					
						
							| 
									
										
										
										
											2016-12-27 07:43:25 -08:00
										 |  |  |   EXPECT_CALL(visitor, visit(_)); | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  |   auto arg = fmt::basic_format_arg<fmt::format_context>(); | 
					
						
							| 
									
										
										
										
											2019-01-29 16:31:25 -05:00
										 |  |  |   fmt::visit_format_arg(visitor, arg); | 
					
						
							| 
									
										
										
										
											2014-07-16 07:55:31 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | #if FMT_USE_CONSTEXPR
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 16:27:29 -08:00
										 |  |  | enum class arg_id_result { none, empty, index, name }; | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | struct test_arg_id_handler { | 
					
						
							|  |  |  |   arg_id_result res = arg_id_result::none; | 
					
						
							|  |  |  |   int index = 0; | 
					
						
							|  |  |  |   string_view name; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 16:27:29 -08:00
										 |  |  |   constexpr void on_auto() { res = arg_id_result::empty; } | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 16:27:29 -08:00
										 |  |  |   constexpr void on_index(int i) { | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |     res = arg_id_result::index; | 
					
						
							|  |  |  |     index = i; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 16:27:29 -08:00
										 |  |  |   constexpr void on_name(string_view n) { | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |     res = arg_id_result::name; | 
					
						
							|  |  |  |     name = n; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <size_t N> | 
					
						
							|  |  |  | constexpr test_arg_id_handler parse_arg_id(const char (&s)[N]) { | 
					
						
							| 
									
										
										
										
											2022-12-24 16:27:29 -08:00
										 |  |  |   auto h = test_arg_id_handler(); | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |   fmt::detail::parse_arg_id(s, s + N, h); | 
					
						
							|  |  |  |   return h; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-30 10:20:07 -08:00
										 |  |  | TEST(core_test, constexpr_parse_arg_id) { | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |   static_assert(parse_arg_id(":").res == arg_id_result::empty, ""); | 
					
						
							|  |  |  |   static_assert(parse_arg_id("}").res == arg_id_result::empty, ""); | 
					
						
							|  |  |  |   static_assert(parse_arg_id("42:").res == arg_id_result::index, ""); | 
					
						
							|  |  |  |   static_assert(parse_arg_id("42:").index == 42, ""); | 
					
						
							|  |  |  |   static_assert(parse_arg_id("foo:").res == arg_id_result::name, ""); | 
					
						
							|  |  |  |   static_assert(parse_arg_id("foo:").name.size() == 3, ""); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 19:22:39 -08:00
										 |  |  | template <size_t N> constexpr auto parse_test_specs(const char (&s)[N]) { | 
					
						
							|  |  |  |   auto ctx = fmt::detail::compile_parse_context<char>(fmt::string_view(s, N), | 
					
						
							|  |  |  |                                                       43, nullptr); | 
					
						
							| 
									
										
										
										
											2022-12-25 12:31:38 -08:00
										 |  |  |   auto specs = fmt::detail::dynamic_format_specs<>(); | 
					
						
							|  |  |  |   fmt::detail::parse_format_specs(s, s + N - 1, specs, ctx, | 
					
						
							|  |  |  |                                   fmt::detail::type::float_type); | 
					
						
							|  |  |  |   return specs; | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(core_test, constexpr_parse_format_specs) { | 
					
						
							| 
									
										
										
										
											2022-12-24 19:22:39 -08:00
										 |  |  |   static_assert(parse_test_specs("<").align == fmt::align::left, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs("*^").fill[0] == '*', ""); | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |   static_assert(parse_test_specs("+").sign == fmt::sign::plus, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs("-").sign == fmt::sign::minus, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs(" ").sign == fmt::sign::space, ""); | 
					
						
							| 
									
										
										
										
											2022-12-24 19:22:39 -08:00
										 |  |  |   static_assert(parse_test_specs("#").alt, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs("0").align == fmt::align::numeric, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs("L").localized, ""); | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |   static_assert(parse_test_specs("42").width == 42, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs("{42}").width_ref.val.index == 42, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs(".42").precision == 42, ""); | 
					
						
							|  |  |  |   static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, ""); | 
					
						
							| 
									
										
										
										
											2022-12-30 14:59:42 -08:00
										 |  |  |   static_assert( | 
					
						
							|  |  |  |       parse_test_specs("f").type == fmt::presentation_type::fixed_lower, ""); | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct test_format_string_handler { | 
					
						
							|  |  |  |   constexpr void on_text(const char*, const char*) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   constexpr auto on_arg_id() -> int { return 0; } | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   template <typename T> constexpr auto on_arg_id(T) -> int { return 0; } | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constexpr void on_replacement_field(int, const char*) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   constexpr auto on_format_specs(int, const char* begin, const char*) -> const | 
					
						
							|  |  |  |       char* { | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |     return begin; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constexpr void on_error(const char*) { error = true; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool error = false; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <size_t N> constexpr bool parse_string(const char (&s)[N]) { | 
					
						
							|  |  |  |   auto h = test_format_string_handler(); | 
					
						
							|  |  |  |   fmt::detail::parse_format_string<true>(fmt::string_view(s, N - 1), h); | 
					
						
							|  |  |  |   return !h.error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | TEST(core_test, constexpr_parse_format_string) { | 
					
						
							| 
									
										
										
										
											2021-05-19 16:08:56 -07:00
										 |  |  |   static_assert(parse_string("foo"), ""); | 
					
						
							|  |  |  |   static_assert(!parse_string("}"), ""); | 
					
						
							|  |  |  |   static_assert(parse_string("{}"), ""); | 
					
						
							|  |  |  |   static_assert(parse_string("{42}"), ""); | 
					
						
							|  |  |  |   static_assert(parse_string("{foo}"), ""); | 
					
						
							|  |  |  |   static_assert(parse_string("{:}"), ""); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif  // FMT_USE_CONSTEXPR
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 07:08:04 -07:00
										 |  |  | struct enabled_formatter {}; | 
					
						
							| 
									
										
										
										
											2022-04-12 06:45:46 -07:00
										 |  |  | struct enabled_ptr_formatter {}; | 
					
						
							| 
									
										
										
										
											2019-06-07 07:08:04 -07:00
										 |  |  | struct disabled_formatter {}; | 
					
						
							|  |  |  | struct disabled_formatter_convertible { | 
					
						
							|  |  |  |   operator int() const { return 42; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | FMT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | template <> struct formatter<enabled_formatter> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2019-06-07 07:08:04 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto format(enabled_formatter, format_context& ctx) const | 
					
						
							|  |  |  |       -> decltype(ctx.out()) { | 
					
						
							| 
									
										
										
										
											2019-06-07 07:08:04 -07:00
										 |  |  |     return ctx.out(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2022-04-12 06:45:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<enabled_ptr_formatter*> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2022-04-12 06:45:46 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto format(enabled_ptr_formatter*, format_context& ctx) const | 
					
						
							| 
									
										
										
										
											2022-04-12 06:45:46 -07:00
										 |  |  |       -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     return ctx.out(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-06-07 07:08:04 -07:00
										 |  |  | FMT_END_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(core_test, has_formatter) { | 
					
						
							| 
									
										
										
										
											2019-11-14 10:08:24 -05:00
										 |  |  |   using fmt::has_formatter; | 
					
						
							| 
									
										
										
										
											2019-06-07 07:08:04 -07:00
										 |  |  |   using context = fmt::format_context; | 
					
						
							| 
									
										
										
										
											2019-11-14 10:08:24 -05:00
										 |  |  |   static_assert(has_formatter<enabled_formatter, context>::value, ""); | 
					
						
							|  |  |  |   static_assert(!has_formatter<disabled_formatter, context>::value, ""); | 
					
						
							| 
									
										
										
										
											2019-12-21 13:10:45 -08:00
										 |  |  |   static_assert(!has_formatter<disabled_formatter_convertible, context>::value, | 
					
						
							|  |  |  |                 ""); | 
					
						
							| 
									
										
										
										
											2018-06-07 20:20:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 18:47:59 -07:00
										 |  |  | struct const_formattable {}; | 
					
						
							|  |  |  | struct nonconst_formattable {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | FMT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | template <> struct formatter<const_formattable> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2021-08-26 18:47:59 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto format(const const_formattable&, format_context& ctx) | 
					
						
							|  |  |  |       -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     auto test = string_view("test"); | 
					
						
							|  |  |  |     return std::copy_n(test.data(), test.size(), ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <> struct formatter<nonconst_formattable> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2021-08-26 18:47:59 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto format(nonconst_formattable&, format_context& ctx) | 
					
						
							|  |  |  |       -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     auto test = string_view("test"); | 
					
						
							|  |  |  |     return std::copy_n(test.data(), test.size(), ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | FMT_END_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 08:26:27 -08:00
										 |  |  | struct convertible_to_pointer { | 
					
						
							|  |  |  |   operator const int*() const { return nullptr; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-14 13:08:14 -08:00
										 |  |  | struct convertible_to_pointer_formattable { | 
					
						
							|  |  |  |   operator const int*() const { return nullptr; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | FMT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | template <> struct formatter<convertible_to_pointer_formattable> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2022-01-14 13:08:14 -08:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto format(convertible_to_pointer_formattable, format_context& ctx) const | 
					
						
							|  |  |  |       -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     auto test = string_view("test"); | 
					
						
							|  |  |  |     return std::copy_n(test.data(), test.size(), ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | FMT_END_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 06:31:29 -08:00
										 |  |  | enum class unformattable_scoped_enum {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(core_test, is_formattable) { | 
					
						
							| 
									
										
										
										
											2021-08-26 17:36:29 -07:00
										 |  |  |   static_assert(!fmt::is_formattable<wchar_t>::value, ""); | 
					
						
							| 
									
										
										
										
											2021-10-17 08:58:41 -07:00
										 |  |  | #ifdef __cpp_char8_t
 | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<char8_t>::value, ""); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<char16_t>::value, ""); | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<char32_t>::value, ""); | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   static_assert(!fmt::is_formattable<signed char*>::value, ""); | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<unsigned char*>::value, ""); | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<const signed char*>::value, ""); | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<const unsigned char*>::value, ""); | 
					
						
							| 
									
										
										
										
											2021-08-26 15:47:44 -07:00
										 |  |  |   static_assert(!fmt::is_formattable<const wchar_t*>::value, ""); | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<const wchar_t[3]>::value, ""); | 
					
						
							| 
									
										
										
										
											2021-08-26 17:36:29 -07:00
										 |  |  |   static_assert(!fmt::is_formattable<fmt::basic_string_view<wchar_t>>::value, | 
					
						
							|  |  |  |                 ""); | 
					
						
							| 
									
										
										
										
											2021-02-28 15:25:33 -08:00
										 |  |  |   static_assert(fmt::is_formattable<enabled_formatter>::value, ""); | 
					
						
							| 
									
										
										
										
											2022-04-12 06:45:46 -07:00
										 |  |  |   static_assert(!fmt::is_formattable<enabled_ptr_formatter*>::value, ""); | 
					
						
							| 
									
										
										
										
											2021-02-28 15:25:33 -08:00
										 |  |  |   static_assert(!fmt::is_formattable<disabled_formatter>::value, ""); | 
					
						
							| 
									
										
										
										
											2023-04-09 09:08:46 -07:00
										 |  |  |   static_assert(!fmt::is_formattable<disabled_formatter_convertible>::value, | 
					
						
							|  |  |  |                 ""); | 
					
						
							| 
									
										
										
										
											2021-08-26 17:36:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 18:47:59 -07:00
										 |  |  |   static_assert(fmt::is_formattable<const_formattable&>::value, ""); | 
					
						
							|  |  |  |   static_assert(fmt::is_formattable<const const_formattable&>::value, ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static_assert(fmt::is_formattable<nonconst_formattable&>::value, ""); | 
					
						
							| 
									
										
										
										
											2022-05-29 15:01:43 -07:00
										 |  |  | #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
 | 
					
						
							| 
									
										
										
										
											2021-08-26 18:47:59 -07:00
										 |  |  |   static_assert(!fmt::is_formattable<const nonconst_formattable&>::value, ""); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 08:26:27 -08:00
										 |  |  |   static_assert(!fmt::is_formattable<convertible_to_pointer>::value, ""); | 
					
						
							| 
									
										
										
										
											2022-01-14 13:08:14 -08:00
										 |  |  |   const auto f = convertible_to_pointer_formattable(); | 
					
						
							|  |  |  |   EXPECT_EQ(fmt::format("{}", f), "test"); | 
					
						
							| 
									
										
										
										
											2021-11-13 08:26:27 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-23 22:55:22 +02:00
										 |  |  |   static_assert(!fmt::is_formattable<void (*)()>::value, ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct s; | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<int(s::*)>::value, ""); | 
					
						
							|  |  |  |   static_assert(!fmt::is_formattable<int (s::*)()>::value, ""); | 
					
						
							| 
									
										
										
										
											2022-01-28 06:31:29 -08:00
										 |  |  |   static_assert(!fmt::is_formattable<unformattable_scoped_enum>::value, ""); | 
					
						
							| 
									
										
										
										
											2023-01-02 10:53:41 -08:00
										 |  |  |   static_assert(!fmt::is_formattable<unformattable_scoped_enum>::value, ""); | 
					
						
							| 
									
										
										
										
											2021-02-28 15:25:33 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  | TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(core_test, format_to) { | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto s = std::string(); | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  |   fmt::format_to(std::back_inserter(s), "{}", 42); | 
					
						
							|  |  |  |   EXPECT_EQ(s, "42"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | #ifdef __cpp_lib_byte
 | 
					
						
							|  |  |  | TEST(core_test, format_byte) { | 
					
						
							|  |  |  |   EXPECT_EQ(fmt::format("{}", std::byte(42)), "42"); | 
					
						
							| 
									
										
										
										
											2022-01-28 06:31:29 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-01-28 06:31:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  | struct convertible_to_int { | 
					
						
							|  |  |  |   operator int() const { return 42; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | struct convertible_to_cstring { | 
					
						
							| 
									
										
										
										
											2020-02-07 18:47:48 -08:00
										 |  |  |   operator const char*() const { return "foo"; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  | FMT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | template <> struct formatter<convertible_to_int> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto format(convertible_to_int, format_context& ctx) const | 
					
						
							|  |  |  |       -> decltype(ctx.out()) { | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  |     return std::copy_n("foo", 3, ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-02-07 18:47:48 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  | template <> struct formatter<convertible_to_cstring> { | 
					
						
							| 
									
										
										
										
											2020-11-15 09:03:20 -08:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2020-02-07 18:47:48 -08:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   auto format(convertible_to_cstring, format_context& ctx) const | 
					
						
							| 
									
										
										
										
											2020-02-07 18:47:48 -08:00
										 |  |  |       -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     return std::copy_n("bar", 3, ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  | FMT_END_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:11:01 -07:00
										 |  |  | TEST(core_test, formatter_overrides_implicit_conversion) { | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  |   EXPECT_EQ(fmt::format("{}", convertible_to_int()), "foo"); | 
					
						
							| 
									
										
										
										
											2023-01-02 09:45:51 -08:00
										 |  |  |   EXPECT_EQ(fmt::format("{}", convertible_to_cstring()), "bar"); | 
					
						
							| 
									
										
										
										
											2019-06-07 06:25:46 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  | // Test that check is not found by ADL.
 | 
					
						
							| 
									
										
										
										
											2021-03-17 20:59:36 -07:00
										 |  |  | template <typename T> void check(T); | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  | TEST(core_test, adl_check) { | 
					
						
							|  |  |  |   EXPECT_EQ(fmt::format("{}", test_struct()), "test"); | 
					
						
							| 
									
										
										
										
											2018-10-24 18:42:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-27 17:10:19 -07:00
										 |  |  | struct implicitly_convertible_to_string_view { | 
					
						
							|  |  |  |   operator fmt::string_view() const { return "foo"; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-03 11:57:37 -08:00
										 |  |  | TEST(core_test, no_implicit_conversion_to_string_view) { | 
					
						
							|  |  |  |   EXPECT_FALSE( | 
					
						
							|  |  |  |       fmt::is_formattable<implicitly_convertible_to_string_view>::value); | 
					
						
							| 
									
										
										
										
											2018-10-27 17:10:19 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-03 11:57:37 -08:00
										 |  |  | #ifdef FMT_USE_STRING_VIEW
 | 
					
						
							|  |  |  | struct implicitly_convertible_to_std_string_view { | 
					
						
							|  |  |  |   operator std::string_view() const { return "foo"; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(core_test, no_implicit_conversion_to_std_string_view) { | 
					
						
							|  |  |  |   EXPECT_FALSE( | 
					
						
							|  |  |  |       fmt::is_formattable<implicitly_convertible_to_std_string_view>::value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-27 17:10:19 -07:00
										 |  |  | // std::is_constructible is broken in MSVC until version 2015.
 | 
					
						
							| 
									
										
										
										
											2022-05-29 15:01:43 -07:00
										 |  |  | #if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1900
 | 
					
						
							| 
									
										
										
										
											2018-10-27 17:10:19 -07:00
										 |  |  | struct explicitly_convertible_to_string_view { | 
					
						
							|  |  |  |   explicit operator fmt::string_view() const { return "foo"; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  | TEST(core_test, format_explicitly_convertible_to_string_view) { | 
					
						
							| 
									
										
										
										
											2022-02-04 11:12:04 -08:00
										 |  |  |   // Types explicitly convertible to string_view are not formattable by
 | 
					
						
							|  |  |  |   // default because it may introduce ODR violations.
 | 
					
						
							|  |  |  |   static_assert( | 
					
						
							|  |  |  |       !fmt::is_formattable<explicitly_convertible_to_string_view>::value, ""); | 
					
						
							| 
									
										
										
										
											2018-10-27 17:10:19 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 13:10:45 -08:00
										 |  |  | #  ifdef FMT_USE_STRING_VIEW
 | 
					
						
							| 
									
										
										
										
											2019-10-04 17:21:10 -07:00
										 |  |  | struct explicitly_convertible_to_std_string_view { | 
					
						
							|  |  |  |   explicit operator std::string_view() const { return "foo"; } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 16:19:01 -07:00
										 |  |  | TEST(core_test, format_explicitly_convertible_to_std_string_view) { | 
					
						
							| 
									
										
										
										
											2022-02-04 11:12:04 -08:00
										 |  |  |   // Types explicitly convertible to string_view are not formattable by
 | 
					
						
							|  |  |  |   // default because it may introduce ODR violations.
 | 
					
						
							|  |  |  |   static_assert( | 
					
						
							|  |  |  |       !fmt::is_formattable<explicitly_convertible_to_std_string_view>::value, | 
					
						
							|  |  |  |       ""); | 
					
						
							| 
									
										
										
										
											2019-10-04 17:21:10 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-12-21 13:10:45 -08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2018-10-27 17:10:19 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-11-25 08:30:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-20 06:13:13 -07:00
										 |  |  | namespace adl_test { | 
					
						
							|  |  |  | template <typename... T> void make_format_args(const T&...) = delete; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct string : std::string {}; | 
					
						
							|  |  |  | }  // namespace adl_test
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Test that formatting functions compile when make_format_args is found by ADL.
 | 
					
						
							|  |  |  | TEST(core_test, adl) { | 
					
						
							|  |  |  |   // Only check compilation and don't run the code to avoid polluting the output
 | 
					
						
							|  |  |  |   // and since the output is tested elsewhere.
 | 
					
						
							|  |  |  |   if (fmt::detail::const_check(true)) return; | 
					
						
							|  |  |  |   auto s = adl_test::string(); | 
					
						
							|  |  |  |   char buf[10]; | 
					
						
							| 
									
										
										
										
											2021-11-24 17:09:41 -05:00
										 |  |  |   (void)fmt::format("{}", s); | 
					
						
							| 
									
										
										
										
											2021-05-20 06:13:13 -07:00
										 |  |  |   fmt::format_to(buf, "{}", s); | 
					
						
							|  |  |  |   fmt::format_to_n(buf, 10, "{}", s); | 
					
						
							| 
									
										
										
										
											2021-11-24 17:09:41 -05:00
										 |  |  |   (void)fmt::formatted_size("{}", s); | 
					
						
							| 
									
										
										
										
											2021-05-20 06:13:13 -07:00
										 |  |  |   fmt::print("{}", s); | 
					
						
							|  |  |  |   fmt::print(stdout, "{}", s); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-07-24 08:02:23 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-05 08:35:08 -07:00
										 |  |  | TEST(core_test, has_const_formatter) { | 
					
						
							|  |  |  |   EXPECT_TRUE((fmt::detail::has_const_formatter<const_formattable, | 
					
						
							|  |  |  |                                                 fmt::format_context>())); | 
					
						
							|  |  |  |   EXPECT_FALSE((fmt::detail::has_const_formatter<nonconst_formattable, | 
					
						
							| 
									
										
										
										
											2021-07-24 08:02:23 -07:00
										 |  |  |                                                  fmt::format_context>())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(core_test, format_nonconst) { | 
					
						
							|  |  |  |   EXPECT_EQ(fmt::format("{}", nonconst_formattable()), "test"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-06-26 15:46:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct its_a_trap { | 
					
						
							|  |  |  |   template <typename T> operator T() const { | 
					
						
							|  |  |  |     auto v = T(); | 
					
						
							|  |  |  |     v.x = 42; | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | FMT_BEGIN_NAMESPACE | 
					
						
							|  |  |  | template <> struct formatter<its_a_trap> { | 
					
						
							| 
									
										
										
										
											2023-07-13 17:17:00 -07:00
										 |  |  |   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | 
					
						
							| 
									
										
										
										
											2023-06-26 15:46:12 -07:00
										 |  |  |     return ctx.begin(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto format(its_a_trap, format_context& ctx) const -> decltype(ctx.out()) { | 
					
						
							|  |  |  |     auto s = string_view("42"); | 
					
						
							|  |  |  |     return std::copy(s.begin(), s.end(), ctx.out()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | FMT_END_NAMESPACE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(core_test, trappy_conversion) { | 
					
						
							|  |  |  |   EXPECT_EQ(fmt::format("{}", its_a_trap()), "42"); | 
					
						
							|  |  |  | } |