str_format_test.cc (42708B)
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 "absl/strings/str_format.h" 16 17 #include <cerrno> 18 #include <cstdarg> 19 #include <cstdint> 20 #include <cstdio> 21 #include <ostream> 22 #include <sstream> 23 #include <string> 24 #include <type_traits> 25 26 #include "gtest/gtest.h" 27 #include "absl/base/config.h" 28 #include "absl/base/macros.h" 29 #include "absl/strings/cord.h" 30 #include "absl/strings/str_cat.h" 31 #include "absl/strings/string_view.h" 32 #include "absl/types/span.h" 33 34 namespace absl { 35 ABSL_NAMESPACE_BEGIN 36 namespace { 37 using str_format_internal::FormatArgImpl; 38 39 using FormatEntryPointTest = ::testing::Test; 40 41 TEST_F(FormatEntryPointTest, Format) { 42 std::string sink; 43 EXPECT_TRUE(Format(&sink, "A format %d", 123)); 44 EXPECT_EQ("A format 123", sink); 45 sink.clear(); 46 47 ParsedFormat<'d'> pc("A format %d"); 48 EXPECT_TRUE(Format(&sink, pc, 123)); 49 EXPECT_EQ("A format 123", sink); 50 } 51 52 TEST_F(FormatEntryPointTest, FormatWithV) { 53 std::string sink; 54 EXPECT_TRUE(Format(&sink, "A format %v", 123)); 55 EXPECT_EQ("A format 123", sink); 56 sink.clear(); 57 58 ParsedFormat<'v'> pc("A format %v"); 59 EXPECT_TRUE(Format(&sink, pc, 123)); 60 EXPECT_EQ("A format 123", sink); 61 } 62 63 TEST_F(FormatEntryPointTest, UntypedFormat) { 64 constexpr const char* formats[] = { 65 "", 66 "a", 67 "%80d", 68 #if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__) 69 // MSVC, NaCL and Android don't support positional syntax. 70 "complicated multipart %% %1$d format %1$0999d", 71 #endif // _MSC_VER 72 }; 73 for (const char* fmt : formats) { 74 std::string actual; 75 int i = 123; 76 FormatArgImpl arg_123(i); 77 absl::Span<const FormatArgImpl> args(&arg_123, 1); 78 UntypedFormatSpec format(fmt); 79 80 EXPECT_TRUE(FormatUntyped(&actual, format, args)); 81 char buf[4096]{}; 82 snprintf(buf, sizeof(buf), fmt, 123); 83 EXPECT_EQ( 84 str_format_internal::FormatPack( 85 str_format_internal::UntypedFormatSpecImpl::Extract(format), args), 86 buf); 87 EXPECT_EQ(actual, buf); 88 } 89 // The internal version works with a preparsed format. 90 ParsedFormat<'d'> pc("A format %d"); 91 int i = 345; 92 FormatArg arg(i); 93 std::string out; 94 EXPECT_TRUE(str_format_internal::FormatUntyped( 95 &out, str_format_internal::UntypedFormatSpecImpl(&pc), {&arg, 1})); 96 EXPECT_EQ("A format 345", out); 97 } 98 99 TEST_F(FormatEntryPointTest, StringFormat) { 100 EXPECT_EQ("123", StrFormat("%d", 123)); 101 constexpr absl::string_view view("=%d=", 4); 102 EXPECT_EQ("=123=", StrFormat(view, 123)); 103 } 104 105 TEST_F(FormatEntryPointTest, StringFormatV) { 106 std::string hello = "hello"; 107 EXPECT_EQ("hello", StrFormat("%v", hello)); 108 EXPECT_EQ("123", StrFormat("%v", 123)); 109 constexpr absl::string_view view("=%v=", 4); 110 EXPECT_EQ("=123=", StrFormat(view, 123)); 111 } 112 113 TEST_F(FormatEntryPointTest, AppendFormat) { 114 std::string s; 115 std::string& r = StrAppendFormat(&s, "%d", 123); 116 EXPECT_EQ(&s, &r); // should be same object 117 EXPECT_EQ("123", r); 118 } 119 120 TEST_F(FormatEntryPointTest, AppendFormatWithV) { 121 std::string s; 122 std::string& r = StrAppendFormat(&s, "%v", 123); 123 EXPECT_EQ(&s, &r); // should be same object 124 EXPECT_EQ("123", r); 125 } 126 127 TEST_F(FormatEntryPointTest, AppendFormatFail) { 128 std::string s = "orig"; 129 130 UntypedFormatSpec format(" more %d"); 131 FormatArgImpl arg("not an int"); 132 133 EXPECT_EQ("orig", 134 str_format_internal::AppendPack( 135 &s, str_format_internal::UntypedFormatSpecImpl::Extract(format), 136 {&arg, 1})); 137 } 138 139 TEST_F(FormatEntryPointTest, AppendFormatFailWithV) { 140 std::string s = "orig"; 141 142 UntypedFormatSpec format(" more %v"); 143 FormatArgImpl arg("not an int"); 144 145 EXPECT_EQ("orig", 146 str_format_internal::AppendPack( 147 &s, str_format_internal::UntypedFormatSpecImpl::Extract(format), 148 {&arg, 1})); 149 } 150 151 TEST_F(FormatEntryPointTest, ManyArgs) { 152 EXPECT_EQ( 153 "60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 " 154 "36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 " 155 "12 11 10 9 8 7 6 5 4 3 2 1", 156 StrFormat("%60$d %59$d %58$d %57$d %56$d %55$d %54$d %53$d %52$d %51$d " 157 "%50$d %49$d %48$d %47$d %46$d %45$d %44$d %43$d %42$d %41$d " 158 "%40$d %39$d %38$d %37$d %36$d %35$d %34$d %33$d %32$d %31$d " 159 "%30$d %29$d %28$d %27$d %26$d %25$d %24$d %23$d %22$d %21$d " 160 "%20$d %19$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d " 161 "%10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d", 162 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 163 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 164 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 165 51, 52, 53, 54, 55, 56, 57, 58, 59, 60)); 166 } 167 168 TEST_F(FormatEntryPointTest, Preparsed) { 169 ParsedFormat<'d'> pc("%d"); 170 EXPECT_EQ("123", StrFormat(pc, 123)); 171 // rvalue ok? 172 EXPECT_EQ("123", StrFormat(ParsedFormat<'d'>("%d"), 123)); 173 constexpr absl::string_view view("=%d=", 4); 174 EXPECT_EQ("=123=", StrFormat(ParsedFormat<'d'>(view), 123)); 175 } 176 177 TEST_F(FormatEntryPointTest, PreparsedWithV) { 178 ParsedFormat<'v'> pc("%v"); 179 EXPECT_EQ("123", StrFormat(pc, 123)); 180 // rvalue ok? 181 EXPECT_EQ("123", StrFormat(ParsedFormat<'v'>("%v"), 123)); 182 constexpr absl::string_view view("=%v=", 4); 183 EXPECT_EQ("=123=", StrFormat(ParsedFormat<'v'>(view), 123)); 184 } 185 186 TEST_F(FormatEntryPointTest, FormatCountCapture) { 187 int n = 0; 188 EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n))); 189 EXPECT_EQ(0, n); 190 EXPECT_EQ("123", StrFormat("%d%n", 123, FormatCountCapture(&n))); 191 EXPECT_EQ(3, n); 192 } 193 194 TEST_F(FormatEntryPointTest, FormatCountCaptureWithV) { 195 int n = 0; 196 EXPECT_EQ("", StrFormat("%n", FormatCountCapture(&n))); 197 EXPECT_EQ(0, n); 198 EXPECT_EQ("123", StrFormat("%v%n", 123, FormatCountCapture(&n))); 199 EXPECT_EQ(3, n); 200 } 201 202 TEST_F(FormatEntryPointTest, FormatCountCaptureWrongType) { 203 // Should reject int*. 204 int n = 0; 205 UntypedFormatSpec format("%d%n"); 206 int i = 123, *ip = &n; 207 FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)}; 208 209 EXPECT_EQ("", str_format_internal::FormatPack( 210 str_format_internal::UntypedFormatSpecImpl::Extract(format), 211 absl::MakeSpan(args))); 212 } 213 214 TEST_F(FormatEntryPointTest, FormatCountCaptureWrongTypeWithV) { 215 // Should reject int*. 216 int n = 0; 217 UntypedFormatSpec format("%v%n"); 218 int i = 123, *ip = &n; 219 FormatArgImpl args[2] = {FormatArgImpl(i), FormatArgImpl(ip)}; 220 221 EXPECT_EQ("", str_format_internal::FormatPack( 222 str_format_internal::UntypedFormatSpecImpl::Extract(format), 223 absl::MakeSpan(args))); 224 } 225 226 TEST_F(FormatEntryPointTest, FormatCountCaptureMultiple) { 227 int n1 = 0; 228 int n2 = 0; 229 EXPECT_EQ(" 1 2", 230 StrFormat("%5d%n%10d%n", 1, FormatCountCapture(&n1), 2, 231 FormatCountCapture(&n2))); 232 EXPECT_EQ(5, n1); 233 EXPECT_EQ(15, n2); 234 } 235 236 TEST_F(FormatEntryPointTest, FormatCountCaptureExample) { 237 int n; 238 std::string s; 239 StrAppendFormat(&s, "%s: %n%s\n", "(1,1)", FormatCountCapture(&n), "(1,2)"); 240 StrAppendFormat(&s, "%*s%s\n", n, "", "(2,2)"); 241 EXPECT_EQ(7, n); 242 EXPECT_EQ( 243 "(1,1): (1,2)\n" 244 " (2,2)\n", 245 s); 246 } 247 248 TEST_F(FormatEntryPointTest, FormatCountCaptureExampleWithV) { 249 int n; 250 std::string s; 251 std::string a1 = "(1,1)"; 252 std::string a2 = "(1,2)"; 253 std::string a3 = "(2,2)"; 254 StrAppendFormat(&s, "%v: %n%v\n", a1, FormatCountCapture(&n), a2); 255 StrAppendFormat(&s, "%*s%v\n", n, "", a3); 256 EXPECT_EQ(7, n); 257 EXPECT_EQ( 258 "(1,1): (1,2)\n" 259 " (2,2)\n", 260 s); 261 } 262 263 TEST_F(FormatEntryPointTest, Stream) { 264 const std::string formats[] = { 265 "", 266 "a", 267 "%80d", 268 "%d %u %c %s %f %g", 269 #if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__) 270 // MSVC, NaCL and Android don't support positional syntax. 271 "complicated multipart %% %1$d format %1$080d", 272 #endif // _MSC_VER 273 }; 274 std::string buf(4096, '\0'); 275 for (const auto& fmt : formats) { 276 const auto parsed = 277 ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt); 278 std::ostringstream oss; 279 oss << StreamFormat(*parsed, 123, 3, 49, "multistreaming!!!", 1.01, 1.01); 280 int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), // 281 123, 3, 49, "multistreaming!!!", 1.01, 1.01); 282 ASSERT_TRUE(oss) << fmt; 283 ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size()) 284 << fmt_result; 285 EXPECT_EQ(buf.c_str(), oss.str()); 286 } 287 } 288 289 TEST_F(FormatEntryPointTest, StreamWithV) { 290 const std::string formats[] = { 291 "", 292 "a", 293 "%v %u %c %v %f %v", 294 }; 295 296 const std::string formats_for_buf[] = { 297 "", 298 "a", 299 "%d %u %c %s %f %g", 300 }; 301 302 std::string buf(4096, '\0'); 303 for (auto i = 0; i < ABSL_ARRAYSIZE(formats); ++i) { 304 const auto parsed = 305 ParsedFormat<'v', 'u', 'c', 'v', 'f', 'v'>::NewAllowIgnored(formats[i]); 306 std::ostringstream oss; 307 oss << StreamFormat(*parsed, 123, 3, 49, 308 absl::string_view("multistreaming!!!"), 1.01, 1.01); 309 int fmt_result = 310 snprintf(&*buf.begin(), buf.size(), formats_for_buf[i].c_str(), // 311 123, 3, 49, "multistreaming!!!", 1.01, 1.01); 312 ASSERT_TRUE(oss) << formats[i]; 313 ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size()) 314 << fmt_result; 315 EXPECT_EQ(buf.c_str(), oss.str()); 316 } 317 } 318 319 TEST_F(FormatEntryPointTest, StreamOk) { 320 std::ostringstream oss; 321 oss << StreamFormat("hello %d", 123); 322 EXPECT_EQ("hello 123", oss.str()); 323 EXPECT_TRUE(oss.good()); 324 } 325 326 TEST_F(FormatEntryPointTest, StreamOkWithV) { 327 std::ostringstream oss; 328 oss << StreamFormat("hello %v", 123); 329 EXPECT_EQ("hello 123", oss.str()); 330 EXPECT_TRUE(oss.good()); 331 } 332 333 TEST_F(FormatEntryPointTest, StreamFail) { 334 std::ostringstream oss; 335 UntypedFormatSpec format("hello %d"); 336 FormatArgImpl arg("non-numeric"); 337 oss << str_format_internal::Streamable( 338 str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1}); 339 EXPECT_EQ("hello ", oss.str()); // partial write 340 EXPECT_TRUE(oss.fail()); 341 } 342 343 TEST_F(FormatEntryPointTest, StreamFailWithV) { 344 std::ostringstream oss; 345 UntypedFormatSpec format("hello %v"); 346 FormatArgImpl arg("non-numeric"); 347 oss << str_format_internal::Streamable( 348 str_format_internal::UntypedFormatSpecImpl::Extract(format), {&arg, 1}); 349 EXPECT_EQ("hello ", oss.str()); // partial write 350 EXPECT_TRUE(oss.fail()); 351 } 352 353 std::string WithSnprintf(const char* fmt, ...) { 354 std::string buf; 355 buf.resize(128); 356 va_list va; 357 va_start(va, fmt); 358 int r = vsnprintf(&*buf.begin(), buf.size(), fmt, va); 359 va_end(va); 360 EXPECT_GE(r, 0); 361 EXPECT_LT(r, buf.size()); 362 buf.resize(r); 363 return buf; 364 } 365 366 TEST_F(FormatEntryPointTest, FloatPrecisionArg) { 367 // Test that positional parameters for width and precision 368 // are indexed to precede the value. 369 // Also sanity check the same formats against snprintf. 370 EXPECT_EQ("0.1", StrFormat("%.1f", 0.1)); 371 EXPECT_EQ("0.1", WithSnprintf("%.1f", 0.1)); 372 EXPECT_EQ(" 0.1", StrFormat("%*.1f", 5, 0.1)); 373 EXPECT_EQ(" 0.1", WithSnprintf("%*.1f", 5, 0.1)); 374 EXPECT_EQ("0.1", StrFormat("%.*f", 1, 0.1)); 375 EXPECT_EQ("0.1", WithSnprintf("%.*f", 1, 0.1)); 376 EXPECT_EQ(" 0.1", StrFormat("%*.*f", 5, 1, 0.1)); 377 EXPECT_EQ(" 0.1", WithSnprintf("%*.*f", 5, 1, 0.1)); 378 } 379 namespace streamed_test { 380 struct X {}; 381 std::ostream& operator<<(std::ostream& os, const X&) { 382 return os << "X"; 383 } 384 } // streamed_test 385 386 TEST_F(FormatEntryPointTest, FormatStreamed) { 387 EXPECT_EQ("123", StrFormat("%s", FormatStreamed(123))); 388 EXPECT_EQ(" 123", StrFormat("%5s", FormatStreamed(123))); 389 EXPECT_EQ("123 ", StrFormat("%-5s", FormatStreamed(123))); 390 EXPECT_EQ("X", StrFormat("%s", FormatStreamed(streamed_test::X()))); 391 EXPECT_EQ("123", StrFormat("%s", FormatStreamed(StreamFormat("%d", 123)))); 392 } 393 394 TEST_F(FormatEntryPointTest, FormatStreamedWithV) { 395 EXPECT_EQ("123", StrFormat("%v", FormatStreamed(123))); 396 EXPECT_EQ("X", StrFormat("%v", FormatStreamed(streamed_test::X()))); 397 EXPECT_EQ("123", StrFormat("%v", FormatStreamed(StreamFormat("%d", 123)))); 398 } 399 400 // Helper class that creates a temporary file and exposes a FILE* to it. 401 // It will close the file on destruction. 402 class TempFile { 403 public: 404 TempFile() : file_(std::tmpfile()) {} 405 ~TempFile() { std::fclose(file_); } 406 407 std::FILE* file() const { return file_; } 408 409 // Read the file into a string. 410 std::string ReadFile() { 411 std::fseek(file_, 0, SEEK_END); 412 int size = std::ftell(file_); 413 EXPECT_GT(size, 0); 414 std::rewind(file_); 415 std::string str(2 * size, ' '); 416 int read_bytes = std::fread(&str[0], 1, str.size(), file_); 417 EXPECT_EQ(read_bytes, size); 418 str.resize(read_bytes); 419 EXPECT_TRUE(std::feof(file_)); 420 return str; 421 } 422 423 private: 424 std::FILE* file_; 425 }; 426 427 TEST_F(FormatEntryPointTest, FPrintF) { 428 TempFile tmp; 429 int result = 430 FPrintF(tmp.file(), "STRING: %s NUMBER: %010d", std::string("ABC"), -19); 431 EXPECT_EQ(result, 30); 432 EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019"); 433 } 434 435 TEST_F(FormatEntryPointTest, FPrintFWithV) { 436 TempFile tmp; 437 int result = 438 FPrintF(tmp.file(), "STRING: %v NUMBER: %010d", std::string("ABC"), -19); 439 EXPECT_EQ(result, 30); 440 EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019"); 441 } 442 443 TEST_F(FormatEntryPointTest, FPrintFError) { 444 errno = 0; 445 int result = FPrintF(stdin, "ABC"); 446 EXPECT_LT(result, 0); 447 EXPECT_EQ(errno, EBADF); 448 } 449 450 #ifdef __GLIBC__ 451 TEST_F(FormatEntryPointTest, FprintfTooLarge) { 452 std::FILE* f = std::fopen("/dev/null", "w"); 453 int width = 2000000000; 454 errno = 0; 455 int result = FPrintF(f, "%*d %*d", width, 0, width, 0); 456 EXPECT_LT(result, 0); 457 EXPECT_EQ(errno, EFBIG); 458 std::fclose(f); 459 } 460 461 TEST_F(FormatEntryPointTest, PrintF) { 462 int stdout_tmp = dup(STDOUT_FILENO); 463 464 TempFile tmp; 465 std::fflush(stdout); 466 dup2(fileno(tmp.file()), STDOUT_FILENO); 467 468 int result = PrintF("STRING: %s NUMBER: %010d", std::string("ABC"), -19); 469 470 std::fflush(stdout); 471 dup2(stdout_tmp, STDOUT_FILENO); 472 close(stdout_tmp); 473 474 EXPECT_EQ(result, 30); 475 EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019"); 476 } 477 478 TEST_F(FormatEntryPointTest, PrintFWithV) { 479 int stdout_tmp = dup(STDOUT_FILENO); 480 481 TempFile tmp; 482 std::fflush(stdout); 483 dup2(fileno(tmp.file()), STDOUT_FILENO); 484 485 int result = PrintF("STRING: %v NUMBER: %010d", std::string("ABC"), -19); 486 487 std::fflush(stdout); 488 dup2(stdout_tmp, STDOUT_FILENO); 489 close(stdout_tmp); 490 491 EXPECT_EQ(result, 30); 492 EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019"); 493 } 494 #endif // __GLIBC__ 495 496 TEST_F(FormatEntryPointTest, SNPrintF) { 497 char buffer[16]; 498 int result = 499 SNPrintF(buffer, sizeof(buffer), "STRING: %s", std::string("ABC")); 500 EXPECT_EQ(result, 11); 501 EXPECT_EQ(std::string(buffer), "STRING: ABC"); 502 503 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456); 504 EXPECT_EQ(result, 14); 505 EXPECT_EQ(std::string(buffer), "NUMBER: 123456"); 506 507 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 1234567); 508 EXPECT_EQ(result, 15); 509 EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); 510 511 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 12345678); 512 EXPECT_EQ(result, 16); 513 EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); 514 515 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %d", 123456789); 516 EXPECT_EQ(result, 17); 517 EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); 518 519 // The `output` parameter is annotated nonnull, but we want to test that 520 // it is never written to if the size is zero. 521 // Use a variable instead of passing nullptr directly to avoid a `-Wnonnull` 522 // warning. 523 char* null_output = nullptr; 524 result = 525 SNPrintF(null_output, 0, "Just checking the %s of the output.", "size"); 526 EXPECT_EQ(result, 37); 527 } 528 529 TEST_F(FormatEntryPointTest, SNPrintFWithV) { 530 char buffer[16]; 531 int result = 532 SNPrintF(buffer, sizeof(buffer), "STRING: %v", std::string("ABC")); 533 EXPECT_EQ(result, 11); 534 EXPECT_EQ(std::string(buffer), "STRING: ABC"); 535 536 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456); 537 EXPECT_EQ(result, 14); 538 EXPECT_EQ(std::string(buffer), "NUMBER: 123456"); 539 540 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 1234567); 541 EXPECT_EQ(result, 15); 542 EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); 543 544 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 12345678); 545 EXPECT_EQ(result, 16); 546 EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); 547 548 result = SNPrintF(buffer, sizeof(buffer), "NUMBER: %v", 123456789); 549 EXPECT_EQ(result, 17); 550 EXPECT_EQ(std::string(buffer), "NUMBER: 1234567"); 551 552 std::string size = "size"; 553 554 // The `output` parameter is annotated nonnull, but we want to test that 555 // it is never written to if the size is zero. 556 // Use a variable instead of passing nullptr directly to avoid a `-Wnonnull` 557 // warning. 558 char* null_output = nullptr; 559 result = 560 SNPrintF(null_output, 0, "Just checking the %v of the output.", size); 561 EXPECT_EQ(result, 37); 562 } 563 564 TEST(StrFormat, BehavesAsDocumented) { 565 std::string s = absl::StrFormat("%s, %d!", "Hello", 123); 566 EXPECT_EQ("Hello, 123!", s); 567 std::string hello = "Hello"; 568 std::string s2 = absl::StrFormat("%v, %v!", hello, 123); 569 EXPECT_EQ("Hello, 123!", s2); 570 // The format of a replacement is 571 // '%'[position][flags][width['.'precision]][length_modifier][format] 572 EXPECT_EQ(absl::StrFormat("%1$+3.2Lf", 1.1), "+1.10"); 573 // Text conversion: 574 // "c" - Character. Eg: 'a' -> "A", 20 -> " " 575 EXPECT_EQ(StrFormat("%c", 'a'), "a"); 576 EXPECT_EQ(StrFormat("%c", 0x20), " "); 577 // Formats char and integral types: int, long, uint64_t, etc. 578 EXPECT_EQ(StrFormat("%c", int{'a'}), "a"); 579 EXPECT_EQ(StrFormat("%c", long{'a'}), "a"); // NOLINT 580 EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a"); 581 // "s" - string Eg: "C" -> "C", std::string("C++") -> "C++" 582 // Formats std::string, char*, string_view, and Cord. 583 EXPECT_EQ(StrFormat("%s", "C"), "C"); 584 EXPECT_EQ(StrFormat("%v", std::string("C")), "C"); 585 EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++"); 586 EXPECT_EQ(StrFormat("%v", std::string("C++")), "C++"); 587 EXPECT_EQ(StrFormat("%s", string_view("view")), "view"); 588 EXPECT_EQ(StrFormat("%v", string_view("view")), "view"); 589 EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord"); 590 EXPECT_EQ(StrFormat("%v", absl::Cord("cord")), "cord"); 591 // Integral Conversion 592 // These format integral types: char, int, long, uint64_t, etc. 593 EXPECT_EQ(StrFormat("%d", char{10}), "10"); 594 EXPECT_EQ(StrFormat("%d", int{10}), "10"); 595 EXPECT_EQ(StrFormat("%d", long{10}), "10"); // NOLINT 596 EXPECT_EQ(StrFormat("%d", uint64_t{10}), "10"); 597 EXPECT_EQ(StrFormat("%v", int{10}), "10"); 598 EXPECT_EQ(StrFormat("%v", long{10}), "10"); // NOLINT 599 EXPECT_EQ(StrFormat("%v", uint64_t{10}), "10"); 600 // d,i - signed decimal Eg: -10 -> "-10" 601 EXPECT_EQ(StrFormat("%d", -10), "-10"); 602 EXPECT_EQ(StrFormat("%i", -10), "-10"); 603 EXPECT_EQ(StrFormat("%v", -10), "-10"); 604 // o - octal Eg: 10 -> "12" 605 EXPECT_EQ(StrFormat("%o", 10), "12"); 606 // u - unsigned decimal Eg: 10 -> "10" 607 EXPECT_EQ(StrFormat("%u", 10), "10"); 608 EXPECT_EQ(StrFormat("%v", 10), "10"); 609 // x/X - lower,upper case hex Eg: 10 -> "a"/"A" 610 EXPECT_EQ(StrFormat("%x", 10), "a"); 611 EXPECT_EQ(StrFormat("%X", 10), "A"); 612 // Floating-point, with upper/lower-case output. 613 // These format floating points types: float, double, long double, etc. 614 EXPECT_EQ(StrFormat("%.1f", float{1}), "1.0"); 615 EXPECT_EQ(StrFormat("%.1f", double{1}), "1.0"); 616 const long double long_double = 1.0; 617 EXPECT_EQ(StrFormat("%.1f", long_double), "1.0"); 618 // These also format integral types: char, int, long, uint64_t, etc.: 619 EXPECT_EQ(StrFormat("%.1f", char{1}), "1.0"); 620 EXPECT_EQ(StrFormat("%.1f", int{1}), "1.0"); 621 EXPECT_EQ(StrFormat("%.1f", long{1}), "1.0"); // NOLINT 622 EXPECT_EQ(StrFormat("%.1f", uint64_t{1}), "1.0"); 623 // f/F - decimal. Eg: 123456789 -> "123456789.000000" 624 EXPECT_EQ(StrFormat("%f", 123456789), "123456789.000000"); 625 EXPECT_EQ(StrFormat("%F", 123456789), "123456789.000000"); 626 // e/E - exponentiated Eg: .01 -> "1.00000e-2"/"1.00000E-2" 627 EXPECT_EQ(StrFormat("%e", .01), "1.000000e-02"); 628 EXPECT_EQ(StrFormat("%E", .01), "1.000000E-02"); 629 // g/G - exponentiate to fit Eg: .01 -> "0.01", 1e10 ->"1e+10"/"1E+10" 630 EXPECT_EQ(StrFormat("%g", .01), "0.01"); 631 EXPECT_EQ(StrFormat("%g", 1e10), "1e+10"); 632 EXPECT_EQ(StrFormat("%G", 1e10), "1E+10"); 633 EXPECT_EQ(StrFormat("%v", .01), "0.01"); 634 EXPECT_EQ(StrFormat("%v", 1e10), "1e+10"); 635 // a/A - lower,upper case hex Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1" 636 637 // On Android platform <=21, there is a regression in hexfloat formatting. 638 #if !defined(__ANDROID_API__) || __ANDROID_API__ > 21 639 EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1"); // .1 to fix MSVC output 640 EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1"); // .1 to fix MSVC output 641 #endif 642 643 // Other conversion 644 int64_t value = 0x7ffdeb4; 645 auto ptr_value = static_cast<uintptr_t>(value); 646 const int& something = *reinterpret_cast<const int*>(ptr_value); 647 EXPECT_EQ(StrFormat("%p", &something), StrFormat("0x%x", ptr_value)); 648 649 // The output of formatting a null pointer is not documented as being a 650 // specific thing, but the attempt should at least compile. 651 (void)StrFormat("%p", nullptr); 652 653 // Output widths are supported, with optional flags. 654 EXPECT_EQ(StrFormat("%3d", 1), " 1"); 655 EXPECT_EQ(StrFormat("%3d", 123456), "123456"); 656 EXPECT_EQ(StrFormat("%06.2f", 1.234), "001.23"); 657 EXPECT_EQ(StrFormat("%+d", 1), "+1"); 658 EXPECT_EQ(StrFormat("% d", 1), " 1"); 659 EXPECT_EQ(StrFormat("%-4d", -1), "-1 "); 660 EXPECT_EQ(StrFormat("%#o", 10), "012"); 661 EXPECT_EQ(StrFormat("%#x", 15), "0xf"); 662 EXPECT_EQ(StrFormat("%04d", 8), "0008"); 663 EXPECT_EQ(StrFormat("%#04x", 0), "0000"); 664 EXPECT_EQ(StrFormat("%#04x", 1), "0x01"); 665 // Posix positional substitution. 666 EXPECT_EQ(absl::StrFormat("%2$s, %3$s, %1$s!", "vici", "veni", "vidi"), 667 "veni, vidi, vici!"); 668 // Length modifiers are ignored. 669 EXPECT_EQ(StrFormat("%hhd", int{1}), "1"); 670 EXPECT_EQ(StrFormat("%hd", int{1}), "1"); 671 EXPECT_EQ(StrFormat("%ld", int{1}), "1"); 672 EXPECT_EQ(StrFormat("%lld", int{1}), "1"); 673 EXPECT_EQ(StrFormat("%Ld", int{1}), "1"); 674 EXPECT_EQ(StrFormat("%jd", int{1}), "1"); 675 EXPECT_EQ(StrFormat("%zd", int{1}), "1"); 676 EXPECT_EQ(StrFormat("%td", int{1}), "1"); 677 EXPECT_EQ(StrFormat("%qd", int{1}), "1"); 678 679 // Bool is handled correctly depending on whether %v is used 680 EXPECT_EQ(StrFormat("%v", true), "true"); 681 EXPECT_EQ(StrFormat("%v", false), "false"); 682 EXPECT_EQ(StrFormat("%d", true), "1"); 683 } 684 685 using str_format_internal::ExtendedParsedFormat; 686 using str_format_internal::ParsedFormatBase; 687 688 struct SummarizeConsumer { 689 std::string* out; 690 explicit SummarizeConsumer(std::string* out) : out(out) {} 691 692 bool Append(string_view s) { 693 *out += "[" + std::string(s) + "]"; 694 return true; 695 } 696 697 bool ConvertOne(const str_format_internal::UnboundConversion& conv, 698 string_view s) { 699 *out += "{"; 700 *out += std::string(s); 701 *out += ":"; 702 *out += std::to_string(conv.arg_position) + "$"; 703 if (conv.width.is_from_arg()) { 704 *out += std::to_string(conv.width.get_from_arg()) + "$*"; 705 } 706 if (conv.precision.is_from_arg()) { 707 *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*"; 708 } 709 *out += str_format_internal::FormatConversionCharToChar(conv.conv); 710 *out += "}"; 711 return true; 712 } 713 }; 714 715 std::string SummarizeParsedFormat(const ParsedFormatBase& pc) { 716 std::string out; 717 if (!pc.ProcessFormat(SummarizeConsumer(&out))) out += "!"; 718 return out; 719 } 720 721 using ParsedFormatTest = ::testing::Test; 722 723 TEST_F(ParsedFormatTest, SimpleChecked) { 724 EXPECT_EQ("[ABC]{d:1$d}[DEF]", 725 SummarizeParsedFormat(ParsedFormat<'d'>("ABC%dDEF"))); 726 EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", 727 SummarizeParsedFormat(ParsedFormat<'s', 'd', 'f'>("%sFFF%dZZZ%f"))); 728 EXPECT_EQ("{s:1$s}[ ]{.*d:3$.2$*d}", 729 SummarizeParsedFormat(ParsedFormat<'s', '*', 'd'>("%s %.*d"))); 730 } 731 732 TEST_F(ParsedFormatTest, SimpleCheckedWithV) { 733 EXPECT_EQ("[ABC]{v:1$v}[DEF]", 734 SummarizeParsedFormat(ParsedFormat<'v'>("ABC%vDEF"))); 735 EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", 736 SummarizeParsedFormat(ParsedFormat<'v', 'v', 'f'>("%vFFF%vZZZ%f"))); 737 EXPECT_EQ("{v:1$v}[ ]{.*d:3$.2$*d}", 738 SummarizeParsedFormat(ParsedFormat<'v', '*', 'd'>("%v %.*d"))); 739 } 740 741 TEST_F(ParsedFormatTest, SimpleUncheckedCorrect) { 742 auto f = ParsedFormat<'d'>::New("ABC%dDEF"); 743 ASSERT_TRUE(f); 744 EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f)); 745 746 std::string format = "%sFFF%dZZZ%f"; 747 auto f2 = ParsedFormat<'s', 'd', 'f'>::New(format); 748 749 ASSERT_TRUE(f2); 750 EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); 751 752 f2 = ParsedFormat<'s', 'd', 'f'>::New("%s %d %f"); 753 754 ASSERT_TRUE(f2); 755 EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); 756 757 auto star = ParsedFormat<'*', 'd'>::New("%*d"); 758 ASSERT_TRUE(star); 759 EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star)); 760 761 auto dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d"); 762 ASSERT_TRUE(dollar); 763 EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar)); 764 // with reuse 765 dollar = ParsedFormat<'d', 's'>::New("%2$s %1$d %1$d"); 766 ASSERT_TRUE(dollar); 767 EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}", 768 SummarizeParsedFormat(*dollar)); 769 } 770 771 TEST_F(ParsedFormatTest, SimpleUncheckedCorrectWithV) { 772 auto f = ParsedFormat<'v'>::New("ABC%vDEF"); 773 ASSERT_TRUE(f); 774 EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f)); 775 776 std::string format = "%vFFF%vZZZ%f"; 777 auto f2 = ParsedFormat<'v', 'v', 'f'>::New(format); 778 779 ASSERT_TRUE(f2); 780 EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); 781 782 f2 = ParsedFormat<'v', 'v', 'f'>::New("%v %v %f"); 783 784 ASSERT_TRUE(f2); 785 EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); 786 } 787 788 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgs) { 789 EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC"))); 790 EXPECT_FALSE((ParsedFormat<'d', 's'>::New("%dABC"))); 791 EXPECT_FALSE((ParsedFormat<'d', 's'>::New("ABC%2$s"))); 792 auto f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC"); 793 ASSERT_TRUE(f); 794 EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); 795 f = ParsedFormat<'d', 's'>::NewAllowIgnored("%dABC"); 796 ASSERT_TRUE(f); 797 EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f)); 798 f = ParsedFormat<'d', 's'>::NewAllowIgnored("ABC%2$s"); 799 ASSERT_TRUE(f); 800 EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f)); 801 } 802 803 TEST_F(ParsedFormatTest, SimpleUncheckedIgnoredArgsWithV) { 804 EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("ABC"))); 805 EXPECT_FALSE((ParsedFormat<'v', 'v'>::New("%vABC"))); 806 EXPECT_FALSE((ParsedFormat<'v', 's'>::New("ABC%2$s"))); 807 auto f = ParsedFormat<'v', 'v'>::NewAllowIgnored("ABC"); 808 ASSERT_TRUE(f); 809 EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); 810 f = ParsedFormat<'v', 'v'>::NewAllowIgnored("%vABC"); 811 ASSERT_TRUE(f); 812 EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f)); 813 } 814 815 TEST_F(ParsedFormatTest, SimpleUncheckedUnsupported) { 816 EXPECT_FALSE(ParsedFormat<'d'>::New("%1$d %1$x")); 817 EXPECT_FALSE(ParsedFormat<'x'>::New("%1$d %1$x")); 818 } 819 820 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) { 821 EXPECT_FALSE(ParsedFormat<'d'>::New("")); 822 823 EXPECT_FALSE(ParsedFormat<'d'>::New("ABC%dDEF%d")); 824 825 std::string format = "%sFFF%dZZZ%f"; 826 EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format))); 827 } 828 829 TEST_F(ParsedFormatTest, SimpleUncheckedIncorrectWithV) { 830 EXPECT_FALSE(ParsedFormat<'v'>::New("")); 831 832 EXPECT_FALSE(ParsedFormat<'v'>::New("ABC%vDEF%v")); 833 834 std::string format = "%vFFF%vZZZ%f"; 835 EXPECT_FALSE((ParsedFormat<'v', 'v', 'g'>::New(format))); 836 } 837 838 #if defined(__cpp_nontype_template_parameter_auto) 839 840 template <auto T> 841 std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*); 842 843 template <auto T> 844 std::false_type IsValidParsedFormatArgTest(...); 845 846 template <auto T> 847 using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr)); 848 849 TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) { 850 ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value); 851 852 ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value); 853 854 ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d | 855 absl::FormatConversionCharSet::x>::value); 856 ASSERT_TRUE( 857 IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value); 858 859 // This is an easy mistake to make, however, this will reduce to an integer 860 // which has no meaning, so we need to ensure it doesn't compile. 861 ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value); 862 863 // For now, we disallow construction based on ConversionChar (rather than 864 // CharSet) 865 ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value); 866 } 867 868 TEST_F(ParsedFormatTest, ExtendedTyping) { 869 EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New("")); 870 ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d")); 871 auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s"); 872 ASSERT_TRUE(v1); 873 auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s"); 874 ASSERT_TRUE(v2); 875 auto v3 = ParsedFormat<absl::FormatConversionCharSet::d | 876 absl::FormatConversionCharSet::s, 877 's'>::New("%d%s"); 878 ASSERT_TRUE(v3); 879 auto v4 = ParsedFormat<absl::FormatConversionCharSet::d | 880 absl::FormatConversionCharSet::s, 881 's'>::New("%s%s"); 882 ASSERT_TRUE(v4); 883 } 884 885 TEST_F(ParsedFormatTest, ExtendedTypingWithV) { 886 EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::v>::New("")); 887 ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::v>::New("%v")); 888 auto v1 = ParsedFormat<'v', absl::FormatConversionCharSet::v>::New("%v%v"); 889 ASSERT_TRUE(v1); 890 auto v2 = ParsedFormat<absl::FormatConversionCharSet::v, 'v'>::New("%v%v"); 891 ASSERT_TRUE(v2); 892 auto v3 = ParsedFormat<absl::FormatConversionCharSet::v | 893 absl::FormatConversionCharSet::v, 894 'v'>::New("%v%v"); 895 ASSERT_TRUE(v3); 896 auto v4 = ParsedFormat<absl::FormatConversionCharSet::v | 897 absl::FormatConversionCharSet::v, 898 'v'>::New("%v%v"); 899 ASSERT_TRUE(v4); 900 } 901 #endif 902 903 TEST_F(ParsedFormatTest, UncheckedCorrect) { 904 auto f = 905 ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF"); 906 ASSERT_TRUE(f); 907 EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f)); 908 909 std::string format = "%sFFF%dZZZ%f"; 910 auto f2 = ExtendedParsedFormat< 911 absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d, 912 absl::FormatConversionCharSet::kFloating>::New(format); 913 914 ASSERT_TRUE(f2); 915 EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); 916 917 f2 = ExtendedParsedFormat< 918 absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d, 919 absl::FormatConversionCharSet::kFloating>::New("%s %d %f"); 920 921 ASSERT_TRUE(f2); 922 EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); 923 924 auto star = 925 ExtendedParsedFormat<absl::FormatConversionCharSet::kStar, 926 absl::FormatConversionCharSet::d>::New("%*d"); 927 ASSERT_TRUE(star); 928 EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star)); 929 930 auto dollar = 931 ExtendedParsedFormat<absl::FormatConversionCharSet::d, 932 absl::FormatConversionCharSet::s>::New("%2$s %1$d"); 933 ASSERT_TRUE(dollar); 934 EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar)); 935 // with reuse 936 dollar = ExtendedParsedFormat< 937 absl::FormatConversionCharSet::d, 938 absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d"); 939 ASSERT_TRUE(dollar); 940 EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}", 941 SummarizeParsedFormat(*dollar)); 942 } 943 944 TEST_F(ParsedFormatTest, UncheckedCorrectWithV) { 945 auto f = 946 ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New("ABC%vDEF"); 947 ASSERT_TRUE(f); 948 EXPECT_EQ("[ABC]{v:1$v}[DEF]", SummarizeParsedFormat(*f)); 949 950 std::string format = "%vFFF%vZZZ%f"; 951 auto f2 = ExtendedParsedFormat< 952 absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v, 953 absl::FormatConversionCharSet::kFloating>::New(format); 954 955 ASSERT_TRUE(f2); 956 EXPECT_EQ("{v:1$v}[FFF]{v:2$v}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); 957 958 f2 = ExtendedParsedFormat< 959 absl::FormatConversionCharSet::v, absl::FormatConversionCharSet::v, 960 absl::FormatConversionCharSet::kFloating>::New("%v %v %f"); 961 962 ASSERT_TRUE(f2); 963 EXPECT_EQ("{v:1$v}[ ]{v:2$v}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); 964 } 965 966 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) { 967 EXPECT_FALSE( 968 (ExtendedParsedFormat<absl::FormatConversionCharSet::d, 969 absl::FormatConversionCharSet::s>::New("ABC"))); 970 EXPECT_FALSE( 971 (ExtendedParsedFormat<absl::FormatConversionCharSet::d, 972 absl::FormatConversionCharSet::s>::New("%dABC"))); 973 EXPECT_FALSE( 974 (ExtendedParsedFormat<absl::FormatConversionCharSet::d, 975 absl::FormatConversionCharSet::s>::New("ABC%2$s"))); 976 auto f = ExtendedParsedFormat< 977 absl::FormatConversionCharSet::d, 978 absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC"); 979 ASSERT_TRUE(f); 980 EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); 981 f = ExtendedParsedFormat< 982 absl::FormatConversionCharSet::d, 983 absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC"); 984 ASSERT_TRUE(f); 985 EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f)); 986 f = ExtendedParsedFormat< 987 absl::FormatConversionCharSet::d, 988 absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s"); 989 ASSERT_TRUE(f); 990 EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f)); 991 } 992 993 TEST_F(ParsedFormatTest, UncheckedIgnoredArgsWithV) { 994 EXPECT_FALSE( 995 (ExtendedParsedFormat<absl::FormatConversionCharSet::v, 996 absl::FormatConversionCharSet::v>::New("ABC"))); 997 EXPECT_FALSE( 998 (ExtendedParsedFormat<absl::FormatConversionCharSet::v, 999 absl::FormatConversionCharSet::v>::New("%vABC"))); 1000 EXPECT_FALSE((ExtendedParsedFormat<absl::FormatConversionCharSet::v, 1001 absl::FormatConversionCharSet::s>:: 1002 New("ABC%2$s"))); 1003 auto f = ExtendedParsedFormat< 1004 absl::FormatConversionCharSet::v, 1005 absl::FormatConversionCharSet::v>::NewAllowIgnored("ABC"); 1006 ASSERT_TRUE(f); 1007 EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); 1008 f = ExtendedParsedFormat< 1009 absl::FormatConversionCharSet::v, 1010 absl::FormatConversionCharSet::v>::NewAllowIgnored("%vABC"); 1011 ASSERT_TRUE(f); 1012 EXPECT_EQ("{v:1$v}[ABC]", SummarizeParsedFormat(*f)); 1013 } 1014 1015 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) { 1016 auto dx = 1017 ExtendedParsedFormat<absl::FormatConversionCharSet::d | 1018 absl::FormatConversionCharSet::x>::New("%1$d %1$x"); 1019 EXPECT_TRUE(dx); 1020 EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx)); 1021 1022 dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d | 1023 absl::FormatConversionCharSet::x>::New("%1$d"); 1024 EXPECT_TRUE(dx); 1025 EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx)); 1026 } 1027 1028 TEST_F(ParsedFormatTest, UncheckedIncorrect) { 1029 EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("")); 1030 1031 EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New( 1032 "ABC%dDEF%d")); 1033 1034 std::string format = "%sFFF%dZZZ%f"; 1035 EXPECT_FALSE( 1036 (ExtendedParsedFormat<absl::FormatConversionCharSet::s, 1037 absl::FormatConversionCharSet::d, 1038 absl::FormatConversionCharSet::g>::New(format))); 1039 } 1040 1041 TEST_F(ParsedFormatTest, UncheckedIncorrectWithV) { 1042 EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New("")); 1043 1044 EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::v>::New( 1045 "ABC%vDEF%v")); 1046 1047 std::string format = "%vFFF%vZZZ%f"; 1048 EXPECT_FALSE( 1049 (ExtendedParsedFormat<absl::FormatConversionCharSet::v, 1050 absl::FormatConversionCharSet::g>::New(format))); 1051 } 1052 1053 TEST_F(ParsedFormatTest, RegressionMixPositional) { 1054 EXPECT_FALSE( 1055 (ExtendedParsedFormat<absl::FormatConversionCharSet::d, 1056 absl::FormatConversionCharSet::o>::New("%1$d %o"))); 1057 } 1058 1059 TEST_F(ParsedFormatTest, DisallowModifiersWithV) { 1060 auto f = ParsedFormat<'v'>::New("ABC%80vDEF"); 1061 EXPECT_EQ(f, nullptr); 1062 1063 f = ParsedFormat<'v'>::New("ABC%0vDEF"); 1064 EXPECT_EQ(f, nullptr); 1065 1066 f = ParsedFormat<'v'>::New("ABC%.1vDEF"); 1067 EXPECT_EQ(f, nullptr); 1068 } 1069 1070 using FormatWrapperTest = ::testing::Test; 1071 1072 // Plain wrapper for StrFormat. 1073 template <typename... Args> 1074 std::string WrappedFormat(const absl::FormatSpec<Args...>& format, 1075 const Args&... args) { 1076 return StrFormat(format, args...); 1077 } 1078 1079 TEST_F(FormatWrapperTest, ConstexprStringFormat) { 1080 EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there"); 1081 } 1082 1083 TEST_F(FormatWrapperTest, ConstexprStringFormatWithV) { 1084 std::string hello = "hello"; 1085 EXPECT_EQ(WrappedFormat("%v there", hello), "hello there"); 1086 } 1087 1088 TEST_F(FormatWrapperTest, ParsedFormat) { 1089 ParsedFormat<'s'> format("%s there"); 1090 EXPECT_EQ(WrappedFormat(format, "hello"), "hello there"); 1091 } 1092 1093 TEST_F(FormatWrapperTest, ParsedFormatWithV) { 1094 std::string hello = "hello"; 1095 ParsedFormat<'v'> format("%v there"); 1096 EXPECT_EQ(WrappedFormat(format, hello), "hello there"); 1097 } 1098 1099 } // namespace 1100 ABSL_NAMESPACE_END 1101 } // namespace absl 1102 1103 namespace { 1104 using FormatExtensionTest = ::testing::Test; 1105 1106 struct Point { 1107 friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString | 1108 absl::FormatConversionCharSet::kIntegral | 1109 absl::FormatConversionCharSet::v> 1110 AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec, 1111 absl::FormatSink* s) { 1112 if (spec.conversion_char() == absl::FormatConversionChar::s) { 1113 s->Append(absl::StrCat("x=", p.x, " y=", p.y)); 1114 } else { 1115 s->Append(absl::StrCat(p.x, ",", p.y)); 1116 } 1117 return {true}; 1118 } 1119 1120 int x = 10; 1121 int y = 20; 1122 }; 1123 1124 TEST_F(FormatExtensionTest, AbslFormatConvertExample) { 1125 Point p; 1126 EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z"); 1127 EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z"); 1128 EXPECT_EQ(absl::StrFormat("a %v z", p), "a 10,20 z"); 1129 1130 // Typed formatting will fail to compile an invalid format. 1131 // StrFormat("%f", p); // Does not compile. 1132 std::string actual; 1133 absl::UntypedFormatSpec f1("%f"); 1134 // FormatUntyped will return false for bad character. 1135 EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)})); 1136 } 1137 1138 struct PointStringify { 1139 template <typename FormatSink> 1140 friend void AbslStringify(FormatSink& sink, const PointStringify& p) { 1141 sink.Append(absl::StrCat("(", p.x, ", ", p.y, ")")); 1142 } 1143 1144 double x = 10.0; 1145 double y = 20.0; 1146 }; 1147 1148 TEST_F(FormatExtensionTest, AbslStringifyExample) { 1149 PointStringify p; 1150 EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z"); 1151 } 1152 1153 struct PointStringifyUsingFormat { 1154 template <typename FormatSink> 1155 friend void AbslStringify(FormatSink& sink, 1156 const PointStringifyUsingFormat& p) { 1157 absl::Format(&sink, "(%g, %g)", p.x, p.y); 1158 } 1159 1160 double x = 10.0; 1161 double y = 20.0; 1162 }; 1163 1164 TEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) { 1165 PointStringifyUsingFormat p; 1166 EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z"); 1167 } 1168 1169 enum class EnumClassWithStringify { Many = 0, Choices = 1 }; 1170 1171 template <typename Sink> 1172 void AbslStringify(Sink& sink, EnumClassWithStringify e) { 1173 absl::Format(&sink, "%s", 1174 e == EnumClassWithStringify::Many ? "Many" : "Choices"); 1175 } 1176 1177 enum EnumWithStringify { Many, Choices }; 1178 1179 template <typename Sink> 1180 void AbslStringify(Sink& sink, EnumWithStringify e) { 1181 absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices"); 1182 } 1183 1184 TEST_F(FormatExtensionTest, AbslStringifyWithEnumWithV) { 1185 const auto e_class = EnumClassWithStringify::Choices; 1186 EXPECT_EQ(absl::StrFormat("My choice is %v", e_class), 1187 "My choice is Choices"); 1188 1189 const auto e = EnumWithStringify::Choices; 1190 EXPECT_EQ(absl::StrFormat("My choice is %v", e), "My choice is Choices"); 1191 } 1192 1193 TEST_F(FormatExtensionTest, AbslStringifyEnumWithD) { 1194 const auto e_class = EnumClassWithStringify::Many; 1195 EXPECT_EQ(absl::StrFormat("My choice is %d", e_class), "My choice is 0"); 1196 1197 const auto e = EnumWithStringify::Choices; 1198 EXPECT_EQ(absl::StrFormat("My choice is %d", e), "My choice is 1"); 1199 } 1200 1201 enum class EnumWithLargerValue { x = 32 }; 1202 1203 template <typename Sink> 1204 void AbslStringify(Sink& sink, EnumWithLargerValue e) { 1205 absl::Format(&sink, "%s", "Many"); 1206 } 1207 1208 TEST_F(FormatExtensionTest, AbslStringifyEnumOtherSpecifiers) { 1209 const auto e = EnumWithLargerValue::x; 1210 EXPECT_EQ(absl::StrFormat("My choice is %g", e), "My choice is 32"); 1211 EXPECT_EQ(absl::StrFormat("My choice is %x", e), "My choice is 20"); 1212 } 1213 1214 } // namespace 1215 1216 // Some codegen thunks that we can use to easily dump the generated assembly for 1217 // different StrFormat calls. 1218 1219 std::string CodegenAbslStrFormatInt(int i) { // NOLINT 1220 return absl::StrFormat("%d", i); 1221 } 1222 1223 std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s, 1224 int64_t i64) { // NOLINT 1225 return absl::StrFormat("%d %s %d", i, s, i64); 1226 } 1227 1228 void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT 1229 absl::StrAppendFormat(out, "%d", i); 1230 } 1231 1232 void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i, 1233 const std::string& s, 1234 int64_t i64) { // NOLINT 1235 absl::StrAppendFormat(out, "%d %s %d", i, s, i64); 1236 }