convert_test.cc (57379B)
1 // Copyright 2020 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <assert.h> 16 #include <locale.h> 17 #include <stdarg.h> 18 #include <stdio.h> 19 20 #include <algorithm> 21 #include <climits> 22 #include <cmath> 23 #include <cstdlib> 24 #include <cstring> 25 #include <cwctype> 26 #include <limits> 27 #include <set> 28 #include <sstream> 29 #include <string> 30 #include <thread> // NOLINT 31 #include <type_traits> 32 #include <vector> 33 34 #include "gmock/gmock.h" 35 #include "gtest/gtest.h" 36 #include "absl/base/attributes.h" 37 #include "absl/base/internal/raw_logging.h" 38 #include "absl/log/log.h" 39 #include "absl/numeric/int128.h" 40 #include "absl/strings/ascii.h" 41 #include "absl/strings/internal/str_format/arg.h" 42 #include "absl/strings/internal/str_format/bind.h" 43 #include "absl/strings/match.h" 44 #include "absl/strings/str_format.h" 45 #include "absl/strings/string_view.h" 46 #include "absl/types/optional.h" 47 #include "absl/types/span.h" 48 49 #if defined(ABSL_HAVE_STD_STRING_VIEW) 50 #include <string_view> 51 #endif 52 53 namespace absl { 54 ABSL_NAMESPACE_BEGIN 55 namespace str_format_internal { 56 namespace { 57 58 struct NativePrintfTraits { 59 bool hex_float_has_glibc_rounding; 60 bool hex_float_prefers_denormal_repr; 61 bool hex_float_uses_minimal_precision_when_not_specified; 62 bool hex_float_optimizes_leading_digit_bit_count; 63 }; 64 65 template <typename T, size_t N> 66 size_t ArraySize(T (&)[N]) { 67 return N; 68 } 69 70 template <typename T> 71 struct AlwaysFalse : std::false_type {}; 72 73 template <typename T> 74 std::string LengthModFor() { 75 static_assert(AlwaysFalse<T>::value, "Unsupported type"); 76 return ""; 77 } 78 template <> 79 std::string LengthModFor<char>() { 80 return "hh"; 81 } 82 template <> 83 std::string LengthModFor<signed char>() { 84 return "hh"; 85 } 86 template <> 87 std::string LengthModFor<unsigned char>() { 88 return "hh"; 89 } 90 template <> 91 std::string LengthModFor<short>() { // NOLINT 92 return "h"; 93 } 94 template <> 95 std::string LengthModFor<unsigned short>() { // NOLINT 96 return "h"; 97 } 98 template <> 99 std::string LengthModFor<int>() { 100 return ""; 101 } 102 template <> 103 std::string LengthModFor<unsigned>() { 104 return ""; 105 } 106 template <> 107 std::string LengthModFor<long>() { // NOLINT 108 return "l"; 109 } 110 template <> 111 std::string LengthModFor<unsigned long>() { // NOLINT 112 return "l"; 113 } 114 template <> 115 std::string LengthModFor<long long>() { // NOLINT 116 return "ll"; 117 } 118 template <> 119 std::string LengthModFor<unsigned long long>() { // NOLINT 120 return "ll"; 121 } 122 123 // An integral type of the same rank and signedness as `wchar_t`, that isn't 124 // `wchar_t`. 125 using IntegralTypeForWCharT = 126 std::conditional_t<std::is_signed<wchar_t>::value, 127 // Some STLs are broken and return `wchar_t` from 128 // `std::make_[un]signed_t<wchar_t>` when the signedness 129 // matches. Work around by round-tripping through the 130 // opposite signedness. 131 std::make_signed_t<std::make_unsigned_t<wchar_t>>, 132 std::make_unsigned_t<std::make_signed_t<wchar_t>>>; 133 134 // Given an integral type `T`, returns a type of the same rank and signedness 135 // that is guaranteed to not be `wchar_t`. 136 template <typename T> 137 using MatchingIntegralType = std::conditional_t<std::is_same<T, wchar_t>::value, 138 IntegralTypeForWCharT, T>; 139 140 std::string EscCharImpl(int v) { 141 char buf[64]; 142 int n = absl::ascii_isprint(static_cast<unsigned char>(v)) 143 ? snprintf(buf, sizeof(buf), "'%c'", v) 144 : snprintf(buf, sizeof(buf), "'\\x%.*x'", CHAR_BIT / 4, 145 static_cast<unsigned>( 146 static_cast<std::make_unsigned_t<char>>(v))); 147 assert(n > 0 && static_cast<size_t>(n) < sizeof(buf)); 148 return std::string(buf, static_cast<size_t>(n)); 149 } 150 151 std::string Esc(char v) { return EscCharImpl(v); } 152 std::string Esc(signed char v) { return EscCharImpl(v); } 153 std::string Esc(unsigned char v) { return EscCharImpl(v); } 154 155 std::string Esc(wchar_t v) { 156 char buf[64]; 157 int n = std::iswprint(static_cast<wint_t>(v)) 158 ? snprintf(buf, sizeof(buf), "L'%lc'", static_cast<wint_t>(v)) 159 : snprintf(buf, sizeof(buf), "L'\\x%.*llx'", 160 static_cast<int>(sizeof(wchar_t) * CHAR_BIT / 4), 161 static_cast<unsigned long long>( 162 static_cast<std::make_unsigned_t<wchar_t>>(v))); 163 assert(n > 0 && static_cast<size_t>(n) < sizeof(buf)); 164 return std::string(buf, static_cast<size_t>(n)); 165 } 166 167 template <typename T> 168 std::string Esc(const T &v) { 169 std::ostringstream oss; 170 oss << v; 171 return oss.str(); 172 } 173 174 void StrAppendV(std::string *dst, const char *format, va_list ap) { 175 // First try with a small fixed size buffer 176 static const int kSpaceLength = 1024; 177 char space[kSpaceLength]; 178 179 // It's possible for methods that use a va_list to invalidate 180 // the data in it upon use. The fix is to make a copy 181 // of the structure before using it and use that copy instead. 182 va_list backup_ap; 183 va_copy(backup_ap, ap); 184 int result = vsnprintf(space, kSpaceLength, format, backup_ap); 185 va_end(backup_ap); 186 if (result < kSpaceLength) { 187 if (result >= 0) { 188 // Normal case -- everything fit. 189 dst->append(space, static_cast<size_t>(result)); 190 return; 191 } 192 if (result < 0) { 193 // Just an error. 194 return; 195 } 196 } 197 198 // Increase the buffer size to the size requested by vsnprintf, 199 // plus one for the closing \0. 200 size_t length = static_cast<size_t>(result) + 1; 201 char *buf = new char[length]; 202 203 // Restore the va_list before we use it again 204 va_copy(backup_ap, ap); 205 result = vsnprintf(buf, length, format, backup_ap); 206 va_end(backup_ap); 207 208 if (result >= 0 && static_cast<size_t>(result) < length) { 209 // It fit 210 dst->append(buf, static_cast<size_t>(result)); 211 } 212 delete[] buf; 213 } 214 215 void StrAppend(std::string *, const char *, ...) ABSL_PRINTF_ATTRIBUTE(2, 3); 216 void StrAppend(std::string *out, const char *format, ...) { 217 va_list ap; 218 va_start(ap, format); 219 StrAppendV(out, format, ap); 220 va_end(ap); 221 } 222 223 std::string StrPrint(const char *, ...) ABSL_PRINTF_ATTRIBUTE(1, 2); 224 std::string StrPrint(const char *format, ...) { 225 va_list ap; 226 va_start(ap, format); 227 std::string result; 228 StrAppendV(&result, format, ap); 229 va_end(ap); 230 return result; 231 } 232 233 NativePrintfTraits VerifyNativeImplementationImpl() { 234 NativePrintfTraits result; 235 236 // >>> hex_float_has_glibc_rounding. To have glibc's rounding behavior we need 237 // to meet three requirements: 238 // 239 // - The threshold for rounding up is 8 (for e.g. MSVC uses 9). 240 // - If the digits lower than than the 8 are non-zero then we round up. 241 // - If the digits lower than the 8 are all zero then we round toward even. 242 // 243 // The numbers below represent all the cases covering {below,at,above} the 244 // threshold (8) with both {zero,non-zero} lower bits and both {even,odd} 245 // preceding digits. 246 const double d0079 = 65657.0; // 0x1.0079p+16 247 const double d0179 = 65913.0; // 0x1.0179p+16 248 const double d0080 = 65664.0; // 0x1.0080p+16 249 const double d0180 = 65920.0; // 0x1.0180p+16 250 const double d0081 = 65665.0; // 0x1.0081p+16 251 const double d0181 = 65921.0; // 0x1.0181p+16 252 result.hex_float_has_glibc_rounding = 253 StartsWith(StrPrint("%.2a", d0079), "0x1.00") && 254 StartsWith(StrPrint("%.2a", d0179), "0x1.01") && 255 StartsWith(StrPrint("%.2a", d0080), "0x1.00") && 256 StartsWith(StrPrint("%.2a", d0180), "0x1.02") && 257 StartsWith(StrPrint("%.2a", d0081), "0x1.01") && 258 StartsWith(StrPrint("%.2a", d0181), "0x1.02"); 259 260 // >>> hex_float_prefers_denormal_repr. Formatting `denormal` on glibc yields 261 // "0x0.0000000000001p-1022", whereas on std libs that don't use denormal 262 // representation it would either be 0x1p-1074 or 0x1.0000000000000-1074. 263 const double denormal = std::numeric_limits<double>::denorm_min(); 264 result.hex_float_prefers_denormal_repr = 265 StartsWith(StrPrint("%a", denormal), "0x0.0000000000001"); 266 267 // >>> hex_float_uses_minimal_precision_when_not_specified. Some (non-glibc) 268 // libs will format the following as "0x1.0079000000000p+16". 269 result.hex_float_uses_minimal_precision_when_not_specified = 270 (StrPrint("%a", d0079) == "0x1.0079p+16"); 271 272 // >>> hex_float_optimizes_leading_digit_bit_count. The number 1.5, when 273 // formatted by glibc should yield "0x1.8p+0" for `double` and "0xcp-3" for 274 // `long double`, i.e., number of bits in the leading digit is adapted to the 275 // number of bits in the mantissa. 276 const double d_15 = 1.5; 277 const long double ld_15 = 1.5; 278 result.hex_float_optimizes_leading_digit_bit_count = 279 StartsWith(StrPrint("%a", d_15), "0x1.8") && 280 StartsWith(StrPrint("%La", ld_15), "0xc"); 281 282 return result; 283 } 284 285 const NativePrintfTraits &VerifyNativeImplementation() { 286 static NativePrintfTraits native_traits = VerifyNativeImplementationImpl(); 287 return native_traits; 288 } 289 290 class FormatConvertTest : public ::testing::Test { }; 291 292 template <typename T> 293 void TestStringConvert(const T& str) { 294 const FormatArgImpl args[] = {FormatArgImpl(str)}; 295 struct Expectation { 296 const char *out; 297 const char *fmt; 298 }; 299 const Expectation kExpect[] = { 300 {"hello", "%1$s" }, 301 {"", "%1$.s" }, 302 {"", "%1$.0s" }, 303 {"h", "%1$.1s" }, 304 {"he", "%1$.2s" }, 305 {"hello", "%1$.10s" }, 306 {" hello", "%1$6s" }, 307 {" he", "%1$5.2s" }, 308 {"he ", "%1$-5.2s" }, 309 {"hello ", "%1$-6.10s" }, 310 }; 311 for (const Expectation &e : kExpect) { 312 UntypedFormatSpecImpl format(e.fmt); 313 EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))); 314 } 315 } 316 317 TEST_F(FormatConvertTest, BasicString) { 318 TestStringConvert("hello"); // As char array. 319 TestStringConvert(L"hello"); 320 TestStringConvert(static_cast<const char*>("hello")); 321 TestStringConvert(static_cast<const wchar_t*>(L"hello")); 322 TestStringConvert(std::string("hello")); 323 TestStringConvert(std::wstring(L"hello")); 324 TestStringConvert(string_view("hello")); 325 #if defined(ABSL_HAVE_STD_STRING_VIEW) 326 TestStringConvert(std::string_view("hello")); 327 TestStringConvert(std::wstring_view(L"hello")); 328 #endif // ABSL_HAVE_STD_STRING_VIEW 329 } 330 331 TEST_F(FormatConvertTest, NullString) { 332 const char* p = nullptr; 333 UntypedFormatSpecImpl format("%s"); 334 EXPECT_EQ("", FormatPack(format, {FormatArgImpl(p)})); 335 336 const wchar_t* wp = nullptr; 337 UntypedFormatSpecImpl wformat("%ls"); 338 EXPECT_EQ("", FormatPack(wformat, {FormatArgImpl(wp)})); 339 } 340 341 TEST_F(FormatConvertTest, StringPrecision) { 342 // We cap at the precision. 343 char c = 'a'; 344 const char* p = &c; 345 UntypedFormatSpecImpl format("%.1s"); 346 EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)})); 347 348 wchar_t wc = L'a'; 349 const wchar_t* wp = &wc; 350 UntypedFormatSpecImpl wformat("%.1ls"); 351 EXPECT_EQ("a", FormatPack(wformat, {FormatArgImpl(wp)})); 352 353 // We cap at the NUL-terminator. 354 p = "ABC"; 355 UntypedFormatSpecImpl format2("%.10s"); 356 EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)})); 357 358 wp = L"ABC"; 359 UntypedFormatSpecImpl wformat2("%.10ls"); 360 EXPECT_EQ("ABC", FormatPack(wformat2, {FormatArgImpl(wp)})); 361 } 362 363 // Pointer formatting is implementation defined. This checks that the argument 364 // can be matched to `ptr`. 365 MATCHER_P(MatchesPointerString, ptr, "") { 366 if (ptr == nullptr && arg == "(nil)") { 367 return true; 368 } 369 void* parsed = nullptr; 370 if (sscanf(arg.c_str(), "%p", &parsed) != 1) { 371 LOG(FATAL) << "Could not parse " << arg; 372 } 373 return ptr == parsed; 374 } 375 376 TEST_F(FormatConvertTest, Pointer) { 377 static int x = 0; 378 const int *xp = &x; 379 char c = 'h'; 380 char *mcp = &c; 381 const char *cp = "hi"; 382 const char *cnil = nullptr; 383 wchar_t wc = L'h'; 384 wchar_t *mwcp = &wc; 385 const wchar_t *wcp = L"hi"; 386 const wchar_t *wcnil = nullptr; 387 const int *inil = nullptr; 388 using VoidF = void (*)(); 389 VoidF fp = [] {}, fnil = nullptr; 390 volatile char vc; 391 volatile char *vcp = &vc; 392 volatile char *vcnil = nullptr; 393 volatile wchar_t vwc; 394 volatile wchar_t *vwcp = &vwc; 395 volatile wchar_t *vwcnil = nullptr; 396 const FormatArgImpl args_array[] = { 397 FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(wcp), 398 FormatArgImpl(inil), FormatArgImpl(cnil), FormatArgImpl(wcnil), 399 FormatArgImpl(mcp), FormatArgImpl(mwcp), FormatArgImpl(fp), 400 FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vwcp), 401 FormatArgImpl(vcnil), FormatArgImpl(vwcnil), 402 }; 403 auto args = absl::MakeConstSpan(args_array); 404 405 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%p"), args), 406 MatchesPointerString(&x)); 407 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%20p"), args), 408 MatchesPointerString(&x)); 409 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.1p"), args), 410 MatchesPointerString(&x)); 411 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args), 412 MatchesPointerString(&x)); 413 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%30.20p"), args), 414 MatchesPointerString(&x)); 415 416 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-p"), args), 417 MatchesPointerString(&x)); 418 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-20p"), args), 419 MatchesPointerString(&x)); 420 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-.1p"), args), 421 MatchesPointerString(&x)); 422 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args), 423 MatchesPointerString(&x)); 424 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-30.20p"), args), 425 MatchesPointerString(&x)); 426 427 // const int* 428 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%1$p"), args), 429 MatchesPointerString(xp)); 430 // const char* 431 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%2$p"), args), 432 MatchesPointerString(cp)); 433 // const wchar_t* 434 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%3$p"), args), 435 MatchesPointerString(wcp)); 436 // null const int* 437 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%4$p"), args), 438 MatchesPointerString(nullptr)); 439 // null const char* 440 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%5$p"), args), 441 MatchesPointerString(nullptr)); 442 // null const wchar_t* 443 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%6$p"), args), 444 MatchesPointerString(nullptr)); 445 // nonconst char* 446 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%7$p"), args), 447 MatchesPointerString(mcp)); 448 // nonconst wchar_t* 449 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%8$p"), args), 450 MatchesPointerString(mwcp)); 451 // function pointer 452 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%9$p"), args), 453 MatchesPointerString(reinterpret_cast<const void *>(fp))); 454 // null function pointer 455 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%10$p"), args), 456 MatchesPointerString(nullptr)); 457 // volatile char* 458 EXPECT_THAT( 459 FormatPack(UntypedFormatSpecImpl("%11$p"), args), 460 MatchesPointerString(reinterpret_cast<volatile const void *>(vcp))); 461 // volatile wchar_t* 462 EXPECT_THAT( 463 FormatPack(UntypedFormatSpecImpl("%12$p"), args), 464 MatchesPointerString(reinterpret_cast<volatile const void *>(vwcp))); 465 // null volatile char* 466 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%13$p"), args), 467 MatchesPointerString(nullptr)); 468 // null volatile wchar_t* 469 EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%14$p"), args), 470 MatchesPointerString(nullptr)); 471 } 472 473 struct Cardinal { 474 enum Pos { k1 = 1, k2 = 2, k3 = 3 }; 475 enum Neg { kM1 = -1, kM2 = -2, kM3 = -3 }; 476 }; 477 478 TEST_F(FormatConvertTest, Enum) { 479 const Cardinal::Pos k3 = Cardinal::k3; 480 const Cardinal::Neg km3 = Cardinal::kM3; 481 const FormatArgImpl args[] = {FormatArgImpl(k3), FormatArgImpl(km3)}; 482 UntypedFormatSpecImpl format("%1$d"); 483 UntypedFormatSpecImpl format2("%2$d"); 484 EXPECT_EQ("3", FormatPack(format, absl::MakeSpan(args))); 485 EXPECT_EQ("-3", FormatPack(format2, absl::MakeSpan(args))); 486 } 487 488 template <typename T> 489 class TypedFormatConvertTest : public FormatConvertTest { }; 490 491 TYPED_TEST_SUITE_P(TypedFormatConvertTest); 492 493 std::vector<std::string> AllFlagCombinations() { 494 const char kFlags[] = {'-', '#', '0', '+', ' '}; 495 std::vector<std::string> result; 496 for (size_t fsi = 0; fsi < (1ull << ArraySize(kFlags)); ++fsi) { 497 std::string flag_set; 498 for (size_t fi = 0; fi < ArraySize(kFlags); ++fi) 499 if (fsi & (1ull << fi)) 500 flag_set += kFlags[fi]; 501 result.push_back(flag_set); 502 } 503 return result; 504 } 505 506 TYPED_TEST_P(TypedFormatConvertTest, AllIntsWithFlags) { 507 typedef TypeParam T; 508 typedef typename std::make_unsigned<T>::type UnsignedT; 509 using remove_volatile_t = typename std::remove_volatile<T>::type; 510 const T kMin = std::numeric_limits<remove_volatile_t>::min(); 511 const T kMax = std::numeric_limits<remove_volatile_t>::max(); 512 const T kVals[] = { 513 remove_volatile_t(1), 514 remove_volatile_t(2), 515 remove_volatile_t(3), 516 remove_volatile_t(123), 517 remove_volatile_t(-1), 518 remove_volatile_t(-2), 519 remove_volatile_t(-3), 520 remove_volatile_t(-123), 521 remove_volatile_t(0), 522 kMax - remove_volatile_t(1), 523 kMax, 524 kMin + remove_volatile_t(1), 525 kMin, 526 }; 527 const char kConvChars[] = {'d', 'i', 'u', 'o', 'x', 'X'}; 528 const std::string kWid[] = {"", "4", "10"}; 529 const std::string kPrec[] = {"", ".", ".0", ".4", ".10"}; 530 531 const std::vector<std::string> flag_sets = AllFlagCombinations(); 532 533 for (size_t vi = 0; vi < ArraySize(kVals); ++vi) { 534 const T val = kVals[vi]; 535 SCOPED_TRACE(Esc(val)); 536 const FormatArgImpl args[] = {FormatArgImpl(val)}; 537 for (size_t ci = 0; ci < ArraySize(kConvChars); ++ci) { 538 const char conv_char = kConvChars[ci]; 539 for (size_t fsi = 0; fsi < flag_sets.size(); ++fsi) { 540 const std::string &flag_set = flag_sets[fsi]; 541 for (size_t wi = 0; wi < ArraySize(kWid); ++wi) { 542 const std::string &wid = kWid[wi]; 543 for (size_t pi = 0; pi < ArraySize(kPrec); ++pi) { 544 const std::string &prec = kPrec[pi]; 545 546 const bool is_signed_conv = (conv_char == 'd' || conv_char == 'i'); 547 const bool is_unsigned_to_signed = 548 !std::is_signed<T>::value && is_signed_conv; 549 // Don't consider sign-related flags '+' and ' ' when doing 550 // unsigned to signed conversions. 551 if (is_unsigned_to_signed && 552 flag_set.find_first_of("+ ") != std::string::npos) { 553 continue; 554 } 555 556 std::string new_fmt("%"); 557 new_fmt += flag_set; 558 new_fmt += wid; 559 new_fmt += prec; 560 // old and new always agree up to here. 561 std::string old_fmt = new_fmt; 562 new_fmt += conv_char; 563 std::string old_result; 564 if (is_unsigned_to_signed) { 565 // don't expect agreement on unsigned formatted as signed, 566 // as printf can't do that conversion properly. For those 567 // cases, we do expect agreement with printf with a "%u" 568 // and the unsigned equivalent of 'val'. 569 UnsignedT uval = 570 static_cast<std::remove_volatile_t<UnsignedT>>(val); 571 old_fmt += LengthModFor< 572 MatchingIntegralType<std::remove_cv_t<decltype(uval)>>>(); 573 old_fmt += "u"; 574 old_result = StrPrint(old_fmt.c_str(), uval); 575 } else { 576 old_fmt += LengthModFor< 577 MatchingIntegralType<std::remove_cv_t<decltype(val)>>>(); 578 old_fmt += conv_char; 579 old_result = StrPrint(old_fmt.c_str(), val); 580 } 581 582 SCOPED_TRACE(std::string() + " old_fmt: \"" + old_fmt + 583 "\"'" 584 " new_fmt: \"" + 585 new_fmt + "\""); 586 UntypedFormatSpecImpl format(new_fmt); 587 EXPECT_EQ(old_result, FormatPack(format, absl::MakeSpan(args))); 588 } 589 } 590 } 591 } 592 } 593 } 594 595 template <typename T> 596 absl::optional<std::string> StrPrintChar(T c) { 597 return StrPrint("%c", static_cast<int>(c)); 598 } 599 template <> 600 absl::optional<std::string> StrPrintChar(wchar_t c) { 601 // musl libc has a bug where ("%lc", 0) writes no characters, and Android 602 // doesn't support forcing UTF-8 via setlocale(). Hardcode the expected 603 // answers for ASCII inputs to maximize test coverage on these platforms. 604 if (static_cast<std::make_unsigned_t<wchar_t>>(c) < 0x80) { 605 return std::string(1, static_cast<char>(c)); 606 } 607 608 // Force a UTF-8 locale to match the expected `StrFormat()` behavior. 609 // It's important to copy the string returned by `old_locale` here, because 610 // its contents are not guaranteed to be valid after the next `setlocale()` 611 // call. 612 std::string old_locale = setlocale(LC_CTYPE, nullptr); 613 if (!setlocale(LC_CTYPE, "en_US.UTF-8")) { 614 return absl::nullopt; 615 } 616 const std::string output = StrPrint("%lc", static_cast<wint_t>(c)); 617 setlocale(LC_CTYPE, old_locale.c_str()); 618 return output; 619 } 620 621 template <typename T> 622 typename std::remove_volatile<T>::type GetMaxForConversion() { 623 return static_cast<typename std::remove_volatile<T>::type>( 624 std::numeric_limits<int>::max()); 625 } 626 627 template <> 628 wchar_t GetMaxForConversion<wchar_t>() { 629 // Don't return values that aren't legal Unicode. For wchar_t conversions in a 630 // UTF-8 locale, conversion behavior for such values is unspecified, and we 631 // don't care about matching it. 632 return (sizeof(wchar_t) * CHAR_BIT <= 16) ? wchar_t{0xffff} 633 : static_cast<wchar_t>(0x10ffff); 634 } 635 636 TYPED_TEST_P(TypedFormatConvertTest, Char) { 637 // Pass a bunch of values of type TypeParam to both FormatPack and libc's 638 // vsnprintf("%c", ...) (wrapped in StrPrint) to make sure we get the same 639 // value. 640 typedef TypeParam T; 641 using remove_volatile_t = typename std::remove_volatile<T>::type; 642 std::vector<remove_volatile_t> vals = { 643 remove_volatile_t(1), remove_volatile_t(2), remove_volatile_t(10), // 644 remove_volatile_t(-1), remove_volatile_t(-2), remove_volatile_t(-10), // 645 remove_volatile_t(0), 646 }; 647 648 // We'd like to test values near std::numeric_limits::min() and 649 // std::numeric_limits::max(), too, but vsnprintf("%c", ...) can't handle 650 // anything larger than an int. Add in the most extreme values we can without 651 // exceeding that range. 652 // Special case: Formatting a wchar_t should behave like vsnprintf("%lc"). 653 // Technically vsnprintf can accept a wint_t in this case, but since we must 654 // pass a wchar_t to FormatPack, the largest type we can use here is wchar_t. 655 using ArgType = 656 std::conditional_t<std::is_same<T, wchar_t>::value, wchar_t, int>; 657 static const T kMin = 658 static_cast<remove_volatile_t>(std::numeric_limits<ArgType>::min()); 659 static const T kMax = GetMaxForConversion<T>(); 660 vals.insert(vals.end(), {static_cast<remove_volatile_t>(kMin + 1), kMin, 661 static_cast<remove_volatile_t>(kMax - 1), kMax}); 662 663 static const auto kMaxWCharT = 664 static_cast<remove_volatile_t>(GetMaxForConversion<wchar_t>()); 665 for (const T c : vals) { 666 SCOPED_TRACE(Esc(c)); 667 const FormatArgImpl args[] = {FormatArgImpl(c)}; 668 UntypedFormatSpecImpl format("%c"); 669 absl::optional<std::string> result = StrPrintChar(c); 670 if (result.has_value()) { 671 EXPECT_EQ(result.value(), FormatPack(format, absl::MakeSpan(args))); 672 } 673 674 // Also test that if the format specifier is "%lc", the argument is treated 675 // as if it's a `wchar_t`. 676 const T wc = 677 std::max(remove_volatile_t{0}, 678 std::min(static_cast<remove_volatile_t>(c), kMaxWCharT)); 679 SCOPED_TRACE(Esc(wc)); 680 const FormatArgImpl wide_args[] = {FormatArgImpl(wc)}; 681 UntypedFormatSpecImpl wide_format("%lc"); 682 result = StrPrintChar(static_cast<wchar_t>(wc)); 683 if (result.has_value()) { 684 EXPECT_EQ(result.value(), 685 FormatPack(wide_format, absl::MakeSpan(wide_args))); 686 } 687 } 688 } 689 690 REGISTER_TYPED_TEST_SUITE_P(TypedFormatConvertTest, AllIntsWithFlags, Char); 691 692 typedef ::testing::Types<int, unsigned, volatile int, short, // NOLINT 693 unsigned short, long, unsigned long, // NOLINT 694 long long, unsigned long long, // NOLINT 695 signed char, unsigned char, char, wchar_t> 696 AllIntTypes; 697 INSTANTIATE_TYPED_TEST_SUITE_P(TypedFormatConvertTestWithAllIntTypes, 698 TypedFormatConvertTest, AllIntTypes); 699 TEST_F(FormatConvertTest, VectorBool) { 700 // Make sure vector<bool>'s values behave as bools. 701 std::vector<bool> v = {true, false}; 702 const std::vector<bool> cv = {true, false}; 703 EXPECT_EQ("1,0,1,0", 704 FormatPack(UntypedFormatSpecImpl("%d,%d,%d,%d"), 705 absl::Span<const FormatArgImpl>( 706 {FormatArgImpl(v[0]), FormatArgImpl(v[1]), 707 FormatArgImpl(cv[0]), FormatArgImpl(cv[1])}))); 708 } 709 710 TEST_F(FormatConvertTest, UnicodeWideString) { 711 // StrFormat() should be able to convert wide strings containing Unicode 712 // characters (to UTF-8). 713 const FormatArgImpl args[] = {FormatArgImpl(L"\u47e3 \U00011112")}; 714 // `u8""` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn) 715 // without it. However, the resulting character type differs between pre-C++20 716 // (`char`) and C++20 (`char8_t`). So deduce the right character type for all 717 // C++ versions, init it with UTF-8, then `memcpy()` to get the result as a 718 // `char*`. 719 using ConstChar8T = std::remove_reference_t<decltype(*u8"a")>; 720 ConstChar8T kOutputUtf8[] = u8"\u47e3 \U00011112"; 721 char output[sizeof kOutputUtf8]; 722 std::memcpy(output, kOutputUtf8, sizeof kOutputUtf8); 723 EXPECT_EQ(output, 724 FormatPack(UntypedFormatSpecImpl("%ls"), absl::MakeSpan(args))); 725 } 726 727 TEST_F(FormatConvertTest, Int128) { 728 absl::int128 positive = static_cast<absl::int128>(0x1234567890abcdef) * 1979; 729 absl::int128 negative = -positive; 730 absl::int128 max = absl::Int128Max(), min = absl::Int128Min(); 731 const FormatArgImpl args[] = {FormatArgImpl(positive), 732 FormatArgImpl(negative), FormatArgImpl(max), 733 FormatArgImpl(min)}; 734 735 struct Case { 736 const char* format; 737 const char* expected; 738 } cases[] = { 739 {"%1$d", "2595989796776606496405"}, 740 {"%1$30d", " 2595989796776606496405"}, 741 {"%1$-30d", "2595989796776606496405 "}, 742 {"%1$u", "2595989796776606496405"}, 743 {"%1$x", "8cba9876066020f695"}, 744 {"%2$d", "-2595989796776606496405"}, 745 {"%2$30d", " -2595989796776606496405"}, 746 {"%2$-30d", "-2595989796776606496405 "}, 747 {"%2$u", "340282366920938460867384810655161715051"}, 748 {"%2$x", "ffffffffffffff73456789f99fdf096b"}, 749 {"%3$d", "170141183460469231731687303715884105727"}, 750 {"%3$u", "170141183460469231731687303715884105727"}, 751 {"%3$x", "7fffffffffffffffffffffffffffffff"}, 752 {"%4$d", "-170141183460469231731687303715884105728"}, 753 {"%4$x", "80000000000000000000000000000000"}, 754 }; 755 756 for (auto c : cases) { 757 UntypedFormatSpecImpl format(c.format); 758 EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args))); 759 } 760 } 761 762 TEST_F(FormatConvertTest, Uint128) { 763 absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979; 764 absl::uint128 max = absl::Uint128Max(); 765 const FormatArgImpl args[] = {FormatArgImpl(v), FormatArgImpl(max)}; 766 767 struct Case { 768 const char* format; 769 const char* expected; 770 } cases[] = { 771 {"%1$d", "2595989796776606496405"}, 772 {"%1$30d", " 2595989796776606496405"}, 773 {"%1$-30d", "2595989796776606496405 "}, 774 {"%1$u", "2595989796776606496405"}, 775 {"%1$x", "8cba9876066020f695"}, 776 {"%2$d", "340282366920938463463374607431768211455"}, 777 {"%2$u", "340282366920938463463374607431768211455"}, 778 {"%2$x", "ffffffffffffffffffffffffffffffff"}, 779 }; 780 781 for (auto c : cases) { 782 UntypedFormatSpecImpl format(c.format); 783 EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args))); 784 } 785 } 786 787 template <typename Floating> 788 void TestWithMultipleFormatsHelper(Floating tested_float) { 789 const NativePrintfTraits &native_traits = VerifyNativeImplementation(); 790 // Reserve the space to ensure we don't allocate memory in the output itself. 791 std::string str_format_result; 792 str_format_result.reserve(1 << 20); 793 std::string string_printf_result; 794 string_printf_result.reserve(1 << 20); 795 796 const char *const kFormats[] = { 797 "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03", 798 "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; 799 800 for (const char *fmt : kFormats) { 801 for (char f : {'f', 'F', // 802 'g', 'G', // 803 'a', 'A', // 804 'e', 'E'}) { 805 std::string fmt_str = std::string(fmt) + f; 806 807 if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' && 808 f != 'a' && f != 'A') { 809 // This particular test takes way too long with snprintf. 810 // Disable for the case we are not implementing natively. 811 continue; 812 } 813 814 if ((f == 'a' || f == 'A') && 815 !native_traits.hex_float_has_glibc_rounding) { 816 continue; 817 } 818 819 if (!native_traits.hex_float_prefers_denormal_repr && 820 (f == 'a' || f == 'A') && 821 std::fpclassify(tested_float) == FP_SUBNORMAL) { 822 continue; 823 } 824 int i = -10; 825 FormatArgImpl args[2] = {FormatArgImpl(tested_float), FormatArgImpl(i)}; 826 UntypedFormatSpecImpl format(fmt_str); 827 828 string_printf_result.clear(); 829 StrAppend(&string_printf_result, fmt_str.c_str(), tested_float, i); 830 str_format_result.clear(); 831 832 { 833 AppendPack(&str_format_result, format, absl::MakeSpan(args)); 834 } 835 836 // For values that we know won't match the standard library 837 // implementation we skip verification, but still run the algorithm to 838 // catch asserts/sanitizer bugs. 839 #ifdef _MSC_VER 840 // MSVC has a different rounding policy than us so we can't test our 841 // implementation against the native one there. 842 continue; 843 #elif defined(__APPLE__) 844 // Apple formats NaN differently (+nan) vs. (nan) 845 if (std::isnan(tested_float)) continue; 846 #endif 847 // We use ASSERT_EQ here because failures are usually correlated and a 848 // bug would print way too many failed expectations causing the test 849 // to time out. 850 ASSERT_EQ(string_printf_result, str_format_result) 851 << fmt_str << " " << StrPrint("%.18g", tested_float) << " " 852 << StrPrint("%a", tested_float) << " " 853 << StrPrint("%.50f", tested_float); 854 } 855 } 856 } 857 858 TEST_F(FormatConvertTest, Float) { 859 std::vector<float> floats = {0.0f, 860 -0.0f, 861 .9999999f, 862 9999999.f, 863 std::numeric_limits<float>::max(), 864 -std::numeric_limits<float>::max(), 865 std::numeric_limits<float>::min(), 866 -std::numeric_limits<float>::min(), 867 std::numeric_limits<float>::lowest(), 868 -std::numeric_limits<float>::lowest(), 869 std::numeric_limits<float>::epsilon(), 870 std::numeric_limits<float>::epsilon() + 1.0f, 871 std::numeric_limits<float>::infinity(), 872 -std::numeric_limits<float>::infinity(), 873 std::nanf("")}; 874 875 // Some regression tests. 876 floats.push_back(0.999999989f); 877 878 if (std::numeric_limits<float>::has_denorm != std::denorm_absent) { 879 floats.push_back(std::numeric_limits<float>::denorm_min()); 880 floats.push_back(-std::numeric_limits<float>::denorm_min()); 881 } 882 883 for (float base : 884 {1.f, 12.f, 123.f, 1234.f, 12345.f, 123456.f, 1234567.f, 12345678.f, 885 123456789.f, 1234567890.f, 12345678901.f, 12345678.f, 12345678.f}) { 886 for (int exp = -123; exp <= 123; ++exp) { 887 for (int sign : {1, -1}) { 888 floats.push_back(sign * std::ldexp(base, exp)); 889 } 890 } 891 } 892 893 for (int exp = -300; exp <= 300; ++exp) { 894 const float all_ones_mantissa = 0xffffff; 895 floats.push_back(std::ldexp(all_ones_mantissa, exp)); 896 } 897 898 // Remove duplicates to speed up the logic below. 899 std::sort(floats.begin(), floats.end(), [](const float a, const float b) { 900 if (std::isnan(a)) return false; 901 if (std::isnan(b)) return true; 902 return a < b; 903 }); 904 floats.erase(std::unique(floats.begin(), floats.end()), floats.end()); 905 906 for (float f : floats) { 907 TestWithMultipleFormatsHelper(f); 908 } 909 } 910 911 TEST_F(FormatConvertTest, Double) { 912 std::vector<double> doubles = {0.0, 913 -0.0, 914 .99999999999999, 915 99999999999999., 916 std::numeric_limits<double>::max(), 917 -std::numeric_limits<double>::max(), 918 std::numeric_limits<double>::min(), 919 -std::numeric_limits<double>::min(), 920 std::numeric_limits<double>::lowest(), 921 -std::numeric_limits<double>::lowest(), 922 std::numeric_limits<double>::epsilon(), 923 std::numeric_limits<double>::epsilon() + 1, 924 std::numeric_limits<double>::infinity(), 925 -std::numeric_limits<double>::infinity(), 926 std::nan("")}; 927 928 // Some regression tests. 929 doubles.push_back(0.99999999999999989); 930 931 if (std::numeric_limits<double>::has_denorm != std::denorm_absent) { 932 doubles.push_back(std::numeric_limits<double>::denorm_min()); 933 doubles.push_back(-std::numeric_limits<double>::denorm_min()); 934 } 935 936 for (double base : 937 {1., 12., 123., 1234., 12345., 123456., 1234567., 12345678., 123456789., 938 1234567890., 12345678901., 123456789012., 1234567890123.}) { 939 for (int exp = -123; exp <= 123; ++exp) { 940 for (int sign : {1, -1}) { 941 doubles.push_back(sign * std::ldexp(base, exp)); 942 } 943 } 944 } 945 946 for (int exp = -300; exp <= 300; ++exp) { 947 const double all_ones_mantissa = 0x1fffffffffffff; 948 doubles.push_back(std::ldexp(all_ones_mantissa, exp)); 949 } 950 951 // Remove duplicates to speed up the logic below. 952 std::sort(doubles.begin(), doubles.end(), [](const double a, const double b) { 953 if (std::isnan(a)) return false; 954 if (std::isnan(b)) return true; 955 return a < b; 956 }); 957 doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end()); 958 959 for (double d : doubles) { 960 TestWithMultipleFormatsHelper(d); 961 } 962 } 963 964 TEST_F(FormatConvertTest, DoubleRound) { 965 std::string s; 966 const auto format = [&](const char *fmt, double d) -> std::string & { 967 s.clear(); 968 FormatArgImpl args[1] = {FormatArgImpl(d)}; 969 AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); 970 #if !defined(_MSC_VER) 971 // MSVC has a different rounding policy than us so we can't test our 972 // implementation against the native one there. 973 EXPECT_EQ(StrPrint(fmt, d), s); 974 #endif // _MSC_VER 975 976 return s; 977 }; 978 // All of these values have to be exactly represented. 979 // Otherwise we might not be testing what we think we are testing. 980 981 // These values can fit in a 64bit "fast" representation. 982 const double exact_value = 0.00000000000005684341886080801486968994140625; 983 assert(exact_value == std::pow(2, -44)); 984 // Round up at a 5xx. 985 EXPECT_EQ(format("%.13f", exact_value), "0.0000000000001"); 986 // Round up at a >5 987 EXPECT_EQ(format("%.14f", exact_value), "0.00000000000006"); 988 // Round down at a <5 989 EXPECT_EQ(format("%.16f", exact_value), "0.0000000000000568"); 990 // Nine handling 991 EXPECT_EQ(format("%.35f", exact_value), 992 "0.00000000000005684341886080801486969"); 993 EXPECT_EQ(format("%.36f", exact_value), 994 "0.000000000000056843418860808014869690"); 995 // Round down the last nine. 996 EXPECT_EQ(format("%.37f", exact_value), 997 "0.0000000000000568434188608080148696899"); 998 EXPECT_EQ(format("%.10f", 0.000003814697265625), "0.0000038147"); 999 // Round up the last nine 1000 EXPECT_EQ(format("%.11f", 0.000003814697265625), "0.00000381470"); 1001 EXPECT_EQ(format("%.12f", 0.000003814697265625), "0.000003814697"); 1002 1003 // Round to even (down) 1004 EXPECT_EQ(format("%.43f", exact_value), 1005 "0.0000000000000568434188608080148696899414062"); 1006 // Exact 1007 EXPECT_EQ(format("%.44f", exact_value), 1008 "0.00000000000005684341886080801486968994140625"); 1009 // Round to even (up), let make the last digits 75 instead of 25 1010 EXPECT_EQ(format("%.43f", exact_value + std::pow(2, -43)), 1011 "0.0000000000001705302565824240446090698242188"); 1012 // Exact, just to check. 1013 EXPECT_EQ(format("%.44f", exact_value + std::pow(2, -43)), 1014 "0.00000000000017053025658242404460906982421875"); 1015 1016 // This value has to be small enough that it won't fit in the uint128 1017 // representation for printing. 1018 const double small_exact_value = 1019 0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625; // NOLINT 1020 assert(small_exact_value == std::pow(2, -120)); 1021 // Round up at a 5xx. 1022 EXPECT_EQ(format("%.37f", small_exact_value), 1023 "0.0000000000000000000000000000000000008"); 1024 // Round down at a <5 1025 EXPECT_EQ(format("%.38f", small_exact_value), 1026 "0.00000000000000000000000000000000000075"); 1027 // Round up at a >5 1028 EXPECT_EQ(format("%.41f", small_exact_value), 1029 "0.00000000000000000000000000000000000075232"); 1030 // Nine handling 1031 EXPECT_EQ(format("%.55f", small_exact_value), 1032 "0.0000000000000000000000000000000000007523163845262640051"); 1033 EXPECT_EQ(format("%.56f", small_exact_value), 1034 "0.00000000000000000000000000000000000075231638452626400510"); 1035 EXPECT_EQ(format("%.57f", small_exact_value), 1036 "0.000000000000000000000000000000000000752316384526264005100"); 1037 EXPECT_EQ(format("%.58f", small_exact_value), 1038 "0.0000000000000000000000000000000000007523163845262640051000"); 1039 // Round down the last nine 1040 EXPECT_EQ(format("%.59f", small_exact_value), 1041 "0.00000000000000000000000000000000000075231638452626400509999"); 1042 // Round up the last nine 1043 EXPECT_EQ(format("%.79f", small_exact_value), 1044 "0.000000000000000000000000000000000000" 1045 "7523163845262640050999913838222372338039460"); 1046 1047 // Round to even (down) 1048 EXPECT_EQ(format("%.119f", small_exact_value), 1049 "0.000000000000000000000000000000000000" 1050 "75231638452626400509999138382223723380" 1051 "394595633413601376560109201818704605102539062"); 1052 // Exact 1053 EXPECT_EQ(format("%.120f", small_exact_value), 1054 "0.000000000000000000000000000000000000" 1055 "75231638452626400509999138382223723380" 1056 "3945956334136013765601092018187046051025390625"); 1057 // Round to even (up), let make the last digits 75 instead of 25 1058 EXPECT_EQ(format("%.119f", small_exact_value + std::pow(2, -119)), 1059 "0.000000000000000000000000000000000002" 1060 "25694915357879201529997415146671170141" 1061 "183786900240804129680327605456113815307617188"); 1062 // Exact, just to check. 1063 EXPECT_EQ(format("%.120f", small_exact_value + std::pow(2, -119)), 1064 "0.000000000000000000000000000000000002" 1065 "25694915357879201529997415146671170141" 1066 "1837869002408041296803276054561138153076171875"); 1067 } 1068 1069 TEST_F(FormatConvertTest, DoubleRoundA) { 1070 const NativePrintfTraits &native_traits = VerifyNativeImplementation(); 1071 std::string s; 1072 const auto format = [&](const char *fmt, double d) -> std::string & { 1073 s.clear(); 1074 FormatArgImpl args[1] = {FormatArgImpl(d)}; 1075 AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); 1076 if (native_traits.hex_float_has_glibc_rounding) { 1077 EXPECT_EQ(StrPrint(fmt, d), s); 1078 } 1079 return s; 1080 }; 1081 1082 // 0x1.00018000p+100 1083 const double on_boundary_odd = 1267679614447900152596896153600.0; 1084 EXPECT_EQ(format("%.0a", on_boundary_odd), "0x1p+100"); 1085 EXPECT_EQ(format("%.1a", on_boundary_odd), "0x1.0p+100"); 1086 EXPECT_EQ(format("%.2a", on_boundary_odd), "0x1.00p+100"); 1087 EXPECT_EQ(format("%.3a", on_boundary_odd), "0x1.000p+100"); 1088 EXPECT_EQ(format("%.4a", on_boundary_odd), "0x1.0002p+100"); // round 1089 EXPECT_EQ(format("%.5a", on_boundary_odd), "0x1.00018p+100"); 1090 EXPECT_EQ(format("%.6a", on_boundary_odd), "0x1.000180p+100"); 1091 1092 // 0x1.00028000p-2 1093 const double on_boundary_even = 0.250009536743164062500; 1094 EXPECT_EQ(format("%.0a", on_boundary_even), "0x1p-2"); 1095 EXPECT_EQ(format("%.1a", on_boundary_even), "0x1.0p-2"); 1096 EXPECT_EQ(format("%.2a", on_boundary_even), "0x1.00p-2"); 1097 EXPECT_EQ(format("%.3a", on_boundary_even), "0x1.000p-2"); 1098 EXPECT_EQ(format("%.4a", on_boundary_even), "0x1.0002p-2"); // no round 1099 EXPECT_EQ(format("%.5a", on_boundary_even), "0x1.00028p-2"); 1100 EXPECT_EQ(format("%.6a", on_boundary_even), "0x1.000280p-2"); 1101 1102 // 0x1.00018001p+1 1103 const double slightly_over = 2.00004577683284878730773925781250; 1104 EXPECT_EQ(format("%.0a", slightly_over), "0x1p+1"); 1105 EXPECT_EQ(format("%.1a", slightly_over), "0x1.0p+1"); 1106 EXPECT_EQ(format("%.2a", slightly_over), "0x1.00p+1"); 1107 EXPECT_EQ(format("%.3a", slightly_over), "0x1.000p+1"); 1108 EXPECT_EQ(format("%.4a", slightly_over), "0x1.0002p+1"); 1109 EXPECT_EQ(format("%.5a", slightly_over), "0x1.00018p+1"); 1110 EXPECT_EQ(format("%.6a", slightly_over), "0x1.000180p+1"); 1111 1112 // 0x1.00017fffp+0 1113 const double slightly_under = 1.000022887950763106346130371093750; 1114 EXPECT_EQ(format("%.0a", slightly_under), "0x1p+0"); 1115 EXPECT_EQ(format("%.1a", slightly_under), "0x1.0p+0"); 1116 EXPECT_EQ(format("%.2a", slightly_under), "0x1.00p+0"); 1117 EXPECT_EQ(format("%.3a", slightly_under), "0x1.000p+0"); 1118 EXPECT_EQ(format("%.4a", slightly_under), "0x1.0001p+0"); 1119 EXPECT_EQ(format("%.5a", slightly_under), "0x1.00018p+0"); 1120 EXPECT_EQ(format("%.6a", slightly_under), "0x1.000180p+0"); 1121 EXPECT_EQ(format("%.7a", slightly_under), "0x1.0001800p+0"); 1122 1123 // 0x1.1b3829ac28058p+3 1124 const double hex_value = 8.85060580848964661981881363317370414733886718750; 1125 EXPECT_EQ(format("%.0a", hex_value), "0x1p+3"); 1126 EXPECT_EQ(format("%.1a", hex_value), "0x1.2p+3"); 1127 EXPECT_EQ(format("%.2a", hex_value), "0x1.1bp+3"); 1128 EXPECT_EQ(format("%.3a", hex_value), "0x1.1b4p+3"); 1129 EXPECT_EQ(format("%.4a", hex_value), "0x1.1b38p+3"); 1130 EXPECT_EQ(format("%.5a", hex_value), "0x1.1b383p+3"); 1131 EXPECT_EQ(format("%.6a", hex_value), "0x1.1b382ap+3"); 1132 EXPECT_EQ(format("%.7a", hex_value), "0x1.1b3829bp+3"); 1133 EXPECT_EQ(format("%.8a", hex_value), "0x1.1b3829acp+3"); 1134 EXPECT_EQ(format("%.9a", hex_value), "0x1.1b3829ac3p+3"); 1135 EXPECT_EQ(format("%.10a", hex_value), "0x1.1b3829ac28p+3"); 1136 EXPECT_EQ(format("%.11a", hex_value), "0x1.1b3829ac280p+3"); 1137 EXPECT_EQ(format("%.12a", hex_value), "0x1.1b3829ac2806p+3"); 1138 EXPECT_EQ(format("%.13a", hex_value), "0x1.1b3829ac28058p+3"); 1139 EXPECT_EQ(format("%.14a", hex_value), "0x1.1b3829ac280580p+3"); 1140 EXPECT_EQ(format("%.15a", hex_value), "0x1.1b3829ac2805800p+3"); 1141 EXPECT_EQ(format("%.16a", hex_value), "0x1.1b3829ac28058000p+3"); 1142 EXPECT_EQ(format("%.17a", hex_value), "0x1.1b3829ac280580000p+3"); 1143 EXPECT_EQ(format("%.18a", hex_value), "0x1.1b3829ac2805800000p+3"); 1144 EXPECT_EQ(format("%.19a", hex_value), "0x1.1b3829ac28058000000p+3"); 1145 EXPECT_EQ(format("%.20a", hex_value), "0x1.1b3829ac280580000000p+3"); 1146 EXPECT_EQ(format("%.21a", hex_value), "0x1.1b3829ac2805800000000p+3"); 1147 1148 // 0x1.0818283848586p+3 1149 const double hex_value2 = 8.2529488658208371987257123691961169242858886718750; 1150 EXPECT_EQ(format("%.0a", hex_value2), "0x1p+3"); 1151 EXPECT_EQ(format("%.1a", hex_value2), "0x1.1p+3"); 1152 EXPECT_EQ(format("%.2a", hex_value2), "0x1.08p+3"); 1153 EXPECT_EQ(format("%.3a", hex_value2), "0x1.082p+3"); 1154 EXPECT_EQ(format("%.4a", hex_value2), "0x1.0818p+3"); 1155 EXPECT_EQ(format("%.5a", hex_value2), "0x1.08183p+3"); 1156 EXPECT_EQ(format("%.6a", hex_value2), "0x1.081828p+3"); 1157 EXPECT_EQ(format("%.7a", hex_value2), "0x1.0818284p+3"); 1158 EXPECT_EQ(format("%.8a", hex_value2), "0x1.08182838p+3"); 1159 EXPECT_EQ(format("%.9a", hex_value2), "0x1.081828385p+3"); 1160 EXPECT_EQ(format("%.10a", hex_value2), "0x1.0818283848p+3"); 1161 EXPECT_EQ(format("%.11a", hex_value2), "0x1.08182838486p+3"); 1162 EXPECT_EQ(format("%.12a", hex_value2), "0x1.081828384858p+3"); 1163 EXPECT_EQ(format("%.13a", hex_value2), "0x1.0818283848586p+3"); 1164 EXPECT_EQ(format("%.14a", hex_value2), "0x1.08182838485860p+3"); 1165 EXPECT_EQ(format("%.15a", hex_value2), "0x1.081828384858600p+3"); 1166 EXPECT_EQ(format("%.16a", hex_value2), "0x1.0818283848586000p+3"); 1167 EXPECT_EQ(format("%.17a", hex_value2), "0x1.08182838485860000p+3"); 1168 EXPECT_EQ(format("%.18a", hex_value2), "0x1.081828384858600000p+3"); 1169 EXPECT_EQ(format("%.19a", hex_value2), "0x1.0818283848586000000p+3"); 1170 EXPECT_EQ(format("%.20a", hex_value2), "0x1.08182838485860000000p+3"); 1171 EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3"); 1172 } 1173 1174 TEST_F(FormatConvertTest, LongDoubleRoundA) { 1175 if (std::numeric_limits<long double>::digits % 4 != 0) { 1176 // This test doesn't really make sense to run on platforms where a long 1177 // double has a different mantissa size (mod 4) than Prod, since then the 1178 // leading digit will be formatted differently. 1179 return; 1180 } 1181 const NativePrintfTraits &native_traits = VerifyNativeImplementation(); 1182 std::string s; 1183 const auto format = [&](const char *fmt, long double d) -> std::string & { 1184 s.clear(); 1185 FormatArgImpl args[1] = {FormatArgImpl(d)}; 1186 AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); 1187 if (native_traits.hex_float_has_glibc_rounding && 1188 native_traits.hex_float_optimizes_leading_digit_bit_count) { 1189 EXPECT_EQ(StrPrint(fmt, d), s); 1190 } 1191 return s; 1192 }; 1193 1194 // 0x8.8p+4 1195 const long double on_boundary_even = 136.0; 1196 EXPECT_EQ(format("%.0La", on_boundary_even), "0x8p+4"); 1197 EXPECT_EQ(format("%.1La", on_boundary_even), "0x8.8p+4"); 1198 EXPECT_EQ(format("%.2La", on_boundary_even), "0x8.80p+4"); 1199 EXPECT_EQ(format("%.3La", on_boundary_even), "0x8.800p+4"); 1200 EXPECT_EQ(format("%.4La", on_boundary_even), "0x8.8000p+4"); 1201 EXPECT_EQ(format("%.5La", on_boundary_even), "0x8.80000p+4"); 1202 EXPECT_EQ(format("%.6La", on_boundary_even), "0x8.800000p+4"); 1203 1204 // 0x9.8p+4 1205 const long double on_boundary_odd = 152.0; 1206 EXPECT_EQ(format("%.0La", on_boundary_odd), "0xap+4"); 1207 EXPECT_EQ(format("%.1La", on_boundary_odd), "0x9.8p+4"); 1208 EXPECT_EQ(format("%.2La", on_boundary_odd), "0x9.80p+4"); 1209 EXPECT_EQ(format("%.3La", on_boundary_odd), "0x9.800p+4"); 1210 EXPECT_EQ(format("%.4La", on_boundary_odd), "0x9.8000p+4"); 1211 EXPECT_EQ(format("%.5La", on_boundary_odd), "0x9.80000p+4"); 1212 EXPECT_EQ(format("%.6La", on_boundary_odd), "0x9.800000p+4"); 1213 1214 // 0x8.80001p+24 1215 const long double slightly_over = 142606352.0; 1216 EXPECT_EQ(format("%.0La", slightly_over), "0x9p+24"); 1217 EXPECT_EQ(format("%.1La", slightly_over), "0x8.8p+24"); 1218 EXPECT_EQ(format("%.2La", slightly_over), "0x8.80p+24"); 1219 EXPECT_EQ(format("%.3La", slightly_over), "0x8.800p+24"); 1220 EXPECT_EQ(format("%.4La", slightly_over), "0x8.8000p+24"); 1221 EXPECT_EQ(format("%.5La", slightly_over), "0x8.80001p+24"); 1222 EXPECT_EQ(format("%.6La", slightly_over), "0x8.800010p+24"); 1223 1224 // 0x8.7ffffp+24 1225 const long double slightly_under = 142606320.0; 1226 EXPECT_EQ(format("%.0La", slightly_under), "0x8p+24"); 1227 EXPECT_EQ(format("%.1La", slightly_under), "0x8.8p+24"); 1228 EXPECT_EQ(format("%.2La", slightly_under), "0x8.80p+24"); 1229 EXPECT_EQ(format("%.3La", slightly_under), "0x8.800p+24"); 1230 EXPECT_EQ(format("%.4La", slightly_under), "0x8.8000p+24"); 1231 EXPECT_EQ(format("%.5La", slightly_under), "0x8.7ffffp+24"); 1232 EXPECT_EQ(format("%.6La", slightly_under), "0x8.7ffff0p+24"); 1233 EXPECT_EQ(format("%.7La", slightly_under), "0x8.7ffff00p+24"); 1234 1235 // 0xc.0828384858688000p+128 1236 const long double eights = 4094231060438608800781871108094404067328.0; 1237 EXPECT_EQ(format("%.0La", eights), "0xcp+128"); 1238 EXPECT_EQ(format("%.1La", eights), "0xc.1p+128"); 1239 EXPECT_EQ(format("%.2La", eights), "0xc.08p+128"); 1240 EXPECT_EQ(format("%.3La", eights), "0xc.083p+128"); 1241 EXPECT_EQ(format("%.4La", eights), "0xc.0828p+128"); 1242 EXPECT_EQ(format("%.5La", eights), "0xc.08284p+128"); 1243 EXPECT_EQ(format("%.6La", eights), "0xc.082838p+128"); 1244 EXPECT_EQ(format("%.7La", eights), "0xc.0828385p+128"); 1245 EXPECT_EQ(format("%.8La", eights), "0xc.08283848p+128"); 1246 EXPECT_EQ(format("%.9La", eights), "0xc.082838486p+128"); 1247 EXPECT_EQ(format("%.10La", eights), "0xc.0828384858p+128"); 1248 EXPECT_EQ(format("%.11La", eights), "0xc.08283848587p+128"); 1249 EXPECT_EQ(format("%.12La", eights), "0xc.082838485868p+128"); 1250 EXPECT_EQ(format("%.13La", eights), "0xc.0828384858688p+128"); 1251 EXPECT_EQ(format("%.14La", eights), "0xc.08283848586880p+128"); 1252 EXPECT_EQ(format("%.15La", eights), "0xc.082838485868800p+128"); 1253 EXPECT_EQ(format("%.16La", eights), "0xc.0828384858688000p+128"); 1254 } 1255 1256 // We don't actually store the results. This is just to exercise the rest of the 1257 // machinery. 1258 struct NullSink { 1259 friend void AbslFormatFlush(NullSink *, string_view) {} 1260 }; 1261 1262 template <typename... T> 1263 bool FormatWithNullSink(absl::string_view fmt, const T &... a) { 1264 NullSink sink; 1265 FormatArgImpl args[] = {FormatArgImpl(a)...}; 1266 return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); 1267 } 1268 1269 TEST_F(FormatConvertTest, ExtremeWidthPrecision) { 1270 for (const char *fmt : {"f"}) { 1271 for (double d : {1e-100, 1.0, 1e100}) { 1272 constexpr int max = std::numeric_limits<int>::max(); 1273 EXPECT_TRUE(FormatWithNullSink(std::string("%.*") + fmt, max, d)); 1274 EXPECT_TRUE(FormatWithNullSink(std::string("%1.*") + fmt, max, d)); 1275 EXPECT_TRUE(FormatWithNullSink(std::string("%*") + fmt, max, d)); 1276 EXPECT_TRUE(FormatWithNullSink(std::string("%*.*") + fmt, max, max, d)); 1277 } 1278 } 1279 } 1280 1281 TEST_F(FormatConvertTest, LongDouble) { 1282 const NativePrintfTraits &native_traits = VerifyNativeImplementation(); 1283 const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", 1284 "%.60", "%+", "% ", "%-10"}; 1285 1286 std::vector<long double> doubles = { 1287 0.0, 1288 -0.0, 1289 std::numeric_limits<long double>::max(), 1290 -std::numeric_limits<long double>::max(), 1291 std::numeric_limits<long double>::min(), 1292 -std::numeric_limits<long double>::min(), 1293 std::numeric_limits<long double>::infinity(), 1294 -std::numeric_limits<long double>::infinity()}; 1295 1296 for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L, 1297 1234567.L, 12345678.L, 123456789.L, 1234567890.L, 1298 12345678901.L, 123456789012.L, 1234567890123.L, 1299 // This value is not representable in double, but it 1300 // is in long double that uses the extended format. 1301 // This is to verify that we are not truncating the 1302 // value mistakenly through a double. 1303 10000000000000000.25L}) { 1304 for (int exp : {-1000, -500, 0, 500, 1000}) { 1305 for (int sign : {1, -1}) { 1306 doubles.push_back(sign * std::ldexp(base, exp)); 1307 doubles.push_back(sign / std::ldexp(base, exp)); 1308 } 1309 } 1310 } 1311 1312 // Regression tests 1313 // 1314 // Using a string literal because not all platforms support hex literals or it 1315 // might be out of range. 1316 doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr)); 1317 1318 for (const char *fmt : kFormats) { 1319 for (char f : {'f', 'F', // 1320 'g', 'G', // 1321 'a', 'A', // 1322 'e', 'E'}) { 1323 std::string fmt_str = std::string(fmt) + 'L' + f; 1324 1325 if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' && 1326 f != 'a' && f != 'A') { 1327 // This particular test takes way too long with snprintf. 1328 // Disable for the case we are not implementing natively. 1329 continue; 1330 } 1331 1332 if (f == 'a' || f == 'A') { 1333 if (!native_traits.hex_float_has_glibc_rounding || 1334 !native_traits.hex_float_optimizes_leading_digit_bit_count) { 1335 continue; 1336 } 1337 } 1338 1339 for (auto d : doubles) { 1340 FormatArgImpl arg(d); 1341 UntypedFormatSpecImpl format(fmt_str); 1342 std::string result = FormatPack(format, {&arg, 1}); 1343 1344 #ifdef _MSC_VER 1345 // MSVC has a different rounding policy than us so we can't test our 1346 // implementation against the native one there. 1347 continue; 1348 #endif // _MSC_VER 1349 1350 // We use ASSERT_EQ here because failures are usually correlated and a 1351 // bug would print way too many failed expectations causing the test to 1352 // time out. 1353 ASSERT_EQ(StrPrint(fmt_str.c_str(), d), result) 1354 << fmt_str << " " << StrPrint("%.18Lg", d) << " " 1355 << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); 1356 } 1357 } 1358 } 1359 } 1360 1361 TEST_F(FormatConvertTest, IntAsDouble) { 1362 const NativePrintfTraits &native_traits = VerifyNativeImplementation(); 1363 const int kMin = std::numeric_limits<int>::min(); 1364 const int kMax = std::numeric_limits<int>::max(); 1365 const int ia[] = { 1366 1, 2, 3, 123, 1367 -1, -2, -3, -123, 1368 0, kMax - 1, kMax, kMin + 1, kMin }; 1369 for (const int fx : ia) { 1370 SCOPED_TRACE(fx); 1371 const FormatArgImpl args[] = {FormatArgImpl(fx)}; 1372 struct Expectation { 1373 int line; 1374 std::string out; 1375 const char *fmt; 1376 }; 1377 const double dx = static_cast<double>(fx); 1378 std::vector<Expectation> expect = { 1379 {__LINE__, StrPrint("%f", dx), "%f"}, 1380 {__LINE__, StrPrint("%12f", dx), "%12f"}, 1381 {__LINE__, StrPrint("%.12f", dx), "%.12f"}, 1382 {__LINE__, StrPrint("%.12a", dx), "%.12a"}, 1383 }; 1384 if (native_traits.hex_float_uses_minimal_precision_when_not_specified) { 1385 Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"}; 1386 expect.push_back(ex); 1387 } 1388 for (const Expectation &e : expect) { 1389 SCOPED_TRACE(e.line); 1390 SCOPED_TRACE(e.fmt); 1391 UntypedFormatSpecImpl format(e.fmt); 1392 EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))); 1393 } 1394 } 1395 } 1396 1397 template <typename T> 1398 bool FormatFails(const char* test_format, T value) { 1399 std::string format_string = std::string("<<") + test_format + ">>"; 1400 UntypedFormatSpecImpl format(format_string); 1401 1402 int one = 1; 1403 const FormatArgImpl args[] = {FormatArgImpl(value), FormatArgImpl(one)}; 1404 EXPECT_EQ(FormatPack(format, absl::MakeSpan(args)), "") 1405 << "format=" << test_format << " value=" << value; 1406 return FormatPack(format, absl::MakeSpan(args)).empty(); 1407 } 1408 1409 TEST_F(FormatConvertTest, ExpectedFailures) { 1410 // Int input 1411 EXPECT_TRUE(FormatFails("%p", 1)); 1412 EXPECT_TRUE(FormatFails("%s", 1)); 1413 EXPECT_TRUE(FormatFails("%n", 1)); 1414 1415 // Double input 1416 EXPECT_TRUE(FormatFails("%p", 1.)); 1417 EXPECT_TRUE(FormatFails("%s", 1.)); 1418 EXPECT_TRUE(FormatFails("%n", 1.)); 1419 EXPECT_TRUE(FormatFails("%c", 1.)); 1420 EXPECT_TRUE(FormatFails("%d", 1.)); 1421 EXPECT_TRUE(FormatFails("%x", 1.)); 1422 EXPECT_TRUE(FormatFails("%*d", 1.)); 1423 1424 // String input 1425 EXPECT_TRUE(FormatFails("%n", "")); 1426 EXPECT_TRUE(FormatFails("%c", "")); 1427 EXPECT_TRUE(FormatFails("%d", "")); 1428 EXPECT_TRUE(FormatFails("%x", "")); 1429 EXPECT_TRUE(FormatFails("%f", "")); 1430 EXPECT_TRUE(FormatFails("%*d", "")); 1431 } 1432 1433 // Sanity check to make sure that we are testing what we think we're testing on 1434 // e.g. the x86_64+glibc platform. 1435 TEST_F(FormatConvertTest, GlibcHasCorrectTraits) { 1436 #if defined(__GLIBC__) && defined(__x86_64__) 1437 constexpr bool kIsSupportedGlibc = true; 1438 #else 1439 constexpr bool kIsSupportedGlibc = false; 1440 #endif 1441 1442 if (!kIsSupportedGlibc) { 1443 GTEST_SKIP() << "Test does not support this platform"; 1444 } 1445 1446 const NativePrintfTraits &native_traits = VerifyNativeImplementation(); 1447 // If one of the following tests break then it is either because the above PP 1448 // macro guards failed to exclude a new platform (likely) or because something 1449 // has changed in the implementation of glibc sprintf float formatting 1450 // behavior. If the latter, then the code that computes these flags needs to 1451 // be revisited and/or possibly the StrFormat implementation. 1452 EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding); 1453 EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr); 1454 EXPECT_TRUE( 1455 native_traits.hex_float_uses_minimal_precision_when_not_specified); 1456 EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count); 1457 } 1458 1459 } // namespace 1460 } // namespace str_format_internal 1461 ABSL_NAMESPACE_END 1462 } // namespace absl