| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  Formatting library implementation tests. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Copyright (c) 2012-2014, Victor Zverovich | 
					
						
							|  |  |  |  All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |     list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |     this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |     and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 
					
						
							|  |  |  |  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
					
						
							|  |  |  |  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | 
					
						
							|  |  |  |  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
					
						
							|  |  |  |  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
					
						
							|  |  |  |  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
					
						
							|  |  |  |  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
					
						
							|  |  |  |  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-22 09:24:54 -07:00
										 |  |  | #define FMT_NOEXCEPT
 | 
					
						
							| 
									
										
										
										
											2018-01-28 20:50:43 -08:00
										 |  |  | #undef FMT_SHARED
 | 
					
						
							| 
									
										
										
										
											2015-06-22 08:17:23 -07:00
										 |  |  | #include "test-assert.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  | // Include format.cc instead of format.h to test implementation-specific stuff.
 | 
					
						
							| 
									
										
										
										
											2016-04-24 09:06:12 -07:00
										 |  |  | #include "fmt/format.cc"
 | 
					
						
							| 
									
										
										
										
											2017-12-17 08:36:19 -08:00
										 |  |  | #include "fmt/printf.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-04 09:04:28 -08:00
										 |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  | #include <cstring>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-04 09:04:28 -08:00
										 |  |  | #include "gmock/gmock.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  | #include "gtest-extra.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  | #include "util.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-04 09:04:28 -08:00
										 |  |  | #undef min
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:06:07 -07:00
										 |  |  | #undef max
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 13:22:45 -08:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | struct ValueExtractor { | 
					
						
							|  |  |  |   T operator()(T value) { | 
					
						
							|  |  |  |     return value; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template <typename U> | 
					
						
							|  |  |  |   T operator()(U) { | 
					
						
							|  |  |  |     throw std::runtime_error(fmt::format("invalid type {}", typeid(U).name())); | 
					
						
							|  |  |  |     return T(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  | TEST(FormatTest, ArgConverter) { | 
					
						
							| 
									
										
										
										
											2017-08-26 09:09:43 -07:00
										 |  |  |   long long value = std::numeric_limits<long long>::max(); | 
					
						
							| 
									
										
										
										
											2017-02-05 06:54:03 -08:00
										 |  |  |   auto arg = fmt::internal::make_arg<fmt::context>(value); | 
					
						
							| 
									
										
										
										
											2017-08-26 09:09:43 -07:00
										 |  |  |   visit(fmt::internal::ArgConverter<long long, fmt::context>(arg, 'd'), arg); | 
					
						
							|  |  |  |   EXPECT_EQ(value, visit(ValueExtractor<long long>(), arg)); | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  | TEST(FormatTest, FormatNegativeNaN) { | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  |   double nan = std::numeric_limits<double>::quiet_NaN(); | 
					
						
							| 
									
										
										
										
											2017-01-22 07:40:21 -08:00
										 |  |  |   if (fmt::internal::fputil::isnegative(-nan)) | 
					
						
							| 
									
										
										
										
											2014-09-05 07:35:00 -07:00
										 |  |  |     EXPECT_EQ("-nan", fmt::format("{}", -nan)); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     fmt::print("Warning: compiler doesn't handle negative NaN correctly"); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  | TEST(FormatTest, StrError) { | 
					
						
							|  |  |  |   char *message = 0; | 
					
						
							|  |  |  |   char buffer[BUFFER_SIZE]; | 
					
						
							| 
									
										
										
										
											2015-06-22 08:17:23 -07:00
										 |  |  |   EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = 0, 0), "invalid buffer"); | 
					
						
							| 
									
										
										
										
											2016-03-08 06:55:41 -08:00
										 |  |  |   EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = buffer, 0), | 
					
						
							|  |  |  |                 "invalid buffer"); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  |   buffer[0] = 'x'; | 
					
						
							| 
									
										
										
										
											2015-10-21 08:30:10 -07:00
										 |  |  | #if defined(_GNU_SOURCE) && !defined(__COVERITY__)
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  |   // Use invalid error code to make sure that safe_strerror returns an error
 | 
					
						
							|  |  |  |   // message in the buffer rather than a pointer to a static string.
 | 
					
						
							| 
									
										
										
										
											2015-10-21 08:30:10 -07:00
										 |  |  |   int error_code = -1; | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   int error_code = EDOM; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-12 07:56:58 -07:00
										 |  |  |   int result = fmt::safe_strerror(error_code, message = buffer, BUFFER_SIZE); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  |   EXPECT_EQ(0, result); | 
					
						
							|  |  |  |   std::size_t message_size = std::strlen(message); | 
					
						
							|  |  |  |   EXPECT_GE(BUFFER_SIZE - 1u, message_size); | 
					
						
							|  |  |  |   EXPECT_EQ(get_system_error(error_code), message); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // safe_strerror never uses buffer on MinGW.
 | 
					
						
							|  |  |  | #ifndef __MINGW32__
 | 
					
						
							| 
									
										
										
										
											2015-06-12 07:56:58 -07:00
										 |  |  |   result = fmt::safe_strerror(error_code, message = buffer, message_size); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  |   EXPECT_EQ(ERANGE, result); | 
					
						
							| 
									
										
										
										
											2015-06-12 07:56:58 -07:00
										 |  |  |   result = fmt::safe_strerror(error_code, message = buffer, 1); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:44:41 -07:00
										 |  |  |   EXPECT_EQ(buffer, message);  // Message should point to buffer.
 | 
					
						
							|  |  |  |   EXPECT_EQ(ERANGE, result); | 
					
						
							|  |  |  |   EXPECT_STREQ("", message); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  | TEST(FormatTest, FormatErrorCode) { | 
					
						
							|  |  |  |   std::string msg = "error 42", sep = ": "; | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     fmt::memory_buffer buffer; | 
					
						
							|  |  |  |     format_to(buffer, "garbage"); | 
					
						
							|  |  |  |     fmt::format_error_code(buffer, 42, "test"); | 
					
						
							|  |  |  |     EXPECT_EQ("test: " + msg, to_string(buffer)); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  |   } | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     fmt::memory_buffer buffer; | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  |     std::string prefix( | 
					
						
							|  |  |  |         fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size() + 1, 'x'); | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     fmt::format_error_code(buffer, 42, prefix); | 
					
						
							|  |  |  |     EXPECT_EQ(msg, to_string(buffer)); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-03-02 07:01:21 -08:00
										 |  |  |   int codes[] = {42, -1}; | 
					
						
							|  |  |  |   for (std::size_t i = 0, n = sizeof(codes) / sizeof(*codes); i < n; ++i) { | 
					
						
							|  |  |  |     // Test maximum buffer size.
 | 
					
						
							|  |  |  |     msg = fmt::format("error {}", codes[i]); | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     fmt::memory_buffer buffer; | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  |     std::string prefix( | 
					
						
							|  |  |  |         fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size(), 'x'); | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     fmt::format_error_code(buffer, codes[i], prefix); | 
					
						
							|  |  |  |     EXPECT_EQ(prefix + sep + msg, to_string(buffer)); | 
					
						
							| 
									
										
										
										
											2014-09-25 07:38:16 -07:00
										 |  |  |     std::size_t size = fmt::internal::INLINE_BUFFER_SIZE; | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     EXPECT_EQ(size, buffer.size()); | 
					
						
							| 
									
										
										
										
											2017-03-11 07:43:26 -08:00
										 |  |  |     buffer.resize(0); | 
					
						
							| 
									
										
										
										
											2016-03-02 07:01:21 -08:00
										 |  |  |     // Test with a message that doesn't fit into the buffer.
 | 
					
						
							|  |  |  |     prefix += 'x'; | 
					
						
							| 
									
										
										
										
											2017-02-18 09:13:12 -08:00
										 |  |  |     fmt::format_error_code(buffer, codes[i], prefix); | 
					
						
							|  |  |  |     EXPECT_EQ(msg, to_string(buffer)); | 
					
						
							| 
									
										
										
										
											2014-09-05 08:04:26 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } |